一个棘手的OOP问题我从来没有理解过

时间:2011-05-19 14:08:06

标签: c++ oop visual-c++

假设我有两个 .cpp 文件: oranges.cpp basket.cpp 。他们分别有orangebasket类。我的main程序会生成许多baskets,而后者会生成许多oranges。基本上,main将有许多Baskets的对象;并且baskets将有许多Oranges的对象。如果我在orange中有一个需要知道我的篮子颜色的功能,我该如何找到篮子的颜色?

orangle.cpp

class oranges
{
    void whichColorBasket()
    {
        // get the color of the basket the orange is in...?
    }
}

basket.cpp

class basket
{
    int color;

    void basket()
    {
        for(int i = 0; i < 10; i++)              
            oranges *o = new oranges;
    }
}

我知道我的语法可能不完美,但我如何从basket中的函数访问orange的数据库(orange是由basket创建的对象)

发送颜色参数不是一个选项,因为orange太多,basket的颜色可能会在运行时发生变化。

我在某处读过静态函数可以解决这个问题,但只有当它们位于相同的 .cpp 文件中时才能工作。

那么,我该怎么办?

10 个答案:

答案 0 :(得分:17)

静态功能几乎肯定是这里的答案。

您可能需要将对“父”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之间移动。

答案 1 :(得分:3)

你需要以某种方式将橙子绑定到他们所属的篮子 - 例如,通过将指针传递到篮子。你如何做到这一点将取决于橙子是否可以在其生命周期内改变它们与背心的结合,以及是否可以在其中的所有橙子被破坏之前销毁它们。

假设橘子永远不会比篮子更活跃而且永远不会改变篮子你就这样做了:

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"
     }
 };

答案 2 :(得分:3)

你需要一个橙色的参考指向橙色的篮子

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;
         }
     } 
}

我忽略了内存泄漏

答案 3 :(得分:2)

你的oranges对象应该有一个实例变量basket来代表它所在的篮子。添加一个方法putInBasket,它取一个篮子并将变量设置为它所在的篮子。然后orange查看whichColorBasket方法中的变量。如果basketNULL,则不在一个篮子里。

这不是最好的设计,因为它提供了不一致的可能性。篮子可能认为它有橙色,但橙色的basket指针可能指向不同的篮子。 orange真的应该知道篮子的颜色吗?用例是什么?如果你只是处理篮子,并且你有橙色,那么篮子应该有一个isOrangeHere方法,告诉你是否有一个给定的橙色。你在所有篮子上调用它,然后你获取返回true的颜色。

答案 4 :(得分:2)

向包含对父篮子的引用的橙子添加属性。在将橙子添加到篮子的方法中,也将父级设置为篮子。

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);
     }         
}

这种语法可能有误,但这是通常的做法。

答案 5 :(得分:2)

简单的答案是你没有。如果必须,那就有 你的设计中出现问题:橙子会是什么样的 知道它在哪个篮子里?如果橙子不在里面怎么办? 一篮子?

如果您需要以某种方式支持这一点,那么“正确”的解决方案 将是观察者模式的一部分;您的 水果将成为其容器的观察者;当你把它 将水果放入容器中,容器会注册 水果,当你拿出水果时,容器会 注销。然后客户可以向水果询问他们的电流 容器,并随意问它。

答案 6 :(得分:1)

因为你正在使用C ++,所以在你的橘子中使用指针。 int *basket_color;然后只需为其指定颜色basket_color = &color

的地址

答案 7 :(得分:1)

避免耦合的方法是询问每个篮子是否包含特定的橙色。如果是,请检查其颜色。

橘子为什么要关心篮子的颜色?那另一个篮子里的苹果怎么样?他们也有兴趣吗?

答案 8 :(得分:0)

您的oranges类可能有basket成员变量,该变量引用包含它的购物篮。然后,当oranges对象想要知道其包含篮子的颜色时,它只是调用得到值myBasket.color

oranges构造函数必须初始化此成员变量,因此需要basket参数。

答案 9 :(得分:0)

编辑:完全重写了这个解决方案,因为我错过了一个关键约束。

另一种可能的方法是将成员变量添加到orange类,如下所示:

class oranges
{
    private:
    int m_nBasketID;

    public:
    oranges(int nID = 0)
    {
       m_nBasketID = nID;
    }

    void whichColorBasket() 
    {
        return gBasketList[m_nBasketID].color;
    }
}

要在oranges类中创建basket时设置值,请执行以下操作:

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;

我在这里做了几个假设:

  1. 可以使用已知值(例如零)来表示未知/未初始化的颜色状态。此值可以在oranges
  2. 的构造函数中使用默认值
  3. 创建后,oranges不会切换篮子。如果需要解决此用例,那么您可以从原始orange中删除basket并将新的basekt添加到目标{{1}}或提供成员函数来处理此案例等