为什么C++不允许派生类在初始化列表中使用基类成员?

Hin*_*sum 2 c++ initialization class list derived

我有以下计划:

#include<iostream> 
using namespace std; 
struct Base01{ 
    int m; 
    Base01():m(2){} 
    void p(){cout<<m<<endl;} 
}; 
struct Derived01:public Base01{ 
    Derived01():m(3){} 
}; 
struct Derived02:virtual public Base01{ 
    Derived01():m(4){} 
}; 
struct my: Derived01,Derived02{ 
    my():m(5){} 
}; 
int main(){ 
    return 0; 
} 
Run Code Online (Sandbox Code Playgroud)

gcc/clang都报告编译错误.

我只想知道这里的语言设计考虑是什么,为什么派生类只能在初始化列表中调用基类ctor,但不能直接使用基类成员?

AnT*_*AnT 8

您在构造函数初始化列表中执行的操作是初始化.它只能在对象的生命周期中完成一次.一般情况下,这就是启动对象生命周期的原因.

基类的构造函数(在派生类的构造函数正确变为活动状态之前完成工作)已经初始化了基类的所有直接子对象.它已经开始了他们的一生.如果您尝试从派生类的构造函数中伸入并初始化基类的直接子对象,那么这显然是同一对象的第二次初始化.这在C++中是完全不可接受的.语言设计通常不允许您第二次初始化某些内容.

在您的情况下,所讨论的子对象具有基本类型int,因此很难看到这种"重新初始化"的危害.但是考虑一些不那么微不足道的东西,比如一个std::string物体.你如何建议派生类应该"撤消并重做"已经由基类执行的初始化?虽然正式地可以正确地执行它,但构造函数初始化程序列表并非用于此目的.

在一般情况下,做这样的事情,要求语言功能,允许用户告诉基类的构造沿东西线"请留下你的这个子对象初始化,我才能够达到,并从派生类后初始化" .但是,C++不为用户提供此类功能.虚拟基类初始化中存在一个模糊的类似特征,但它有一个非常特定(和不同)的目的.