C++构造函数中虚函数调用规则

问题描述

我们有以下C++代码:

#include <iostream>

class B {
   
public:
    B() {
   
        test();
    }

    virtual void test() {
   
        std::cout << "B\n" << std::endl;
    }
private:
};

class D : public B {
   
public:
    D() = default;
    virtual void test() override {
   
        std::cout << "D\n" << std::endl;
    }
private:
};

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

运行这段代码时,输出的是 B 而不是 D。这是为什么?

初步观察

首先,我们有一个基类 B 和一个派生类 DB 的构造函数中调用了虚函数 test(),而 D 重写了这个虚函数。当我们创建一个 D 的对象时,B 的构造函数会被调用,然后在 B 的构造函数中调用了 test()。然而,输出的是 Btest() 实现,而不是 D 的。

理解对象构造过程

在C++中,对象的构造是从基类到派生类的顺序进行的。具体到这段代码:

  1. 当创建 D 的对象 d 时,首先调用 B 的构造函数。
  2. B 的构造函数中,调用了 test()
  3. 之后,D 的构造函数被调用(这里 D 的构造函数是默认的,没有额外操作)。

虚函数在构造函数中的行为

关键在于:在构造函数中调用虚函数时,虚函数的动态绑定(多态)行为不会发生。也就是说,在 B 的构造函数中调用 test() 时,它调用的是 Btest(),而不是 Dtest()

这是因为:

  • B 的构造函数正在执行时,D 的部分还没有被构造。此时对象的 D 部分还不完整,因此不能安全地调用 D 的重写函数。
  • C++ 的设计决定了在基类的构造函数中,虚函数调用被解析为当前类(即基类)的实现,而不是派生类的实现。这是为了避免在对象未完全构造时调用未初始化的
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值