CppCoreGuidelines C.82 不要在构造/析构函数中调用虚函数
13 November 2022
C.82: Don’t call virtual functions in constructors and destructors
理由
构造函数和析构函数中调用的函数应该是当前正在构造的对象的函数,而不应该是继承类中需要重载的虚函数。不然会让人很难理解。
更差的情况,在构造或析构函数中,直接或间接调用还没实现的纯虚函数会产生未定义的行为。
例子
class Base { public: virtual void f() = 0; // not implemented virtual void g(); // implemented with Base version virtual void h(); // implemented with Base version virtual ~Base(); // implemented with Base version }; class Derived : public Base { public: void g() override; // provide Derived implementation void h() final; // provide Derived implementation Derived() { // BAD: attempt to call an unimplemented virtual function f(); // BAD: will call Derived::g, not dispatch further virtually g(); // GOOD: explicitly state intent to call only the visible version Derived::g(); // ok, no qualification needed, h is final h(); } };
注意
调用一个明确限定了从属于哪个类的函数,就算这个函数是个虚函数,也已经不是虚调用了。
请查看C.50工厂函数,如何调用继承类的函数而不会导致未定义行为结果。
注意
在构造函数和析构函数中调用虚函数没有什么内在错误。语义上来说这种调用是类型安全的。但是,经验表明这种调用不太需要、容易混淆维护者、成为信手的错误之源。
强化
- 标记在构造和析构函数中调用虚函数的情况