为什么在虚拟继承中调用Default构造函数?


78

我不明白为什么在下面的代码中,当我实例化一个类型为object的对象时daughtergrandmother()会调用默认构造函数?

我认为grandmother(int)应该调用构造函数(以遵循我的mother类构造函数的规范),或者由于虚拟继承而根本不应该编译此代码。

在这里,编译器grandmother在我的背后默默地调用默认构造函数,而我从未要求过它。

#include <iostream>

class grandmother {
public:
    grandmother() {
        std::cout << "grandmother (default)" << std::endl;
    }
    grandmother(int attr) {
        std::cout << "grandmother: " << attr << std::endl;
    }
};

class mother: virtual public grandmother {
public:
    mother(int attr) : grandmother(attr) {
        std::cout << "mother: " << attr << std::endl;
    }
};

class daughter: virtual public mother {
public:
    daughter(int attr) : mother(attr) {
        std::cout << "daughter: " << attr << std::endl;
    }
};

int main() {
  daughter x(0);
}

什么编译器(和版本)?您用什么论据进行了编译?
orlp 2012年

fedora 15上的gcc 4.6.3 20120306(Red Hat 4.6.3-2),参数为:-O0 -g3 -Wall -c -fmessage-length = 0
Simon Desfarges

g ++ 4.1.2存在相同的问题:codepad.org/L0jBXfSP
orlp 2012年

带有-Wall -pedantic-errors的Ubuntu 4.7快照再现了这一点。
juanchopanza 2012年

Answers:


84

使用虚拟继承时,最派生类的构造函数直接调用虚拟基类的构造函数。在这种情况下,daughter构造函数直接调用grandmother构造函数。

由于您没有grandmother在初始化列表中显式调用构造函数,因此将调用默认构造函数。要调用正确的构造函数,请将其更改为:

daugther(int attr) : grandmother(attr), mother(attr) { ... }

另请参阅此FAQ条目


2
完全有道理,谢谢!层次结构中的所有构造函数都是从最后一个类调用的,而不是从它们各自的子类调用的。没想到。C ++规范有时可能会很棘手……
Aurelien Ribon 2012年

1
很好的答案!谢谢!
芥末

1
@Xriuk它是指使用虚拟继承继承的类的构造函数。
interjay

1
这是否意味着祖母会被两次打电话?给母亲打电话给祖母会怎样?
Youda008 '16

5
@ Youda008将被调用一次。mother除非您直接实例化mother而不是派生类,否则from的调用将被忽略。
interjay 2016年
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.