c ++回调 - 编译虚拟函数的替代方法

时间:2011-11-15 19:21:47

标签: c++ design-patterns

我希望一个通用的可重用类能够执行回调。我通常使用虚函数来执行此操作:

通用类:

class LibraryClass
{
private:
    virtual void SomeCallback(){}
};

使用泛型类的代码:

class AppClass;

class LibraryClassWrapper: public LibraryClass
{
public:
    LibraryClassWrapper(AppClass& appClass):appClass_(appClass){}
private:
    virtual void SomeCallback();
    AppClass& appClass_;
};

class AppClass
{
public:
    AppClass():libraryClassWrapper_(*this){}
    void handleCallbackFromLibraryClass()
    {
        std::cout << "Handling callback" << std::endl;
    }
private:
    LibraryClassWrapper libraryClassWrapper_;
};

void LibraryClassWrapper::SomeCallback()
{
    appClass_.handleCallbackFromLibraryClass();
}

这似乎是一个非常多的样板,只是为了连接一个回调。另一种方法是使用仿函数,它可能更清洁一些。

但是我发现在编译时已经知道了很多。这可以简化,以便在编译时解决回调吗?

3 个答案:

答案 0 :(得分:5)

您可以使用 Curiously recurring template pattern(CRTP) 来实现静态多态性。

答案 1 :(得分:3)

你可能会发现只是简单地使用std :: function就可以了。这样客户端可以实现他们的类,但他们认为合适而不是被迫使用继承。

这也优于C风格的回调,通常需要void*&#34;用户数据&#34;指针,以便能够与想要使用成员函数的类一起正常运行。

您可以使用lambda捕获您需要的任何状态,并且可以让回调的接口仅反映与通知相关的内容。应该像这样简单:

#include <functional>

typedef std::function<void()> CallbackType;

struct Example
{
    void CallbackHandler()
    {
        /* do something */
    }
};

void FreeFunctionHandler()
{
    /* do something */
}

// Use lambda to call member function of 'example'
Example example;
CallbackType callback1 = [&example]() { example.CallbackHandler(); };

// Use free function
CallbackType callback2 = FreeFunctionHandler;

// Execute callbacks
callback1();
callback2();

答案 2 :(得分:1)

我认为基于政策的设计是您正在寻找的:

http://en.wikipedia.org/wiki/Policy-based_design

Alexandrescu的“现代C ++设计”概述了基本模式,并用于伴随库“Loki”。鉴于此,Loki图书馆本身就是如何通过政策使用设计的一个很好的参考。该库位于sourceforge:

http://loki-lib.sourceforge.net/index.php?n=Main.HomePage