【发布时间】:2011-06-25 08:14:36
【问题描述】:
我从未使用过多重继承,并偶然发现了一个我从未遇到过的设计问题..
class A {
//..methods..
}
class B : public A {
int b;
//...methods..
}
class C : public A {
int c1,c2;
}
class D : public B,public C {
}
这是经典的钻石。事实上,C 实际上只是一个带有两个额外整数的A。 D 实际上只是 B 和 C 的聚合,但我觉得多重继承并不是为了制造这样的东西而设计的。或者可能有其他最佳做法可以做到这一点。
我尝试实现多重继承的原因是我想编写一个类似void func(A*) 的函数并将其传递给A 或D 类指针。我的天真的尝试是做一个简单的演员表:
void func(A* a) { // <-- I call this with a A or D pointer
// ..do something with A members..
if(is_the_case) { // <-- Im sure the passed "a" pointer is actually a *D
D* d = (D*)a;
// ..do something with the extra 2 ints provided by the C class..
}
}
不起作用.. 编译得很好,但是当 if(is_the_case) 被执行时我有一个非常奇怪的行为,清除了 2 个额外的整数 c1 和 c2,也清除了 b(由 B 继承)。
我想起了钻石问题,但这里的层次结构中只有一个B(和两个A),所以我不明白为什么b 也会被清除。为了尝试,我在B 和C 声明中使用了公共虚拟。现在每次转换都是编译错误,除非我使用dynamic_cast..
有人能说清楚幕后发生的事情吗?考虑到还有其他课程,例如:
class E : public A {
int e;
//..methods..
}
class F : public E,public C {
}
也就是说,其他类只是从 A 派生的类的聚合 + 由 C 继承的两个额外整数,并且可以传递给采用 *A 的函数
谢谢,我尽量说清楚了..
【问题讨论】:
-
将一个指针类型转换为另一个指针类型不会产生错误。你能展示你在
D* d = (D*)a;之后做了什么吗? “清除c1,c2”是什么意思?你是怎么做到的? -
c1=c2=0; ..现在 d.b 也是 0.. 我没有收到任何错误.. 它编译并运行.. 问题是 b 也设置为 0
-
您能否在分配给 d.c1 和 d.c2 之前检查 d.b 值?可能已经是 0...
-
当你用一个指向 D 的指针调用 func 时,你如何处理调用点的模棱两可的 base A?
-
它应该抱怨。你确定层次结构吗?
标签: c++ oop multiple-inheritance