Доступ к членам содержащихся объектов из содержащихся объектов - PullRequest
0 голосов
/ 08 марта 2011

Если у меня есть несколько уровней содержания объекта (один объект определяет и создает экземпляр другого объекта, который определяет и создает экземпляр другого объекта ..), возможно ли получить доступ к верхнему, содержащему - объекту переменные и функции , пожалуйста?

Пример:

    class CObjectOne
    {
    public:
       CObjectOne::CObjectOne() { Create(); };

       void Create();

       std::vector<ObjectTwo>vObejctsTwo;
       int nVariableOne;
    }
    bool CObjectOne::Create()
    {
       CObjectTwo ObjectTwo(this);
       vObjectsTwo.push_back(ObjectTwo);
    }

    class CObjectTwo
    {
     public:
       CObjectTwo::CObjectTwo(CObjectOne* pObject)
       {
        pObjectOne = pObject;
        Create();
       };

       void Create();
       CObjectOne* GetObjectOne(){return pObjectOne;};

       std::vector<CObjectTrhee>vObjectsTrhee;
       CObjectOne* pObjectOne;
       int nVariableTwo;
    }
    bool CObjectTwo::Create()
    {
       CObjectThree ObjectThree(this);
       vObjectsThree.push_back(ObjectThree);
    }

    class CObjectThree
    {
     public:
       CObjectThree::CObjectThree(CObjectTwo* pObject)
       {
        pObjectTwo = pObject;
        Create();
       };

       void Create();
       CObjectTwo* GetObjectTwo(){return pObjectTwo;};

       std::vector<CObjectsFour>vObjectsFour;
       CObjectTwo* pObjectTwo;
       int nVariableThree;
    }
    bool CObjectThree::Create()
    {
       CObjectFour ObjectFour(this);
       vObjectsFour.push_back(ObjectFour);
    }

main()
{
    CObjectOne myObject1;
}

Скажите, что из CObjectThree мне нужно получить доступ к nVariableOne в CObjectOne . Я хотел бы сделать это следующим образом:

int nValue = vObjectThree[index].GetObjectTwo()->GetObjectOne()->nVariable1;

Однако после компиляции и запуска приложения я получаю Ошибка нарушения доступа к памяти .

  • Что не так с кодом выше (это пример, и может содержать орфографические ошибки)?
  • Нужно ли создавать объекты динамически вместо статически ?
  • Есть ли другой способ получения переменных, хранящихся в , содержащих объекты, из , содержащих объектов?

Ответы [ 3 ]

1 голос
/ 08 марта 2011

Когда вы передаете указатель, который указывает обратно на объект контейнера, этот указатель иногда называется обратным указателем . Я вижу, что этот метод все время используется в библиотеках с графическим интерфейсом, где виджет может нуждаться в доступе к своему родительскому виджету.

При этом вы должны спросить себя, есть ли лучший дизайн, который не включает круговые зависимости (круговой в том смысле, что контейнер зависит от контактирующего лица, а контактируемый - от контейнера).

Вы не строго должны создавать объекты динамически, чтобы техника обратного указателя работала. Вы всегда можете взять адрес выделенного стека (или статически выделенного) объекта. Пока сохраняется жизнь этого объекта, пока другие используют указатели на него. Но на практике этот метод обычно используется с динамически создаваемыми объектами.

Обратите внимание, что вы также можете использовать обратную ссылку вместо обратного указателя.


Я думаю, я знаю, что вызывает ваши ошибки сегментации. Когда ваши векторы перераспределяют свою память (в результате увеличения их размера), адреса старых векторных элементов становятся недействительными. Но дети (и внуки) этих объектов по-прежнему хранят старые адреса в своих указателях!

Чтобы сработал обратный указатель, вам нужно будет динамически распределять каждый объект и сохранять его указатели в векторах. Это сделает управление памятью намного более запутанным, поэтому вы можете использовать умные указатели или boost :: ptr_containers.


Увидев комментарий, который вы сделали в другом ответе, теперь у меня есть лучшее представление о том, чего вы пытаетесь достичь. Вы должны исследовать родовое дерево структуры и составной шаблон . Составной шаблон обычно используется в приведенном выше примере с виджетом.

1 голос
/ 08 марта 2011

Может быть, все ваши объекты могут наследовать от общего интерфейса, например:

class MyObject
{
public:
    virtual int getData() = 0;
}

И после того, как вы можете использовать std :: tree из библиотеки stl для построения вашей структуры.

0 голосов
/ 28 сентября 2015

Как сказал Эмиль, ошибка сегментации вызвана перераспределением. Точно говоря, когда локальный стек объектов указатель «this» был передан для создания другого объекта, который затем копируется в векторный контейнер. Затем завершается функция Create (), объект стекового фрейма перестает существовать и указатель в контейнере становится недействительным.

...