Сложная проблема ООП, я никогда не думал - PullRequest
10 голосов
/ 19 мая 2011

Допустим, у меня есть два .cpp файла: oranges.cpp и basket.cpp .У них есть классы orange и basket соответственно.Моя main программа генерирует много baskets, которые в свою очередь генерируют много oranges.Таким образом, в основном main будет иметь множество объектов Basketsbaskets будет иметь много объектов 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 ]

17 голосов
/ 19 мая 2011

Статические функции почти наверняка не ответ здесь.

Возможно, вам потребуется передать ссылку на «родительский» 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 с..

3 голосов
/ 19 мая 2011

вам понадобится ссылка оранжевого цвета, указывающая на корзину, в которой находится апельсин

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 голосов
/ 19 мая 2011

Вам нужно каким-то образом привязать апельсины к корзине, к которой они принадлежат - например, передав указатель на корзину. То, как вы это сделаете, будет зависеть от того, смогут ли апельсины изменить свою привязку к бэкету в течение своей жизни, и может ли бэкэт быть уничтожен до того, как все апельсины в нем будут уничтожены.

Предполагая, что апельсины никогда не переживают корзину и никогда не меняют корзину, вы делаете это следующим образом:

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 голосов
/ 19 мая 2011

Простой ответ - нет. Если вам нужно, есть проблема в вашем дизайне где-то: какой бы апельсин знаете, в какой корзине это находится? А что, если апельсин не в корзина?

Если вам нужно как-то поддержать это, «правильное» решение было бы что-то в соответствии с шаблоном Observer; ваш Фрукт был бы наблюдателем своего контейнера; когда вы положите фрукты в контейнер, контейнер будет регистрироваться с фрукты, и когда вы взяли фрукты, контейнер дерегистрировать. Клиенты могли тогда спросить фрукты для их текущего контейнер, и спросите, что они хотят.

2 голосов
/ 19 мая 2011

Добавить свойство в апельсины, которое содержит ссылку на родительскую корзину. В методе добавления апельсинов в корзину также установите родительский элемент в корзину.

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

Этот синтаксис может быть неправильным, но это обычно так.

2 голосов
/ 19 мая 2011

Ваш oranges объект должен иметь переменную экземпляра basket, представляющую корзину, в которой он находится. Добавьте метод putInBasket, который берет корзину и устанавливает переменную для корзины, в которой он находится. Затем оранжевый смотрит на переменную в метод whichColorBasket. Если basket равно NULL, его нет в корзине.

Тем не менее, это не лучший дизайн, поскольку он может привести к несогласованности. Корзина могла бы думать, что у нее есть апельсин, но указатель basket апельсина может указывать на другую корзину. Должен ли orange действительно знать цвет корзины, в которой он находится? Какой вариант использования? Если вы работаете только с корзинами и у вас есть апельсин, возможно, корзина должна иметь метод isOrangeHere, который сообщает вам, есть ли данный апельсин. Вы называете это на всех корзинах, а затем берете цвет того, который возвращает истину.

1 голос
/ 19 мая 2011

Способ избежать связывания - спросить каждую корзину, содержит ли она определенный оранжевый цвет. Если это так, проверьте его цвет.

Почему оранжевый должен заботиться о цвете корзины? А как насчет яблок в другой корзине? Они тоже заинтересованы?

1 голос
/ 19 мая 2011

Поскольку вы используете C ++, используйте указатель в ваших апельсинах.int *basket_color; затем просто назначьте ему адрес корзины цвета basket_color = &color

0 голосов
/ 19 мая 2011

РЕДАКТИРОВАТЬ: полностью переделал это решение, как я пропустил из-за ключевого ограничения.

Другим возможным способом было бы добавить переменную-член в класс 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. oranges не переключать корзины после создания . Если необходимо рассмотреть этот вариант использования, тогда вы можете удалить orange из исходного basket и добавить новый к месту назначения basekt или предоставить функцию-член для обработки этого случая и т. Д.
0 голосов
/ 19 мая 2011

Ваш класс oranges может иметь переменную-член basket, которая ссылается на корзину, в которой он содержится.Затем, когда объект oranges хочет узнать цвет своей содержащей его корзины, он просто вызывает, получает значение myBasket.color.

. Конструктор oranges должен инициализировать эту переменную-член, поэтому он будетнужен параметр basket.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...