一个棘手的OOP问题,我从来没有想过
A tricky OOP problem I never got my head around
假设我有两个.cpp文件:橙子.cpp和篮子.cpp。他们分别有orange
类和basket
类。我的main
程序生成许多baskets
进而产生许多oranges
。所以基本上,main
将有许多Baskets
对象;baskets
将有许多Oranges
的对象.如果我在orange
中有一个函数需要知道篮子的颜色,我将如何找到篮子的颜色?
橘子.cpp
class oranges
{
void whichColorBasket()
{
// get the color of the basket the orange is in...?
}
}
篮子.cpp
class basket
{
int color;
void basket()
{
for(int i = 0; i < 10; i++)
oranges *o = new oranges;
}
}
我知道我的语法可能并不完美,但是我将如何从orange
中的函数访问basket
的数据成员(orange
是由basket
创建的对象)。
发送颜色参数不是一个选项,因为orange
太多,并且basket
的颜色可能会在运行时更改。
我在某处读到静态函数可以解决问题,但它们只有在同一个.cpp文件中时才有效。
那么,我该怎么办?
静态函数几乎肯定不是这里的答案。
您可能需要将对"父"Basket
对象的引用传递给Oranges
对象,然后它可以查询该对象以查找颜色。
例如:
class Basket
{
public:
void Basket() {
Oranges *o = new Oranges(*this);
}
color getColor() const { ... }
};
class Oranges
{
private:
const Basket &myBasket;
public:
Oranges(const Basket &b) : myBasket(b) {} // Store reference
color getColor() const { return myBasket.getColor(); } // Interrogate my basket
};
是使用指针还是引用将取决于Oranges
是否可以在 Basket
s 之间移动。
你需要一个橙色的引用,指向橙色所在的篮子
class oranges{
basket* b;
int whichColorBasket() {
return b->color;
}
}
class basket{
int color;
void basket(){
for(int i=0;i<10;i++){
oranges *o=new oranges;
o->b = &this;
}
}
}
我在这里忽略了内存泄漏
您需要以某种方式将橙子绑定到它们所属的篮子 - 例如,通过将指针传递给篮子。如何做到这一点将取决于橙子在其生命周期中是否可以改变它们与背胶的结合,以及是否可以在它中的所有橙子被销毁之前销毁背胶。
假设橙子永远不会超过篮子,也永远不会改变篮子,你这样做:
class oranges{
public:
oranges( backet* object ) { belongsTo = object; }
void whichColorBasket() {
here get belongsTo->color;
}
private:
backet* belongsTo;
};
class basket{
int color;
void basket(){
for(int i=0;i<10;i++)
oranges *o=new oranges( this ); //pass "current object"
}
};
您的oranges
对象应该有一个实例变量basket
表示它所在的篮子。添加一个方法putInBasket
,该方法获取一个篮子并将变量设置为它所在的篮子。然后橙色查看whichColorBasket
方法中的变量。如果basket
NULL
它不在篮子里。
但是,这不是最好的设计,因为它提供了不一致的可能性。篮子可能认为它有一个橙子,但橙子的basket
指针可能指向不同的篮子。orange
真的应该知道它所在的篮子的颜色吗?用例是什么?如果你只处理篮子,并且你有一个橙子,也许篮子应该有一个isOrangeHere
的方法,它告诉你是否有一个给定的橙子在那里。您在所有篮子上调用它,然后取返回 true 的篮子的颜色。
简单的答案是你没有。 如果有必要,有某处设计中存在问题:什么样的橙色会知道它在什么篮子里吗? 如果橙色不在一篮子?
如果您需要以某种方式支持这一点,"适当的"解决方案将是类似于观察者模式的东西;你水果将是其容器的观察者;当您将水果放入容器中,容器将注册到水果,当你把水果拿出来时,容器会取消注册。 然后,客户可以向水果询问他们当前的水果容器,随便问。
向 Orange 添加一个属性,其中包含对父篮子的引用。在将橙子添加到篮子的方法中,还将父项设置为篮子。
class oranges{
basket* basket;
void oranged(basket* bask)
{
basket = bask;
}
int whichColorBasket() {
return basket->color;
}
}
class basket{
int color;
void basket(){
for(int i=0;i<10;i++)
oranges *o=new oranges(&this);
}
}
此语法可能是错误的,但这是通常的做法。
由于您正在使用C++因此请在橙子中使用指针。 int *basket_color;
然后只需为它分配篮子颜色的地址basket_color = &color
避免耦合的方法是询问每个篮子是否包含特定的橙色。如果是,请检查其颜色。
为什么橙色应该关心篮子的颜色?另一个篮子里的苹果呢?他们也感兴趣吗?
您的oranges
类可以有一个引用包含它的篮子的 basket
成员变量。然后,当一个oranges
对象想知道它所包含的篮子的颜色时,它只是调用得到myBasket.color
的值。
oranges
构造函数必须初始化此成员变量,因此它需要一个basket
参数。
编辑:完全重做了这个解决方案,因为我错过了一个关键约束。
另一种可能的方法是将成员变量添加到orange
类中,如下所示:
class oranges
{
private:
int m_nBasketID;
public:
oranges(int nID = 0)
{
m_nBasketID = nID;
}
void whichColorBasket()
{
return gBasketList[m_nBasketID].color;
}
}
并在basket
类中创建oranges
时设置值,如下所示:
class basket
{
static unsigned int nBasketID;
public:
int color;
void basket()
{
//First basket will have ID = 1 because
//0 is reserved for unknown/uninitialized state.
nBasketID++;
for(int i=0;i<10;i++)
oranges *o=new oranges(nBasketID);
gBasketList.push_back(*this);
}
其他修改如下:
unsigned int basket::nBasketID = 0;
std::vector<basket> gBasketList;
我在这里做了几个假设:
- 有一个已知值(如零)可用于表示未知/未初始化的颜色状态。此值可以在
oranges
的构造函数中使用默认值。 oranges
创建后不会切换篮子。如果需要解决此用例,则可以从原始basket
中删除orange
并向目标basekt
添加新或提供成员函数来处理这种情况等。
- 警告处理为错误这里有什么问题
- 最小硬币更换问题(自上而下方法)
- 为"adjacent"变量赋值时出现问题
- 我的神经网络不起作用 [XOR 问题]
- 在Ubuntu 16.04上安装Cilk时出现问题
- C++我的数学有什么问题,为什么我的代码不能正确循环
- 编译包含字符串的代码时遇到问题
- Project Euler问题4的错误解决方案
- 问题:什么是QAbstractItemView::NoEditTriggers的反面
- 在编译C++代码(具有dlib和opencv)到WASM时面临问题
- 在进程中对同一管道进行读取和写入时C++管道出现问题
- 静态数据成员的问题-修复链接错误会导致编译器错误
- C++ 雷神库 - 使用资源加载器类时出现问题(不命名类型)
- C OOP,读取文件的问题,EOF使用了两次,排行榜
- C++OOP注册回调函数(typedef问题)
- c++ OOP初学者,赋值问题
- 对复制构造函数的c++ OOP程序问题?继承
- 试图通过c++中的OOP正确理解关键字friend,编码问题
- 一个棘手的OOP问题,我从来没有想过
- OOP 设计问题:包含对象或容器中的责任