Ada*_*zyk 11 c++ multiple-inheritance
考虑这个C++代码:
#include <iostream>
using namespace std;
struct B {
virtual int f() { return 1; }
int g() { return 2; }
};
struct D1 : public B { // (*)
int g() { return 3; }
};
struct D2 : public B { // (*)
virtual int f() { return 4; }
};
struct M : public D1, public D2 {
int g() { return 5; }
};
int main() {
M m;
D1* d1 = &m;
cout << d1->f()
<< static_cast<D2&>(m).g()
<< static_cast<B*>(d1)->g()
<< m.g();
}
Run Code Online (Sandbox Code Playgroud)
它打印1225.如果我们进行虚拟继承,即在标有(*)的行virtual之前添加public,则打印4225.
1改变4吗?static_cast<D2&>(m)和的含义static_cast<B*>(d1)吗?图片胜于雄辩,所以在答案之前......
M类层次结构没有 D1和D2的B的虚拟基础继承:
M
/ \
D1 D2
| |
B B
Run Code Online (Sandbox Code Playgroud)
M级层级WITH B中D1和D2的虚拟基础继承:
M
/ \
D1 D2
\ /
B
Run Code Online (Sandbox Code Playgroud)
跨代委托,或者我喜欢称之为兄弟 - 多态性与扭曲.虚基础继承将B :: f()重写修复为D2:f().希望在考虑虚拟函数的实现位置以及它们因继承链而重写的内容时,图片可以帮助解释这一点.
static_cast在这种情况下,运算符用法驱动从派生到基类类型的转换.
阅读非常糟糕的代码并了解语言"工作"的基础知识的经验很多
谢天谢地.这并不常见.然而,原来的iostream库会给你做噩梦,如果这总是令人困惑的话.
(1) 你能解释一下为什么1变成4吗?
没有virtual继承,有2个独立的继承层次;B->D1->M和B->D2->M。想象一下 2 个virtual函数表(尽管这是实现定义的)。
当您调用f()with时D1*,它只会知道B::f(),仅此而已。通过virtual继承,baseclass B被委托给M,因此D2::f()被视为 的一部分class M。
static_cast<D2&>(m)(2) 你能解释一下和的含义static_cast<B*>(d1)吗?
static_cast<D2&>(m),就像考虑class Mas的对象一样class D2
static_cast<B*>(d1),就像考虑class D1as的指针一样class B1。
两者都是有效的演员表。
因为函数选择g()不是在编译时发生的。如果是这样的话,所有这些选角都不再重要了。virtualvirtual
(3) 你如何在这种组合中不迷失方向?你在画东西吗?
当然,它很复杂,乍一看,如果有这么多这样的类,人们可能很容易迷失。
(4) 在正常项目中,这样复杂的设置是否常见?
一点也不,这很不寻常,有时还有代码味道。