Ben*_*tFX 76 c++ function callback member
我知道这已被问了很多次,因此很难深入研究这个问题并找到一个有效的简单例子.
我有这个,它很简单,适用于MyClass......
#include <iostream>
using std::cout;
using std::endl;
class MyClass
{
public:
MyClass();
static void Callback(MyClass* instance, int x);
private:
int private_x;
};
class EventHandler
{
public:
void addHandler(MyClass* owner)
{
cout << "Handler added..." << endl;
//Let's pretend an event just occured
owner->Callback(owner,1);
}
};
EventHandler* handler;
MyClass::MyClass()
{
private_x = 5;
handler->addHandler(this);
}
void MyClass::Callback(MyClass* instance, int x)
{
cout << x + instance->private_x << endl;
}
int main(int argc, char** argv)
{
handler = new EventHandler();
MyClass* myClass = new MyClass();
}
class YourClass
{
public:
YourClass();
static void Callback(YourClass* instance, int x);
};
Run Code Online (Sandbox Code Playgroud)
那怎么可以重写,以便EventHandler::addHandler()将与工作都MyClass和YourClass.我很抱歉,但这只是我的大脑工作的方式,我需要看一个简单的例子,说明在我理解为什么/如何工作之前有效的方法.如果你有一个最喜欢的方式让这个工作现在是时候展示它,请标记该代码并将其发回.
[编辑]
在回答之前,答案被删除了.在我的案例中,答案是模板化的功能.将addHandler更改为此...
class EventHandler
{
public:
template<typename T>
void addHandler(T* owner)
{
cout << "Handler added..." << endl;
//Let's pretend an event just occured
owner->Callback(owner,1);
}
};
Run Code Online (Sandbox Code Playgroud)
Som*_*ude 158
而不是静态方法和身边掠过的指针类的实例,你可以使用新的C++ 11标准功能:std::function与std::bind:
#include <functional>
class EventHandler
{
public:
void addHandler(std::function<void(int)> callback)
{
cout << "Handler added..." << endl;
// Let's pretend an event just occured
callback(1);
}
};
Run Code Online (Sandbox Code Playgroud)
该addHandler方法现在接受一个std::function参数,这个"函数对象"没有返回值,并以整数作为参数.
要将其绑定到特定函数,请使用std::bind:
class MyClass
{
public:
MyClass();
// Note: No longer marked `static`, and only takes the actual argument
void Callback(int x);
private:
int private_x;
};
MyClass::MyClass()
{
using namespace std::placeholders; // for `_1`
private_x = 5;
handler->addHandler(std::bind(&MyClass::Callback, this, _1));
}
void MyClass::Callback(int x)
{
// No longer needs an explicit `instance` argument,
// as `this` is set up properly
cout << x + private_x << endl;
}
Run Code Online (Sandbox Code Playgroud)
您需要std::bind在添加处理程序时使用,因为您明确需要将其他隐式this指针指定为参数.如果您有独立功能,则不必使用std::bind:
void freeStandingCallback(int x)
{
// ...
}
int main()
{
// ...
handler->addHandler(freeStandingCallback);
}
Run Code Online (Sandbox Code Playgroud)
让事件处理程序使用std::function对象,也可以使用新的C++ 11 lambda函数:
handler->addHandler([](int x) { std::cout << "x is " << x << '\n'; });
Run Code Online (Sandbox Code Playgroud)
这是一个简洁的版本,适用于类方法回调和常规函数回调。在此示例中,为了显示如何处理参数,回调函数采用两个参数:bool和int。
class Caller {
template<class T> void addCallback(T* const object, void(T::* const mf)(bool,int))
{
using namespace std::placeholders;
callbacks_.emplace_back(std::bind(mf, object, _1, _2));
}
void addCallback(void(* const fun)(bool,int))
{
callbacks_.emplace_back(fun);
}
void callCallbacks(bool firstval, int secondval)
{
for (const auto& cb : callbacks_)
cb(firstval, secondval);
}
private:
std::vector<std::function<void(bool,int)>> callbacks_;
}
class Callee {
void MyFunction(bool,int);
}
//then, somewhere in Callee, to add the callback, given a pointer to Caller `ptr`
ptr->addCallback(this, &Callee::MyFunction);
//or to add a call back to a regular function
ptr->addCallback(&MyRegularFunction);
Run Code Online (Sandbox Code Playgroud)
这将特定于 C++11 的代码限制为类 Caller 中的 addCallback 方法和私有数据。至少对我来说,这最大限度地减少了在实施时出错的机会。