Сложная проблема ООП: у меня никогда не было головы
Скажем, у меня есть два файла .cpp: oranges.cpp и basket.cpp. Они имеют классы orange
и basket
, соответственно. Моя программа 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;
}
}
Я знаю, что мой синтаксис может быть не идеальным, но как мне получить доступ к datamember из basket
из функции в orange
(orange
- это объект, созданный basket
).
Отправка цвета параметра не является параметром, так как слишком много orange
, а цвет basket
может меняться во время выполнения.
Я где-то читал, что статические функции будут делать трюк, но они работают только в том случае, если они находятся в одном файле .cpp.
Итак, что мне делать?
Ответы
Ответ 1
Статические функции почти наверняка не здесь.
Вам, вероятно, потребуется передать ссылку на "родительский" 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.
Ответ 2
Вам нужно как-то связать апельсины с корзиной, к которой они принадлежат, например, передав указатель на корзину. Как вы это сделаете, будет зависеть от того, могут ли апельсины изменить свою привязку к backet во время их жизни и может ли быть уничтожена спина до того, как все апельсины в ней будут уничтожены.
Предполагая, что апельсины никогда не ожидают корзины и никогда не меняют корзину, вы делаете это так:
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"
}
};
Ответ 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;
}
}
}
Я игнорирую утечку памяти здесь
Ответ 4
В вашем объекте oranges
должна быть переменная экземпляра basket
, представляющая ее корзину. Добавьте метод putInBasket
, который берет корзину и устанавливает переменную в ее корзину. Затем оранжевый смотрит на переменную в метод whichColorBasket
. Если basket
NULL
, это не в корзине.
Однако это не лучший дизайн, поскольку он создает потенциальную возможность для несогласованности. Корзина может подумать, что у нее оранжевый цвет, но оранжевый указатель basket
может указывать на другую корзину. Если orange
действительно знает цвет корзины? Какой прецедент? Если вы используете только корзины, и у вас есть оранжевый, возможно, корзина должна иметь метод isOrangeHere
, который говорит вам, есть ли данный оранжевый цвет. Вы вызываете его на всех корзинах, а затем вы берете цвет того, который возвращает true.
Ответ 5
Добавить свойство в апельсины, содержащее ссылку на родительскую корзину. В методе добавления апельсинов в корзину также установите родительский элемент в корзину.
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);
}
}
Этот синтаксис может быть неправильным, но это как обычно делается.
Ответ 6
Простой ответ заключается в том, что вы этого не делаете. Если вам нужно,
проблема в вашем дизайне где-то: какой апельсин
знаете, в какую корзину он? А что, если оранжевый не в
корзина?
Если вам нужно каким-то образом поддержать это, "правильное" решение
будет что-то вроде линии Наблюдателя; ваш
плод будет наблюдателем его контейнера; когда вы ставите
фрукты в контейнер, контейнер будет регистрироваться с помощью
фрукты, и когда вы вытащили плод, контейнер
дерегистрировать. Затем клиенты могли спросить о фруктах
контейнер, и спросите его, что они хотят.
Ответ 7
Поскольку вы используете С++, используйте указатель в ваших апельсинах. int *basket_color;
затем просто назначьте ему адрес цвета корзин basket_color = &color
Ответ 8
Способ избежать муфты - спросить каждую корзину, если она содержит оранжевый цвет. Если это так, проверьте его цвет.
Почему оранжевый уход за цветом корзины? А как насчет яблок в другой корзине? Они тоже заинтересованы?
Ответ 9
В вашем классе oranges
может быть переменная-член basket
, которая ссылается на содержащую ее корзину. Затем, когда объект oranges
хочет знать цвет его содержащей корзины, он просто вызывает значение myBasket.color
.
Конструктор oranges
должен будет инициализировать эту переменную-член, поэтому для этого потребуется параметр basket
.
Ответ 10
EDIT: полностью отменило это решение, поскольку я пропустил ограничение ключа.
Другим возможным способом было бы добавить переменную-член в класс 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;
Я сделал несколько предположений здесь:
- Существует известное значение (например, ноль), которое может использоваться для представления неизвестного/неинициализированного состояния цвета. Это значение может использоваться по умолчанию в конструкторе
oranges
.
-
oranges
не меняют корзины после создания. Если этот прецедент должен быть рассмотрен, вы можете удалить orange
из исходного basket
и добавить новый в пункт назначения basekt
или предоставить функцию-член для обработки этого случая и т.д.