CodeWalk

构造函数中可以调用虚函数吗?为什么?

作者:孤独的心 · 2026-05-30 12:55

在构造函数的执行体中调用虚函数会发生什么?实际调用的是哪个类的函数版本?为什么C++标准不建议在构造或析构函数中调用虚函数?底层原因是什么?

回答

孤独的心

结论:构造函数中调用虚函数不会产生多态行为,调用的是当前正在构造的类的版本,而非派生类的覆盖版本。

底层原因:对象构造是从基类到派生类逐步进行的。当执行基类构造函数时,派生类的成员变量尚未初始化,vptr(virtual pointer)指向的是基类的虚表,而非最终派生类的虚表。因此虚函数调用被解析为基类版本。

示例

struct Base { Base() { f(); } virtual void f() { cout<<"Base"; } };
struct Derived : Base { void f() override { cout<<"Derived"; } };
Derived d; // 输出"Base"而非"Derived"

C++标准规定[ISO C++ 12.7/4]:在构造/析构期间,对象的动态类型(dynamic type)是当前正在构造/析构的类。

建议:不要在构造函数中调用虚函数。若需要类似行为,考虑:①二段式构造;②CRTP静态分发;③在构造后调用单独的初始化函数。