4

我可以在函数指针和子类对象之间进行选择。为了清楚起见,假设我必须通知某个对象某些动作(例如计时器);参考以下两个选择(演示目的的非常基本的代码):

版本 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++ 方式,哪一种是高效的?如果您在这方面有任何其他建议,请告诉我。

如果我在这方面不清楚,请告诉我。

谢谢

4

5 回答 5

14

我会说std::functionstd::bind。那么,如果你想使用继承类、独立函数、成员函数或lambdas都没关系。


顺便说一句,如果有人好奇,我前段时间做了一个简单的计时器事件处理,作为另一个问题的答案。它展示了例如std::function和的使用std::bindhttps ://stackoverflow.com/a/11866539/440558 。

于 2013-02-25T12:53:55.223 回答
4

我认为最好使用boost(or std since C++11)::function来保存回调并boost::bind绑定它的参数,或者使用boost::signal. 这将是更通用和更详细的解决方案,代价是非常小的惩罚。

http://www.boost.org/doc/libs/1_53_0/doc/html/signals2.html

于 2013-02-25T12:53:06.857 回答
2

您正在使用面向对象的编程,并且应该遵循面向对象的编程范例。

在我看来,使用对象,而不是函数指针,是更干净且通常更好的方法。

您还可以尝试使用访问者模式来使代码更好、更灵活。

您还可以考虑发布者/订阅者模式

于 2013-02-25T12:52:26.053 回答
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();
}
于 2013-02-25T12:57:26.877 回答
0

两者都有效。您的第一个是“C 风格”,需要在某处使用静态函数。第二个版本是“C++ 风格”,允许您使用 TimerTask 的实例。

一般来说,应该使用版本 2,因为它不需要静态函数。

于 2013-02-25T12:54:42.127 回答