我从来没有使用过多重继承并且偶然遇到了一个我从未遇到过的设计问题..
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
(和2个A
),所以我不明白为什么 b
也被清除。只是为了尝试,我在 B
和 C
声明中使用了 public virtual。现在每次转换都是编译错误,除非我使用 dynamic_cast
..
谁能说清楚幕后发生的事情?考虑到还有其他类,如:
class E : public A {
int e;
//..methods..
}
class F : public E,public C {
}
也就是说,其他类只是从 A
派生的类的集合 + C
继承的两个额外的整数,并且可以传递给采用以下函数的函数*A
谢谢,我尽量说清楚了..
最佳答案
您的代码可以正常工作,因为您使用了 C 风格的转换,它可以是 reinterpret_cast
,据我了解,您可以在任何两种指针类型之间reinterpret_cast
,即使它没有意义。从多重继承的基类向上转换为更派生的类时,您必须使用 dynamic_cast
。 static_cast
会产生编译时错误。事实上,dynamic_cast
同时完成了这两项工作。
void func(A* a) { // <-- I call this with a A or D pointer
// ..do something with A members..
if(D* d = dynamic_cast<D*>(a)) { // a definitely points to a D
// and we got a guaranteed good pointer too
}
}
这是一个很好的例子,说明为什么应该避免 C 风格的转换。
关于c++ - 多重继承和数据成员,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/6476677/