构造函数调用层次结构

use*_*920 6 c++ constructor call hierarchy

我在类型层次结构中调用构造函数的规则时遇到了棘手的问题.这是我做的:

class A{
protected:
    int _i;
public:
    A(){i = 0;}
    A(int i) : _i(i){}
    virtual ~A(){}
    virtual void print(){std::cout<<i<<std::endl;}
};

class B : virtual public A{
protected:
    int _j;
public:
    B() : A(){_j = 0;}
    B(int i, int j) : A(i), _j(j){}
    virtual ~B(){}
    virtual void print(){std::cout<<i<<", "<<j<<std::endl;}
};

class C : virtual public B{
protected:
    int _k;
public:
    C() : B(){_k = 0;}
    C(int i, int j, int k} : B(i,j), _k(k){}
    virtual ~C(){}
    virtual void print(){std::cout<<i<<", "<<j<<", "<<k<<std::endl;}
};

int main(){
    C* myC = new C(1,2,3);
    myC->print();
    delete myC;
    return 0;
}
Run Code Online (Sandbox Code Playgroud)

现在,我想让新的C(1,2,3)调用B(1,2)的构造函数,然后调用构造函数A(1)来存储_i = 1,_j = 2,_k = 3.在创建类C的实例myC时,出于某种原因我不明白,但是,要调用的第一个构造函数是A的标准构造函数,即A :: A(); 这显然会导致错误的结果,因为受保护的变量_i被赋值为0.从不调用构造函数A(1).为什么会这样?我发现这非常直观.有没有办法避免显式调用类型层次结构中的所有构造函数来实现所需的行为?

谢谢你的帮助!

zau*_*ufi 7

你真的需要virtual继承吗?你有一个问题,因为第一个虚拟基构造函数将首先被调用,但继承当你不指定任何CB(后者已经A几乎继承,所以默认叫).

一个解决方案是删除虚拟继承......正如Arne Mertz的答案所述.另一个(如果你真的想要虚拟继承)是ACctor 明确调用:

C(int i, int j, int k} : A(i), B(i,j), _k(k){}
Run Code Online (Sandbox Code Playgroud)


Arn*_*rtz 6

这是因为您使用了虚拟继承,这在存在多个继承时才有意义.只是正常继承,一切都会如你所愿.


Gor*_*pik 5

使用虚拟继承时,派生程度最高的类必须直接调用其所有虚拟基础的构造函数.在这种情况下,构造函数C必须为B和调用构造函数A.由于您只调用B构造函数,因此它使用默认A构造函数.B构造函数调用另一个A构造函数并不重要:因为它是一个虚拟基类,所以忽略此调用.

你有两种解决这个问题的方法:显式调用A(int)构造函数:

C(int i, int j, int k} : A (i), B(i,j), _k(k){}
Run Code Online (Sandbox Code Playgroud)

或使用普通继承而不是虚拟.

  • 最派生的类没有_必须_显式调用其虚拟基类的构造函数,它可以让它们像问题中一样隐式默认初始化。然而,它确实做到了,您是正确的,它始终是初始化虚拟基类的最派生类。 (2认同)