Sas*_*cha 6 c++ methods function callback
我们为客户提供简单的通信库.
我的问题是:如何从我们客户的类中保存指向方法的指针?
Library.h 是头文件,包含客户建立通信所需的所有方法.
library.cpp是我们的代码.在某处我必须保存指向我们客户的回调函数方法的指针.
customer.cpp 是客户如何使用我们的库的一个例子.
library.h:
// This is the header file what our customer gets
class Library {
public:
template <class Object, class Function>
void SetCallback(Object &obj, Function f);
};
Run Code Online (Sandbox Code Playgroud)
library.cpp:
struct T_CUSTOMER {
Object o; // <- ???
Function f; // <- ???
} customer;
void Library::SetCallback(Object &obj, Function f) {
//Saving the method from our costumer
customer.o = obj; // <- ???
customer.f = f; // <- ???
}
void someFunction(void) {
// here i want to call the method from the customer
customer.o->customer.f(); //<- ???
}
Run Code Online (Sandbox Code Playgroud)
customer.cpp中:
class AnyCustomerClass {
private:
Library lib;
public:
AnyCustomerClass() {
//< here the customer sets his method which I should call
lib.SetCallback(this, &AnyCustomerClass::callback());
}
callback() {
// do something
}
}
Run Code Online (Sandbox Code Playgroud)
谢谢你的帮助!
基本思想是,您定义一个抽象的Callback类,它实际上被传递给您的接口.这个回调函数传递一个int参数:
struct Callback {
virtual ~Callback(){}
virtual void operator()(int param)=0;
};
Run Code Online (Sandbox Code Playgroud)
这个类允许你的实现不需要你需要回调的代码的知识.当然,要调用一个类,你需要一个回调的实例,它已知道它的目标.因此,您还提供了一个模板化子类,使您的库用户可以轻松地将其中一个类中的方法绑定到通用Callback的实例: -
template<class T>
class ClassCallback : public Callback {
T* _classPtr;
typedef void(T::*fncb)(int param);
fncb _cbProc;
public:
ClassCallback(T* classPtr,fncb cbProc):_classPtr(classPtr),_cbProc(cbProc){}
virtual void operator()(int param){
(_classPtr->*_cbProc)(param);
}
};
Run Code Online (Sandbox Code Playgroud)
要从类中创建回调实例,代码将如下所示.调用也很简单:
struct CMyClass {
Library* _theLibrary;
CMyClass(Library* init):_theLibrary(init){
Callback* pCB = new ClassCallback<CMyClass>(&myClass,&CMyClass::OnCb);
_theLibrary->SetCallback(pCB);
}
void OnCb(int){
// callback triggered
}
void Run(){
_theLibrary->DoWork();
}
};
Run Code Online (Sandbox Code Playgroud)
总结:Library.h然后会是这样的.定义抽象回调类,库类以及客户用来包装其类及其回调方法的模板化实用程序类:
// This is the header file what our customer gets
struct Callback {... };
class Library {
Callback* _pcb;
public:
void SetCallback(Callback* pcb){_pcb=pcb;}
void DoWork(){
int status=0;
(*pcb)(status);
}
~Library(){delete _pcb;}
};
template<class T> struct ClassCallback{ ... };
Run Code Online (Sandbox Code Playgroud)
基本思想是在虚函数调用后隐藏对象和函数(Object以及Function代码中)的确切类型,并将它们包装在抽象接口中(这是'类型擦除'习语).
然后,您可以通过模板界面让您的客户从"基本回调"类型中获得.
有关教程,请参阅本网站上的第4部分.或者看一下Boost.Function和Boost.Bind是如何工作的(他们正是这样做的,尽管有一个稍微强大的界面)