Шаблон наблюдателя c ++: необработанные указатели против shared_ptr? - PullRequest
1 голос
/ 01 ноября 2011

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

У меня есть класс докладчика (Model View Presenter), который реализует шаблон Observer, и он получает уведомление, когда происходят определенные события. Я написал универсальные классы Subject / Observer, от которых может наследовать любой класс. Метод обновления выглядит примерно так:

void MyPresenter::Update(Subject *subject)
{
    if(subject == myService_)
    {
        DoSomething();
    }
    else if(subject == myOtherService_)
    {
        DoSomethingElse();
    }

}

Это работало нормально, пока я не преобразовал myService_ (член класса MyPresenter) в std::shared_ptr. Теперь выражение (subject == myService_) больше не действует.

Я могу со временем преобразовать все в shared_ptr, но до тех пор есть ли простой способ для меня поддерживать как необработанные указатели, так и shared_ptr с помощью шаблона Observer? В идеале я хотел бы, чтобы шаблон наблюдателя был независим от реализации указателя наблюдателя, но, возможно, это невозможно. Как я могу это исправить?

UPDATE

Должен ли интерфейс Observer шаблона наблюдателя принимать общий указатель? Или лучше держать это в качестве сырых указателей? В настоящее время у меня есть:

class Subject;

class Observer
{
public:
    virtual ~Observer() {}
    virtual void Update(Subject *subject) = 0;

protected:
    Observer() {}
};

Ответы [ 3 ]

3 голосов
/ 01 ноября 2011

Чтобы это работало, myService_ и тема должны быть shared_ptr. В противном случае вы можете попытаться сравнить его, если subject и shared_ptr указывают на один и тот же объект.

  subject == myService_.get()

В противном случае попробуйте изменить все указатели на shared_ptr.

1 голос
/ 01 ноября 2011

Вы можете использовать shared_ptr элемент get, который возвращает необработанный указатель, который обертывает shared_ptr:

subject == myService_.get()

В общем, я бы не советовал вслепую конвертировать все необработанные указатели в shared_ptr s.Вы всегда должны думать о том, действительно ли окружающий объект владеет указанным объектом (и общая собственность все еще принадлежит).Иногда std::unique_ptr (хотя я не знаю, есть ли у tr1 это уже, в противном случае std::auto_ptr) - лучший выбор, если это строгое владение или просто необработанный указатель, если оно не принадлежит.

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

ПРИМЕЧАНИЕ: Я знаю, что это тот же ответ, что и уже существующий, но я отчаянно почувствовал необходимость против простого предложения shared_ptr повсеместно.

0 голосов
/ 05 июня 2013

Почему бы просто не позволить модели наследоваться от std::enable_shared_from_this.Если владение в любом случае является общим, то shared_from_this можно вернуть из (возможно, виртуального) метода модели.Остерегайтесь, однако, это имеет некоторые ограничения для конструктора модели.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...