Круговая зависимость в MVC std :: shared_ptr

Я пытаюсь создать эту структуру MVC для моего проекта. Я впервые использую shared_ptr и weak_ptr и получаю много проблем, кроме циклической зависимости.

Модель наблюдаема. Вид — это Наблюдатель.

class Observable
{
std::set< std::shared_ptr<Observer> > observers;
public:
Observable( void );
void registerObserver( std::shared_ptr<Observer>  );
void removeObserver( std::shared_ptr<Observer> & );
void notifyObservers( void );
virtual ~Observable( void );
};class Observer
{
public:
Observer(void);
virtual void update() = 0;
virtual ~Observer(void);
};

class Model : public Observable
{
public:
Model(void);
void internalStateChange();
void funcForController();
int getSomethingForView() const;
~Model(void);
};

class View :
public Observer
{
std::weak_ptr<Model> model;
std::shared_ptr<Controller> controller;
public:
View( const std::shared_ptr<Model> &, const std::shared_ptr<Controller> & );
void update() override;
~View(void);
};

class Controller
{
std::shared_ptr<Model> model;
std::shared_ptr<View> view;
public:
Controller( std::shared_ptr<Model> & );
void changeHappened() const;
~Controller(void);
};

Мой вывод:
введите описание изображения здесь

Это показывает, что он где-то зависает, а затем примерно через 50 секунд завершается без других выходных данных.
введите описание изображения здесь

Контроллер не разрушается. 🙁

Как мне решить проблему?

3

Решение

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

Стандартная библиотека предоставляет программисту два разных класса (на самом деле, есть и другие умные указатели), а именно shared_ptr
а также weak_ptr, Общий указатель — это интеллектуальный указатель, сохраняющий указатель на объект и дополнительный указатель на общий счетчик ссылок. Каждый раз
сделана копия умного указателя счетчик ссылок автоматически
увеличивается на 1. Когда общий указатель уничтожается (или используется для ссылки на другой объект), счетчик ссылок для его объекта (или для
его предыдущий объект) уменьшается. Общие указатели построены из необработанного
указатели изначально имеют счетчик ссылок 1. Когда счетчик ссылок
достигает 0, указанный объект автоматически уничтожается. Слабые указатели
используется для того, чтобы разбить циклы в ссылочной структуре. Они могут быть
используется для получения общего указателя на тот же объект и проверки
объект уже был уничтожен. Они не включают подсчет ссылок.
Слабые указатели не предназначены для прямой разыменования (т.е. они не могут
использоваться для получения доступа к указанному объекту, так как это может привести к
аварии или случайное поведение; на самом деле они могут быть висящими указателями).

Что касается вашей конкретной проблемы, дело в следующем: у вас есть класс

class Controller
{
public:
std::shared_ptr<View> view;
};

и другой класс:

class View :
public Observer
{
public:
std::shared_ptr<Controller> controller;
};

и вы «назначаете» друг друга, т.е.

std::shared_ptr<Controller> c(new Controller);
std::shared_ptr<View> v(new View);
c->view = v;
v->controller = c;

когда c а также v выйти из области видимости, не будут вызываться деструкторы, так как есть еще одна ссылка для c (v->controller) и один для v (c->view).

Решение, в двух словах, заключается в замене одного из двух shared_ptrс weak_ptr, Конечно, вы не просто смотрите один из двух случайным образом, какой из них заменить, зависит от вашего дизайна, и вы вполне можете заменить оба из них (все зависит от семантики владения). Однако, если вы замените (хотя бы) один из них, проблема решена.

То же самое относится ко всем ссылочным циклам в вашем дизайне

0

Другие решения

Других решений пока нет …

По вопросам рекламы [email protected]