Цитата(Idle @ Aug 15 2012, 22:57)

не использую си++, использую си, абстрактные типы данных через incomplete structure pointer-ы собственно вопрос, как правильно организовывать взаимодействие объектов, когда "вложенный объект" должен вызывать родителя родителя?
Нет ничего нового под солнцем

- практически все механизмы взаимодействия объектов уже открыты и где-то используются. Общение дочерних объектов с родительскими широко применяется в библиотеках классов GUI, например, таких как MFC или VCL.
Для того, чтобы организовать такое взаимодействие, очень желательно породить (как производные классы) все объекты, участвующие в родственных отношениях, от одного (супер)базового класса, хотя бы и формального (т.е. не имеющего собственных функций), просто для того, чтобы указатель любого участника "большой семьи" приводился к указателю одного и того же типа типа автоматически.
А для большего удобства в этом же супербазовом классе (superbase) лучше сразу создать переменную (указатель), в которой каждый объект будет помнить указатель на своего родителя (естественно, приведенного к типу superbase*). Например, классу superbase достаточно выглядеть так:
class superbase
{
Piblic:
superbase *myParent;
superbase(superbase *parent) { myParent = parent; }
};
В принципе родительские и дочерние объекты могут быть совершенно разными по своим структурам классами, их переписывать не надо, а достаточно ОБЪЕДИНИТЬ с классом superbase! Скажем были раньше у вас три класса Object1, Object2 и Object3, на основе которых вы порождали состоящие в родстве объекты: бабушку, мать и дочь. А теперь создайте для них новую тройку объектов:
class Family1 : public superbase, public Object1 // это для бабушки
{
Family1(superbase *parent, ...) : superbase(parent), Object1(...) { ... }
};
class Family2 : public superbase, public Object2 // это для матери
{
Family2(superbase *parent, ...) : superbase(parent), Object2(...) { ... }
};
class Family3 : public superbase, public Object3 // это для дочери
{
Family3(superbase *parent, ...) : superbase(parent), Object3(...) { ... }
};
Мы видим, что новые семейные классы (Family1, Family2, Family3) функционально тождественны старым индивидуальным классам (Object1, Object2 и Object3) соответственно. А троеточием я обозначила список тех параметров, которыми инициируются старые классы. Фактически, семейные классы отличаются от старых только одним - дополнительным параметром parent и способностью его запоминать в своей переменной myParent.
Процесс рождения чада сопровождается тем, что родитель при вызове конструктора сообщает, помимо прочего, указатель на самого себя (this), чтобы ребенок мог его запомнить:
new Family3 child1( this, ...);
Теперь дитя child1 всегда будет помнить свою маму в child1.myParent. Ну а самый старый патриарх, которого порождает уже не семья, а само приложение, инициируется с парамером NULL вместо указателя на parent. В смысле, что родителя у него среди семьи нет.
Весь смак в том, что теперь любой потомок будет способным не только узнать адрес своего родителя по myParent, но и обратиться к нему (вызвать по этому поинтеру какую-нибудь родительскую функцию). А если возникнут затруднения с доступом, то поинтер myParent всегда можно привести к полному указателю на родительский класс динамически.
Точно так же можно достучаться до предка в любом поколении через цепочку myParent->myParent->...->myParent. И если на каком-то этапе очередной myParent окажется равным NULL, то это родоначальник династии, и глубже опускаться по генеалогическому древу не надо. Например, послание собственной бабушке будет выглядеть так:
myParent->myParent->Message = "Здравствуй, бабуля!";
А послание прадедушке так:
myParent->myParent->myParent->Message = "Привет, прадед!";
Если последнее поколение - помидор, а предок всего сущего - admin, то жалобу ему помидор может оправить, либо вызвав myParent от myParent столько раз, каким по счету поколением от него является помидор. А если он точно этого не знает, то легко может узнать, проследив эту цепочку до нуля:
superbase *Admin = myParent;
while(Admin->myParent != NULL) Admin = Admin->myParent; // спускаем админа вглубь, пока не достигнем сироты
Admin->Message = "Караул! Загниваю!";