我可以在函数指针和子类对象之间进行选择。为了说清楚,说我必须通知一些行动的某个对象(例如计时器);请参考以下两个选项(用于演示目的的非常基本的代码):
版本1
typedef void TimerCallback(void *args);
class Timer{
public:
Timer();
~Timer();
void schedule(TimerCallback *callback, void *args, long timeout)=0;
void cancel();
};
版本2
class TimerTask{
public:
TimerTask();
virtual ~TimerTask();
void timedout()=0;
};
class Timer{
public:
Timer();
virtual ~Timer();
void schedule(TimerTask *callback, long timeout)=0;
void cancel();
};
哪一个是标准的C ++方式,哪个是高效的?如果您对此有任何其他建议,请与我们联系。
如果我不清楚这方面,请告诉我。
由于
答案 0 :(得分:14)
我会说std::function
和std::bind
。那么,如果要使用继承类,独立函数,成员函数或lambdas,则无关紧要。
顺便说一下,如果有人好奇的话,我会在前一段时间处理一个简单的计时器事件,作为另一个问题的答案。它展示了使用例如std::function
和std::bind
:https://stackoverflow.com/a/11866539/440558。
答案 1 :(得分:4)
我认为最好使用boost(or std since C++11)::function
来保持回调,使用boost::bind
来绑定它的参数,或者使用boost::signal
。
这将是一个更普遍和冗长的解决方案,代价是真正的小罚款。
答案 2 :(得分:2)
您正在使用面向对象的编程,您应该遵循面向对象的编程范例。
在我看来,使用对象而不是函数指针是更干净,通常更好的方法。
您还可以尝试使用visitor pattern使代码更好,更灵活。
您还可以考虑publisher/subscriber pattern。
答案 3 :(得分:1)
函数指针有效地阻止你使用闭包 - 为你的事件处理程序分配方法(这不是完全是真的,但它会以这种方式限制你,这个解决方案没什么用处)。
我会投票反对面向对象的方法。如果您使用C ++ 11,您可能会大量简化代码:
#include <cstdio>
#include <functional>
class Emitter
{
private:
std::function<void(int)> eventHandler;
public:
void SetEventHandler(std::function<void(int)> newEventHandler)
{
eventHandler = newEventHandler;
}
void EmitEvent()
{
eventHandler(42); // + error-checking
}
};
class Handler
{
private:
void HandleEvent(int i)
{
printf("Event handled with i == %d\n", i);
}
public:
void AttachEmitter(Emitter & e)
{
e.SetEventHandler([this](int i) { HandleEvent(i); });
}
};
int main(int argc, char * argv[])
{
Emitter e;
Handler h;
h.AttachEmitter(e);
e.EmitEvent();
}
答案 4 :(得分:0)
两者都有效。你的第一个是“C风格”,需要在某个地方使用静态功能。第二个版本是“C ++样式”,允许您使用TimerTask的实例。
通常,应该使用版本2,因为它不需要静态函数。