一个棘手的 OOP 问题,我一直没有搞清楚

发布于 2024-11-08 14:30:26 字数 1032 浏览 0 评论 0原文

假设我有两个 .cpp 文件:oranges.cppbasket.cpp。它们分别具有类 orangebasket。我的main程序生成了许多篮子,这些篮子又生成了许多橙子。所以基本上,main 将有许多 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 的数据成员>orangeorange是由basket创建的对象)。

发送颜色参数不是一个选项,因为有太多橙色,并且篮子的颜色可能会在运行时发生变化。

我在某处读到静态函数可以解决这个问题,但它们只有在同一个 .cpp 文件中才有效。

那么,我该怎么办?

Say I have two .cpp files: oranges.cpp and basket.cpp. They have the classes orange and basket, respectively. My main program generates many baskets which in turn generate many oranges. So basically, main will have many objects of Baskets; and baskets will have many objects of Oranges. If I have a function in orange that needs to know the color of my basket, how would I go about finding the color of the basket?

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

I know my syntax may not be perfect but how would I access the datamember of basket from a function in orange (orange is an object created by basket).

Sending the color a parameter isn't an option as there are too many oranges and the color of the basket may change during runtime.

I read somewhere that static functions would do the trick, but they only work if they are in the same .cpp file.

So, what do I do?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(10

阪姬 2024-11-15 14:30:26

静态函数几乎肯定不是这里的答案。

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

Static functions are almost certainly not the answer here.

You would probably need to pass a reference to the "parent" Basket to the Oranges object, which it can then interrogate to find the colour.

For example:

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

};

Whether you use a pointer or a reference will depend on whether the Oranges can ever move between Baskets.

飘过的浮云 2024-11-15 14:30:26

你需要一个橙色的引用,指向橙色所在的篮子,

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

我在这里忽略内存泄漏

you'll need a reference in orange pointing to the basket the orange is in

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

I'm ignoring memory leaks here

瞳孔里扚悲伤 2024-11-15 14:30:26

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

假设橙子永远不会比篮子寿命长并且永远不会更换篮子,你可以这样做:

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

You need to somehow bind oranges to the basket they belong to - for example, by passing a pointer to the basket. How you do it will depend on whether oranges can change their binding to a backet during their lifetime and whether backet can be destroyed before all oranges in it are destroyed.

Assuming oranges never outlive the basket and never change the basket you do it this way:

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"
     }
 };
彼岸花似海 2024-11-15 14:30:26

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

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

Your oranges object should have an instance variable basket representing the basket it's in. Add a method putInBasket which takes a basket and sets the variable to the basket it's in. Then the orange looks at the variable in the whichColorBasket method. If basket is NULL it's not in a basket.

This isn't the best design, though, cause it provides a potential for inconsistency. A basket might think it has an orange, but the orange's basket pointer could point to a different basket. Should an orange really know the color of the basket it's in? What's the use case? If you're only handling baskets, and you have an orange, perhaps the basket should have a isOrangeHere method, which tells you whether a given orange is there. You call it on all the baskets, and then you take the color of the one that returns true.

贩梦商人 2024-11-15 14:30:26

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

如果您需要以某种方式支持这一点,“正确的”解决方案
类似于观察者模式;你的
水果将成为其容器的观察者;当你把
水果放入容器中,容器将向
水果,当你把水果拿出来时,容器就会
注销。然后客户可以向水果询问他们当前的情况
容器,并询问他们想要的任何内容。

The simple answer is that you don't. If you have to, there is
a problem in your design somewhere: what kind of orange would
know what basket it is in? And what if the orange isn't in
a basket?

If you need to support this in some way, the "proper" solution
would be something along the lines of the Observer pattern; your
fruit would be an observer of its container; when you put the
fruit into a container, the container would register with the
fruit, and when you took the fruit out, the container would
deregister. Clients could then ask the fruit for their current
container, and ask it whatever they want.

婴鹅 2024-11-15 14:30:26

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

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

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

Add a property to oranges that contains a reference to the parent basket. In the method for adding oranges to basket, also set the parent to the basket.

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

This syntax may be wrong but this is how its normally done.

后知后觉 2024-11-15 14:30:26

由于您使用的是 C++,因此请在橙色中使用指针。 int *basket_color; 然后将其分配给篮子颜色的地址 basket_color = &color

Since you're using C++ use a pointer in your oranges. int *basket_color; then just assign it the address of the baskets color basket_color = &color

孤千羽 2024-11-15 14:30:26

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

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

The way to avoid the coupling is to ask each basket if it contains a specific orange. If it does, check its color.

Why should the orange care about the basket's color? What about the apples in the other basket? Are they interested too?

少钕鈤記 2024-11-15 14:30:26

您的“oranges”类可以有一个“basket”成员变量,该变量引用包含它的篮子。然后,当一个 Oranges 对象想要知道其包含的篮子的颜色时,它只需调用 get myBasket.color 的值即可。

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

Your oranges class could have a basket member variable that references the basket that contains it. Then, when an oranges object wants to know the colour of its containing basket it just calls gets the value of myBasket.color.

The oranges constructor would have to initialise this member variable, so it would need a basket parameter.

空宴 2024-11-15 14:30:26

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

另一种可能的方法是向 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;

我在这里做了几个假设:

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

EDIT: Completely redid this solution as I had missed on a key constraint.

Another possible way would be to add a member variable to the orange class like so:

class oranges
{
    private:
    int m_nBasketID;

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

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

And to set the value while creating the oranges in the basket class, like so:

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

Additional modifications are as follows:

unsigned int basket::nBasketID = 0;
std::vector<basket> gBasketList;

I've made a couple of assumptions here:

  1. There is a known value (such as zero) that can be used to represent an unknown/uninitialized colour state. This value can be used a default value in the constructor of oranges.
  2. The oranges do not switch baskets after creation. If this use-case needs to be addressed then may you could delete the orange from the original basket and add a new one to the destination basekt or provide a member function to handle this case etc.
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文