[英]multiple inheritance and data members
我从未使用多重继承,却偶然遇到了从未遇到过的设计问题。
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*)
类的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)
时,我有一个非常奇怪的行为,清除了两个额外的int c1
和c2
,也清除了b
(由B
继承)。
我对钻石问题怀有戒心,但是在层次结构中只有一个B
(和2 A
),所以我不明白为什么b
也要清除。 为了尝试,我在B
和C
声明中使用了公共虚拟。 现在,每次转换都是编译错误,除非我使用dynamic_cast
..
有人可以说清楚幕后发生的事情吗? 考虑到还有其他类似的课程,什么是最佳做法?
class E : public A {
int e;
//..methods..
}
class F : public E,public C {
}
也就是说,其他类只是从A
派生的类的集合+ C
继承的两个额外的int的集合,并且可以传递给采用*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型强制转换的一个很好的例子。
我不知道你为什么看到这种行为。 如注释中所述,您不应按照说明进行编码。
有设计上的问题吗? 是。 不要基于查询对象的类型来明确地做出选择。 这就是虚函数的用途。
class A
{
public:
virtual void prepare_for_list_insertion() {}
};
class B : public A
{
int b;
};
class C : public A
{
private:
int c1, c2;
protected:
void clear() { c1 = c2 = 0; }
};
class D : public B, public C
{
public:
void prepare_for_list_insertion()
{
clear();
}
};
void func(A* a)
{
a->prepare_for_list_insertion();
}
int main()
{
A a;
func(&a); // calls A::prepare_for_list_insertion
D d;
// You need a cast to disambiguate the A base - either will do.
func(static_cast<C*>(&d)); // calls D::prepare_for_list_insertion
func(static_cast<B*>(&d)); // calls D::prepare_for_list_insertion
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.