在我们的代码库中,我们有很多这样的类:
class DirectoryCallback {
public:
virtual ~DirectoryCallback(){};
virtual void process(const std::string &path) = 0;
};
它们通常只有一个目的:包装函数调用。扩展这些接口是非常的。无聊并没有伤害,但我想知道:这个模式有什么用处,因为我们在C ++中有lambda和std::function
?因为完全他们可以做什么...包装一个函数调用。
答案 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
成员的简单方法是内存效率较低。