问题描述
以下代码:
#include<iostream>
using namespace std;
class Man
{
int stories;
public:
Man(int stories) : stories(stories) {cout << "A man is created with " << stories << " stories." << endl;};
};
class Grandpa : public virtual Man
{
int pipes;
public:
Grandpa(int stories, int pipes) : Man(1000), pipes(pipes)
{
stories += stories;
cout << "Grandpa is created with " << stories << " stories and pipes." << endl;
};
};
class Father : public Grandpa
{
int cars;
public:
Father(int stories, int cars) : Man(1000), Grandpa(1000, 1), cars(cars)
{
stories += stories;
cout << "Father is created with " << stories << " stories and cars." << endl;
};
};
class Son : public Father
{
int girls;
public:
Son(int stories, int girls) : Man(1000), Father(1000, 3), girls(girls)
{
stories += stories;
cout << "Son is created with " << stories << " stories and girls." << endl;
};
};
int main()
{
Son Dick(1000, 5);
return 0;
}
在运行中提供以下输出:
Gives the following output on the run:
创建了一个拥有1000个故事的男人.
爷爷是用2000个故事和烟斗创建的.
父亲是由2000个故事和汽车组成的.
儿子由2000个故事和女孩组成.
当我不在父亲和儿子的初始值设定项列表中调用Man(int)时,它将无法编译.它正在尝试调用Man(void),而Man()未定义.为什么会这样呢?但是,我认为,当调用父亲或儿子的构造函数时,虚拟库的构造函数已经在爷爷中被调用了!而且因此,我希望输出为:
And it does not compile, when I do not call Man(int) in Father's and Son's initializers' lists. It is trying to call Man(void), and Man() is not defined. Why is it so? Yet, I think, when Father's or Son's constructors were called, the virtual base's constructor had already been called in Grandpa! Moreover thus, I would expect the output to be:
创建了一个拥有1000个故事的男人.
爷爷是用2000个故事和烟斗创建的.
父亲是由3000个故事和汽车组成的.
儿子由4000个故事和女孩组成.
然后概括一下:为什么虚拟基类构造函数必须在派生类的初始化列表中显式调用,尽管它已被放置在较年轻的祖先初始化列表中?为什么在年轻的祖先中似乎没有调用它,而尝试调用默认的基类呢?
To recapitulate then: why a virtual base class constructor has to be called explicitly in an initializer list of a derived class, although it is already placed in an younger's ancestor initializer list? Why it is seemingly not called in the younger ancestor, and a default base class is tried to be called instead?
编辑,因为找到了数字问题的答案真可惜:)我本应该在爷爷protected int _stories;
中创建int stories
,然后输出将如预期的那样:男人的故事为1000个,爷爷的故事为2000个,父亲的故事为3000个,迪克的故事为4000个:)本地变量而不是Man的成员...对不起,麻烦您了!
EDIT due to finding an answer to problem with numbersWhat a shame :) I should have made int stories
in Grandpa protected int _stories;
and then the output would be as expected: 1000 stories for Man, 2000 for Grandpa, 3000 for Father and 4000 for Dick :) Otherwise stories += stories
acts on local variable instead of the Man's member... Sorry for bothering!
推荐答案
对虚拟基础的构造函数的调用来自于所创建对象的最派生类型.在这种情况下,它是Son
,因此Son
需要调用Man
的构造函数.
The call to the virtual base's constructor comes from the most-derived type of the object being created. In this case, that's Son
, so Son
needs to call Man
's constructor.
但是,也可以创建实际上不是Son
的Father
(例如,具有Father Dick(1000, 5)
的main
).因此,Father
可能最终成为初始化Man
的对象,这意味着它需要调用Man
的构造函数. Grandpa
也是一样.
However, it's also possible to create a Father
that isn't actually a Son
(e.g., main
having Father Dick(1000, 5)
). Because of that, Father
might end up being the one to initialize Man
, meaning it needs to call Man
's constructor. The same is true for Grandpa
.
如果创建Man
,Grandpa
和Father
抽象类,则它们不再可能是初始化Man
的类,因此不需要调用其构造函数.但是,当我这样做时(Glang编译它),GCC 6.1给了我一个错误.我相信海湾合作委员会在这里是错的.
If you make Man
, Grandpa
, and Father
abstract classes, they can no longer possibly be the ones to initialize Man
, and thus do not need a call to its constructor. However, GCC 6.1 gives me an error when I do this (Clang compiles it). I believe GCC to be wrong here.
这篇关于为什么在较老的祖先已有的规则中,在最派生类的初始化列表中显式调用虚拟基类构造函数的规则?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!