23
class A {
        int i;
public: 
        A() {cout<<"in A's def const\n";};
        A(int k) {cout<<"In A const\n";  i = k; }
        };

class B : virtual public A {
public:
        B(){cout<<"in B's def const\n";};
        B(int i) : A(i) {cout<<"in B const\n";}
        };

class C :   public B {
public:
        C() {cout<<"in C def cstr\n";}
        C(int i) : B(i) {cout<<"in C const\n";}
        };

int main()
{
        C c(2);
        return 0;
}

这种情况下的输出是

in A's def const
in B const
in C const

为什么这不进入in A const

`它应该遵循 1 arg 构造函数调用的顺序。但是使用 virtual 关键字从 A 派生 B 实际发生了什么。

还有几个问题

即使我删除了上述程序中的 virtual 关键字并删除了所有默认构造函数,它也会出错。那么,为什么它需要 def 构造函数

4

3 回答 3

18

虚拟基类的构造函数总是从最派生类调用,使用它可能传入的任何参数。在您的情况下,最派生类没有为 指定初始化程序A,因此使用默认构造函数。

于 2012-05-10T12:44:39.123 回答
8

正如JamesKanze 所解释的,在virtual继承的情况下,它是调用虚拟基类的构造函数的最派生类。因此,如果您想要A调用整数的构造函数,则需要将其添加到C的初始化列表中。

C(int i) : A(i), B(i) {cout<<"in C const\n";}

对于您问题的第二部分,不需要默认构造函数,但是派生类必须显式调用非默认构造函数,因为在没有非默认构造函数的情况下编译器无法为您执行此操作。

#include <iostream>
using namespace std;

class A {
  int i;
public:
  // A() {cout<<"in A's def const\n";};
  A(int k) {cout<<"In A const\n";  i = k; }
};

class B : virtual public A {
public:
  // B(){cout<<"in B's def const\n";};
  B(int i) : A(i) {cout<<"in B const\n";}
};

class C :   public B {
public:
  C() : A(42), B(42) {cout<<"in C def cstr\n";}
  C(int i) : A(i), B(i) {cout<<"in C const\n";}
};

int main()
{
  C c(2), c2;
  return 0;
}

这打印出来

In A const
in B const
in C const
In A const
in B const
in C def cstr
于 2012-05-10T13:11:57.243 回答
2

这里有两个问题。

为什么这不进入A const?

因为您使用的是虚拟继承。

使用虚拟继承时,最派生类的ctor的初始化列表直接调用虚拟基类的ctor。. 在这种情况下,这意味着' 构造函数直接C调用A' 构造函数。由于您没有指定在 的初始化列表中调用哪个构造函数,因此调用了默认构造函数。AC

这可以通过将您的实现更改C::C(int)为:

C(int i) : A(i), B(i) {cout<<"in C const\n";}

如果我删除上述程序中的 virtual 关键字并删除所有默认构造函数,则会出错。那么,为什么它需要 def 构造函数呢?

因为B也没有指定A调用哪个ctor,所以使用了默认的构造函数。如果去掉As def ctor,B就不能编译。

于 2012-05-10T13:15:39.340 回答