2015-02-09 4 views
1

В моей системе GUI основной строительный блок - Container класс, который может быть нарисован . (= доступен для рисования). Однако Container сам по себе является «вид таблицы '- он содержит ячейки.Избегайте циклических зависимостей - потребность в взаимном сдерживании

Cell класс служит для макетирование. Количество ячеек, которые имеет контейнер, определяется количеством строк и столбцов. Cell объекты не видны.

И вот в чем проблема. Cell объекты не могут быть нарисованы - они содержат Container объектов, которые нарисованы по правилам, определенным в объекте Cell (выравнивание, отступы и т. Д.) При вызове cell.draw().

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

unique_ptr ошибка

/usr/include/c++/4.8/bits/unique_ptr.h:65:22: error: invalid application of ‘sizeof’ to incomplete type ‘Container’ 
    static_assert(sizeof(_Tp)>0, 

Container.hpp

#include <Cell.hpp> // Causes circular dependency 
class Cell; // Causes error: invalid application of ‘sizeof’ 

class Container 
{ 
// ... 
private: 
    std::vector<std::unique_ptr<Cell>> cells; 
// ... 
} 

Cell.hpp

#include <Container.hpp> //Causes circular dependency 
class Container; // Causes error: invalid application of ‘sizeof’ 
class Cell 
{ 
// ... 
private: 
    std::vector<std::unique_prt<Container>> subcontainers; 
// ... 
} 

Есть ли п ледяной путь, как решить ситуацию с помощью умных указателей (может быть, перепроектировав решение всей задачи), или мне нужно использовать исходные указатели здесь?

+2

Я действительно не понимаю, почему вы бы * имели такой цикл. Что такое * смысл * контейнера, содержащего ячейки, содержащие контейнеры? Даже если вы сделаете это на синтаксическом уровне *, это похоже на плохой дизайн * семантически * ... – DevSolar

+0

Вы считали, что используете ссылки вместо указателей? –

+0

Я думаю, что у вас должен быть один контейнер, содержащий контейнеры: D каждый контейнер имеет метод getCells() – Aitch

ответ

5

std::unique_ptr работает с объявленными типами вперед, но ему необходимо знать полный тип для вызова делетера.

Это укусит вас, если ваш класс использует созданный компилятором деструктор. Вы можете избавиться от проблемы, указав (возможно, пустой) настраиваемый деструктор для класса вне строки в исходном файле, где видны полное определение типа для удерживаемого .

Обратитесь к this answer за подробностями.

+0

Я определил деструктор (и даже экземпляр конструктора и оператора присваивания) в файле реализации. Однако проблема все еще существует. Любые идеи почему? – sjaustirni

+0

@Dundee Не обошлось без подробностей. Не могли бы вы разместить полное сообщение об ошибке, которое вы получаете от компилятора, включая все этапы стека создания экземпляра шаблона? – ComicSansMS

+0

Проблема была проблемой пространства имен. Я забыл включить форвардную декларацию в соответствующее пространство имен. Спасибо за помощь. Извиняюсь за мой идиотизм. – sjaustirni

0

Ответ: Я думаю, что у вас должен быть один контейнер, содержащий контейнеры: D каждый контейнер имеет метод getCells().

+1

Но сохраните их как умные указатели (общие или уникальные). Вы не хотите, чтобы меня все время копировали? – Aitch