c++ - C++ 入门第 5 版。虚拟继承和ctor-init
问题描述
在 C++ 入门第 5 版上。第18章多重和虚拟继承,我有一个问题:
练习 18.30:在 Base 中定义一个默认构造函数、一个复制构造函数和一个具有 int 参数的构造函数。在每个派生类中定义相同的三个构造函数。每个构造函数都应该使用它的参数来初始化它的 Base 部分。
我试图以这种方式解决它,所以这是我的继承层次结构:
struct Class {
Class(){cout << "Class()\n";}
~Class(){cout << "~Class()\n";}
};
struct Base : Class {
Base(){cout << "Base()\n";}
Base(int){cout << "Base(int)\n";}
Base(Base const&){cout << "Base(Base const&)\n";}
~Base(){cout << "~Base()\n";}
};
struct D1 : virtual public Base {
D1(){cout << "D1()\n";}
D1(int x) : Base(x){
cout << "D1(int)\n";
}
D1(D1 const& rhs) : Base(rhs){
cout << "D1(D1 const&)\n";
}
~D1(){cout << "~D1()\n";}
};
struct D2 : virtual public Base {
D2(){cout << "D2()\n";}
D2(int x) : Base(x){
cout << "D2(int)\n";
}
D2(D2 const& rhs) : Base(rhs){
cout << "D2(D2 const&)\n";
}
~D2(){cout << "~D2()\n";}
};
struct MI : public D1, public D2 {
MI(){cout << "MI()\n";}
MI(int x) : Base(x), D1(x), D2(x){
cout << "MI(int)\n";
}
MI(MI const& rhs) : Base(rhs), D1(rhs), D2(rhs){
cout << "MI(MI const&)\n";
}
~MI(){cout << "~MI()\n";}
};
struct Final : public MI, public Class {
Final(){cout << "Final()\n";}
Final(int x) : MI(x){
cout << "Final(int)\n";
}
Final(Final const& rhs) : MI(rhs), Class(rhs){
cout << "Final(Final const&)\n";
}
~Final(){cout << "~Final()\n";}
};
现在,如果我编译程序,我会收到错误:
error: ‘Class’ is an ambiguous base of ‘Final’
所以问题出在 classFinal
的复制构造函数初始化列表中,所以我如何初始化复制构造函数中的子部分Class
。
没有抱怨,
Final(int)
因为我让默认的 ctorClass()
运行:Final(int x) : MI(x) // Class default ctor is executed.
所以帮助我解决这个问题。谢谢!
解决方案
这是不可访问基类的情况。该类Final
已经有一个继承链:
struct Final -> struct MI -> struct D1 -> struct Base -> struct Class
写东西 asclass Square: public Shape
表示一种is-a
关系,所以 Square is-a Shape。Final
对于您的类链,它还Class
通过许多中间父系谱系建立了相同的关系。写作public Class
实际上是多余的struct Final : public MI, public Class
。在现实世界的类比中,这类似于表明曾曾祖父是直系父亲,除非我们讨论的是幻想或反常的东西,否则这是不适用的。编译器在警告中声明了它所提出的歧义,然后无法编译代码。这里有一个更细致入微的答案。对于您的具体问题,只需删除Class
fromFinal
应该没问题用于编译。
PS 请考虑重命名Class
为其他名称,因为这是 C++ 并且...class
是一件大事。class Class
会很不可读。
推荐阅读
- javascript - 使用 Vue js 的多级下拉菜单
- c# - 当我创建权限谷歌驱动程序 API C# 时删除链接中的邀请代码
- ios - 访问核心数据以快速返回第一个单词
- java - 当我需要使用浮点数/双精度数时,如何在 Spring 中验证表单输入?
- java - java - 如何使用java中的jsch lib自动连接到具有键盘交互式身份验证的ssh服务器
- sql - 如何优化与自身连接表的红移查询?
- amazon-web-services - 将 EC2 实例指向 GoDaddy 域
- python - 我可以从路径本身就是参数的配置文件构建 Python Click cli 吗?
- kotlin - Room - 如何设置可为空的外键
- python - python找不到文件