Chcę zaimplementować menedżera, który przechowuje wywołania zwrotne do funkcji składowych klas polimorficznych za pomocą C++ 11. Problem polega na tym, że nie jestem pewien, jak poradzić sobie z przypadkiem, w którym obiekt, do którego należy członek, zostanie usunięty lub powinien zostać usunięty, a ja chcę uczynić interfejs tak prostym, jak to tylko możliwe.Używanie std :: function i std :: bind do przechowywania wywołania zwrotnego i obsługi usuwania obiektu.
Więc pomyślałem o następujących rzeczach: Store std::weak_ptr
do obiektu, a także std::function
do członka.
Poniższy wydaje się działać:
class MyBase {
public:
MyBase() {}
virtual ~MyBase() {}
};
//--------------------------------------------------
class MyClass : public MyBase {
public:
MyClass() : MyBase() {}
void myDouble(double val) const { std::cout << "Value is: " << val << std::endl; }
};
//--------------------------------------------------
Class Manager {
public:
void setFunction(std::weak_ptr<MyBase> base, std::function<void(double)> func) {
m_function.first = base;
m_function.second = func;
}
private:
std::pair<std::weak_ptr<MyBase>, std::function<void(double)>> m_function;
};
Aby tego używać:
Manager db;
std::shared_ptr<MyClass> myClass = std::make_shared<MyClass>();
db.setFunction(myClass, std::bind(&MyClass::myDouble, myClass, std::placeholders::_1));
Teraz chcę ukryć std::bind
część od użytkownika tak, że on potrzebuje tylko zadzwonić:
db.setFunction(myClass, &MyClass::myDouble);
Więc chcę uzyskać prawie następujące czynności w mojej funkcji menedżera:
void setFunc2(std::weak_ptr<MyBase> base, std::function<void(double)> func) {
m_function.first = base;
m_function.second = std::bind(func, base, std::placeholders::_1);
}
Ale przede daje błędy:
error: no match for 'operator=' (operand types are 'std::function<void(double)>' and
'std::_Bind_helper<false, std::function<void(double)>&, std::weak_ptr<MyBase>&, const std::_Placeholder<1>&>::type {aka std::_Bind<std::function<void(double)>(std::weak_ptr<MyBase>, std::_Placeholder<1>)>}')
m_function.second = std::bind(func, base, std::placeholders::_1);
Czy istnieje lepszy sposób to zrobić, a może sposób, aby dostać tę pracę?
Coś interesującego, co zauważam. Jeśli użyję std::shared_ptr
, use_count()
zostanie zwiększony o wywołanie std::bind
w oryginalnym kodzie. W związku z tym nie mogę ręcznie zresetować/zniszczyć obiektu, chyba że usunę element z mojego menedżera. Gdzie jest to udokumentowane zachowanie, zwykle używam cppreference?
Mam spojrzał na następującym pytaniem ale nie wydaje się uzyskać go pracy dla mojego problemu: How can I use polymorphism with std::function?
chodzi shared_ptr licznika wykorzystywanych http://en.cppreference.com/w/cpp/utility/functional/bind mówi " Zwracany typ std :: bind zawiera [...] jeden obiekt na każdy z argumentów ..., [...] skonstruowanych ze std :: forward (arg_i). " i niżej na tej samej stronie "Argumenty do powiązania są kopiowane lub przenoszone,". Od momentu podania wartości zmiennej shared_ptr masz kopię. –
Cubbi
'& MyClass :: myDouble' nie będzie konwertować na' std :: function 'mimo to. –
@ T.C W pełni zdaję sobie z tego sprawę, a więc powód pytania. Nie obchodzi mnie, jak wygląda podpis, chcę, żeby wywołanie wyglądało jak 'db.setFunction (myClass i MyClass :: myDouble);' –