2015-11-06 3 views
3

Следующий класс наблюдателя регистрирует функцию обратного вызова с субъектом по вызову attach, когда его ctor выполняет. Я хотел бы, чтобы dtor наблюдателя отменил регистрацию функции обратного вызова.Передача shared_ptr в std :: function (функция-член)

Как передать тот же указатель на detach, как я сделал, до attach, чтобы субъект мог удалить его из списка наблюдателей?

Я думаю, что я должен хранить shared_ptr к this, но я не уверен, как я получаю от этого к shared_ptr функции члена callback.

Может ли кто-нибудь помочь?

Observer::Observer(Subject& subject) : m_subject(subject), 
{ 
    m_subject.attach("cmd", std::make_shared<std::function<void()>>(std::bind(&Observer::callback, this))); 
} 

Observer::~Observer() 
{ 
    // I tried this initially but realised that the pointer below 
    // is different to the one passed to `attach` from the ctor. 

    m_subject.detach("cmd", std::make_shared<std::function<void()>>(std::bind(&Observer::callback, this))); 
} 

void Observer::callback() 
{ 
    // do some stuff 
} 

attach и detach объявлены следующим образом:

void Subject::attach(const std::string& command, const std::shared_ptr<std::function<void()>>& callback); 

void Subject::detach(const std::string& command, const std::shared_ptr<std::function<void()>>& callback); 
+0

Есть ли особая причина, по которой вы не используете 'const Subject &' в своем списке параметров ctor? Я спрашиваю, потому что вы, очевидно, копируете-копируете копию в любом случае. – Superlokkus

+0

@Superlokkus Потому что 'Subject :: attach' не' const'. – ksl

+0

Так что 'm_subject' является' Subject & ', тоже? В противном случае вы создаете копию своего предмета, а затем это не имеет значения. – Superlokkus

ответ

1

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

Как это:

class Observer { 
    //Other Stuff here 

private: 
    std::shared_ptr<std::function<void()>> callback_ptr; 
}; 

Observer::Observer(Subject& subject) : 
m_subject(subject), 
callback_ptr(std::make_shared<std::function<void()>>(std::bind(&Observer::callback, this)) 
{ 
    m_subject.attach("cmd", std::make_shared<std::function<void()>>(std::bind(&Observer::callback, this))); 
} 

Observer::~Observer() 
{ 
    m_subject.detach("cmd", callback_ptr)); 
} 

Стоит отметить, что, как @dkg также отметил, make_shared же всегда возвращает новый shared_ptr каждый раз, как это называется, потому что цель состоит в том, чтобы «создать новый объект с следующие параметры и вернуть shared_ptr ". Примерно эквивалентен shared_ptr(new std::function<void()> (std::bind(&Observer::callback, this)). Причина, по которой есть дополнительная функция make_shared, состоит в том, чтобы минимизировать выделение и гарантировать безопасность исключений в длинном выражении. Если вы просто хотите поделиться одним объектом, то просто распространяйте копию вашего shared_ptr.

+1

Это решение. В противном случае в dtor создается новый экземпляр с использованием 'make_shared', а переданный общий указатель указывает на этот новый экземпляр вместо созданного в ctor ... –

1

Каждый раз, когда вы вызываете std::make_shared, он выделяет и создает для вас новый объект.

В вашем коде вы вызываете его дважды, тогда у вас есть два экземпляра вашего объекта, которые не совпадают.

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

Смежные вопросы