You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

C++:基类构造函数调用虚方法时子类重写方法未触发疑问

构造函数中调用虚函数的“坑”——你想错的原因和实际行为

嘿,我太懂这种预期和实际不符的困惑了!很多刚摸C++虚函数的朋友都会默认觉得:基类构造里调用虚方法,子类重写后肯定会调子类的实现,但实际完全不是这么回事!

先把你没写完的代码补全,咱们用实际运行结果说话:

#include <iostream>
using namespace std;

class Base {
protected:
    void CreateA();
    virtual void CreateB();
public:
    Base();
    ~Base();
};

Base::Base(){
    this->CreateA();
}

Base::~Base(){}

void Base::CreateA(){
    cout << "BASE CREATE A " << endl;
    this->CreateB();
}

void Base::CreateB(){
    cout << "BASE CREATE B" << endl;
}

// 定义子类,重写CreateB
class Derived : public Base {
protected:
    void CreateB() override {
        cout << "DERIVED CREATE B" << endl;
    }
};

int main() {
    Derived d;
    return 0;
}

运行结果会是啥?

你可能以为会输出:

BASE CREATE A
DERIVED CREATE B

但实际输出是:

BASE CREATE A
BASE CREATE B

为啥会这样?

这得从C++对象的构造顺序和虚函数表(vtable)的初始化逻辑说起:

  • 当你创建Derived对象时,先执行基类Base的构造函数,此时子类Derived的成员变量还没初始化,对象的虚函数表还是基类Base的版本。
  • 基类构造完成后,才会初始化子类的成员,然后把虚函数表切换到子类的版本。
  • 所以在基类构造函数里调用虚函数CreateB,此时对象还处于“基类状态”,只会调用基类的CreateB实现,子类的重写版本根本还没“上线”。

重要提醒

永远别在构造函数或析构函数里调用虚函数!不管是直接调用还是间接调用(比如你这里CreateA里调用CreateB),都不会触发子类的重写逻辑,完全不符合你的预期,很容易埋下bug。

内容的提问来源于stack exchange,提问作者ICU_

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.21 06:57:08