【问题标题】:Why is Default constructor called in virtual inheritance?为什么在虚拟继承中调用默认构造函数?
【发布时间】:2012-04-12 01:23:10
【问题描述】:

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

我认为要么应该调用 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);
}

【问题讨论】:

  • 什么编译器(和版本)?你用什么参数编译它?
  • gcc 4.6.3 20120306 (Red Hat 4.6.3-2) 在 fedora 15 上。参数是:-O0 -g3 -Wall -c -fmessage-length=0
  • g++ 4.1.2 也有同样的问题:codepad.org/L0jBXfSP
  • 带有 -Wall -pedantic-errors 的 Ubuntu 4.7 快照重现了这一点。

标签: c++ inheritance virtual-inheritance


【解决方案1】:

当使用虚继承时,虚基类的构造函数由最派生类的构造函数直接调用。本例中daughter构造函数直接调用grandmother构造函数。

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

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

另见This FAQ entry

【讨论】:

  • 这完全有道理,谢谢!层次结构中的所有构造函数都是从最后一个类调用的,而不是由它们各自的子类调用。从来没想过。 C++ 规范有时会很棘手……
  • 谢谢!所以在虚拟继承的情况下,最好的办法是手动调用链的所有构造函数。
  • @Xriuk 指的是使用虚拟继承继承的类的构造函数。
  • 这是否意味着祖母会被叫两次?母亲内部给祖母打电话会发生什么?
  • @Youda008 会被调用一次。来自mother 的调用将被忽略,除非您直接实例化mother 而不是派生类。
猜你喜欢
  • 2018-04-18
  • 2021-06-02
  • 2012-07-26
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-06-21
相关资源
最近更新 更多