在构造函数中调度含虚函数的回调是否符合C++标准?
关于C++构造函数中调度虚函数回调的可靠性与标准合规性问题
正如Scott Meyers在《Effective C++(第3版)》中指出:
条款9:绝不在构造或析构过程中调用虚函数。
请参考以下C++代码:
class my_class { my_class() { // here we _cannot_ call other_virtual() // but will this lambda call the correct function // if it is called after this CTOR has exited its scope? schedule_work([this]{ other_virtual(); }); } void schedule_work(std::function<void()> callback); virtual void other_virtual() = 0; }; class derived : public my_class { derived() : my_class() {} // make sure to implement the pure virtual void other_virtual() override; };
请问上述代码写法是否属于可靠的C实现?是否符合C标准的相关规定?
结论
这段代码是可靠且符合C++标准的,核心原因如下:
- 构造函数中并未直接调用虚函数
other_virtual(),只是将捕获this的lambda作为回调注册到schedule_work中,而该回调的执行时机是在my_class和derived的构造函数都完全执行完毕之后。 - 当回调真正执行时,对象已完成完整构造,此时
this指向的derived对象虚函数表已正确初始化,调用other_virtual()会正常触发derived中的重写版本,完全符合虚函数调用规则。
Scott Meyers的条款9禁止的是在构造/析构过程中直接或间接调用虚函数——因为此时子类部分尚未构造(或已析构),虚函数会被解析为当前正在构造/析构的基类版本(纯虚函数会直接导致未定义行为)。但本案例中虚函数调用发生在构造完成后,完全避开了该风险。
需要注意的额外事项:
- 必须确保回调执行时,
this指向的对象仍然存活,否则会触发悬空指针的未定义行为。 schedule_work需要保证回调不会在对象构造完成前被执行,否则仍会违反条款9的禁忌。
内容的提问来源于stack exchange,提问作者SupAl
相关产品推荐
相关产品推荐

