由于lambda进入C ++,`Callback`接口是否已过时?

时间:2015-03-20 07:35:22

标签: c++ c++11 lambda callback obsolete

在我们的代码库中,我们有很多这样的类:

class DirectoryCallback {
public: 
    virtual ~DirectoryCallback(){};
    virtual void process(const std::string &path) = 0;
};

它们通常只有一个目的:包装函数调用。扩展这些接口是非常的。无聊并没有伤害,但我想知道:这个模式有什么用处,因为我们在C ++中有lambda和std::function?因为完全他们可以做什么...包装一个函数调用。

1 个答案:

答案 0 :(得分:0)

这个答案有点混乱,但需要考虑一些事情......

虚拟函数 - 用作回调 - 更具有内在的限制性:

  • 您知道派生类必须指定一个实现(给定您的= 0),但在派生对象的生命周期内它不会发生变化(可能与const std::function个对象设置类似在初始化列表中,但不必是),

  • 你知道从构造函数完成到销毁之前回调是活动的

相比之下,有人想要处理指定一组回调lambda的代码,必须更仔细地查看它们的设置方式和时间,以及它们是否可以在对象的生命周期内变化。 Lambdas可能会从他们创建的函数中捕获更多输入和上下文 - 这增加了潜在的复杂性。

设置std::function回调可能需要更明确的过程代码来设置std::function变量,除非只在构造函数的初始化列表中完成。虚函数override更具说明性,有些人更喜欢。

使用了虚函数的最派生实现,而在最派生的构造函数中将lambda指定为std::function可能需要通过层次结构将其显式传递给所有级别的基类构造函数。

虚拟函数的const - 直观地工作,但是通过将std::function成员设置为lambdas来指定行为的派生类有机会获取对派生对象的非const访问权限,无论基类设计表明这些回调应该是什么。

虚拟分派由编译器密切理解,并且在编译时已知对象的动态类型时,通常可以使用可能内联的函数进行解析。认为对于std::function对象必须实现等效优化是一个延伸,其中lambda在运行时名义上由派生函数设置....

虚拟函数被有效地计算为每类表的每个对象指针,使用std::function手动编排会更麻烦。每次回调std::function成员的简单方法是内存效率较低。