//a1 Должен инициализироваться указателем на b1
//b1 Должен инициализироваться указателем на a1
---------------------------------------------------
то есть должно получиться что-то похожее на
A a1(&b1);
B b1(&a1);
Ясно что можно инициализировать ручками во время выполнения программы, но хочется чтобы сам компилятор выполнил связывание...
Адрес экземпляра класса B неизвестен до его конструирования на стеке, как и адрес экземпляра класса А. Придется ручками. Иначе,наверное, никак. Единственное, что можно b1={&a1};
Успехов.
М>A a1; М>B b1;
М>//a1 Должен инициализироваться указателем на b1 М>//b1 Должен инициализироваться указателем на a1 М>--------------------------------------------------- М>то есть должно получиться что-то похожее на М>A a1(&b1); М>B b1(&a1); М>Ясно что можно инициализировать ручками во время выполнения программы, но хочется чтобы сам компилятор выполнил связывание...
М>Михаил
Здравствуйте, Михаил1981, Вы писали:
М>Ясно что можно инициализировать ручками во время выполнения программы, но хочется чтобы сам компилятор выполнил связывание...
Обычный применяемый в таких случаях ход — завести для этих двух классов структуру, их содержащую и в конструкторе проставляющая ссылки друг на друга:
struct AB {
A a;
B b;
AB () { a.p = &b; b.p = &a; }
};
void f () {
AB ab; // указатели проинициализируются...
A& a = ab.a;
B& b = ab.b;
// дальше пишешь то, что хотел написать.
}
Если в конструкторах A и B вызываются виртуальные методы друг друга, можно схлопотать pure virtual call.
Структуру можно сделать локальной.
Здравствуйте, Klestov, Вы писали:
K>Объекты класса A должна инициализироватся не в конструкторе — назовем ее отложенная инициализация.
Это не совсем интересно, поскольку рекомендуется как можно больше инициализации переносить в конструктор, усиляя таким образом инвариант класса. Например, в приведенном выше примере объекты типов A и B могли содержать константные указатели или ссылки друг на друга, что требовало их инициалиции именно в констукторе, а точнее в списке инициализации.
Если классы так уж тесно связаны, то можно
вложить один из них в другой... вот так например:
struct A;
struct B
{
B(A* pa): pA(pa){}
A* pA;
void f() {cout << "F" << endl; }
};
struct A
{
A () : b(this){} // сдесь может ругаться.operator B& () { return b; }
B b;
void g() {cout << "G" << endl; }
};
int _tmain(int argc, _TCHAR* argv[])
{
A a;
B& b = a; // B как бы не самостоятельный... ну и что?
// Важно то, что они инициализируются одновременно.
// т.е. когда доступен а тогда достепен и в.
b.f(); // ((B&)a).f();
a.g();
getch();
return 0;
}
Здравствуйте, Anton V. Kolotaev, Вы писали:
AVK>Здравствуйте, Klestov, Вы писали:
K>>Объекты класса A должна инициализироватся не в конструкторе — назовем ее отложенная инициализация.
AVK>Это не совсем интересно, поскольку рекомендуется как можно больше инициализации переносить в конструктор, усиляя таким образом инвариант класса. Например, в приведенном выше примере объекты типов A и B могли содержать константные указатели или ссылки друг на друга, что требовало их инициалиции именно в констукторе, а точнее в списке инициализации.
Интересно — не интересно это не технические понятия НО — исходя из всего сказанного на тему у меня возникает ВОПРОС если классы так тесно связаны не я вляется ли это признаком декомпозиции некоего класса описавающего сущность и не есть ли эта ситуация ошибкой проектирования !?
Может не следует идти на поводу о 2-х классах а стоит перепроектировать систему т.к. в ней явно прослеживается концептуальный дефект ?
Здравствуйте, Klestov, Вы писали:
K>Интересно — не интересно это не технические понятия
Ну так мы и нетехнари.
K>НО — исходя из всего сказанного на тему у меня возникает ВОПРОС если классы так тесно связаны не я вляется ли это признаком декомпозиции некоего класса описавающего сущность и не есть ли эта ситуация ошибкой проектирования !? K>Может не следует идти на поводу о 2-х классах а стоит перепроектировать систему т.к. в ней явно прослеживается концептуальный дефект ?
Я не думаю, что появление перекрестных ссылок — признак плохого дизайна. Когда я старался придерживаться "чистого" ООП, они иногда возникали, и я не могу сказать, что это плохо.
Что плохого в следующем коде? (за исключением возможности схватить pure virtual call)
struct IA
{
//....
};
struct IB
{
//....
};
class CA : public IA
{
IB &_ib;
public:
CA (IB &ib) : _ib(ib) {}
// ....
};
class CB : public IB
{
IA &_ia;
public:
CB (IA &ia) : _ia(ia) {}
// ....
};
class Facade
{
CA _ca;
CB _cb;
public:
Facade () : _ca (_cb), _cb (_ca) {}
//...
};
Интерфейсы IA и IB независимы. То, что CA выражен в терминах IB, CB не знает. Наоборот тоже верно. CA и CB тоже ничего друг о друге не знают. Что плохого в том, что они оказались подходящими кандидатами для удовлетворения функциональности друг друга?
Здравствуйте, Anton V. Kolotaev, Вы писали:
AVK>Ну так мы и нетехнари.
Да да — мы творческая интеллигенция, а программирование это всего лиш искуство например как фигурная лепка из пластилина в слепую для детей с задержанным развитием речи
AVK>Что плохого в следующем коде? (за исключением возможности схватить pure virtual call)
Этот присер не показателен и только косвенно касается данной темы
Здравствуйте, Anton V. Kolotaev, Вы писали:
AVK>Я привел пример естественного дизайна, при котором возникают перекрестные ссылки. Обвинение в плохом дизайне несостоятельно.
Может быть я не достаточно ясно выразил свою мысль в предыдущих постах но мой замечание относилось не только в отношении перекрестной ссылки но и того что при этом функциональность объектов тесно связана – возможно требуется создать агрегирующий класс или просто объединить классы в один.
Нулями закидать много ума не надо. Сначала попробуй просто указать человеку на правила форума... А вот если не понимает — тогда конечно. Но тут я с тобой согласен — есть за что.
WH>Ноль за оверквотинг.
WH>ЗЫ Всех оверквотеров нулями закидаю. Призывю присоединиться!