c++回调——编译时虚拟函数的替代品

c++ callbacks - compile time alternatives to virtual functions

本文关键字:函数 虚拟 替代品 回调 编译 c++      更新时间:2023-10-16

我想要一个能够执行回调的通用可重用类。我通常使用虚函数来完成:

泛型类:
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();
}

这似乎是一个可怕的大量的样板文件,只是为了连接回调。另一种选择是使用函子,这可能更简洁一些。

但是在我看来,很多东西在编译时就已经知道了。这是否可以简化,以便在编译时解析回调?

您可以使用奇怪的循环模板模式(CRTP)来实现静态多态性。

您可能会发现只需简单地使用std::函数就可以达到目的。这样,客户端就可以按照他们认为合适的方式实现他们的类,而不是被迫使用继承。

这也比C风格的回调更可取,C风格的回调通常需要一个void*"用户数据"指针,以便能够正确地与想要使用成员函数的类一起工作。

您可以使用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();

我认为基于策略的设计是你正在寻找的:

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

基本模式在Alexandrescu的"Modern c++ Design"中概述,并在其配套库"Loki"中使用。鉴于此,Loki库本身是如何使用策略设计的一个很好的参考。该库在sourceforge上:

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