I never used multiple inheritance and stumbled into a design problem I never faced..
class A {
//..methods..
}
class B : public A {
int b;
//...methods..
}
class C : public A {
int c1,c2;
}
class D : public B,public C {
}
Here's the classical diamond. The fact is that C
is really just an A
with two extra ints. and D
is really just an aggregation of B
and C
but I feel like multiple inheritance was not designed to make things like these. Or that there may be other best practices to do this.
The reason why im trying to implement multiple inheritance is that I want to write a function like void func(A*)
and pass it either a A
or D
class pointer. My ingenuous attempt is to make a simple cast:
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..
}
}
Doesn't work.. Compiles fine, but I have a really strange behaviour when if(is_the_case)
is executed, clearing that 2 extra ints c1
and c2
, clears also b
(inherithed by B
).
I remebered about the diamond problem, but here there is only one B
(and 2 A
) in the hierarchy, so I don't understand why b
gets cleared as well. Just to try, I used public virtual in B
and C
declaration. Now every cast is a compile error unless I use a dynamic_cast
..
Can someone make it clear what's happening behind the scenes? What is the best practice to do it, considering there are other classes like:
class E : public A {
int e;
//..methods..
}
class F : public E,public C {
}
That is, other classes that are just an aggregation of a class derived from A
+ two extra ints inherited by C
and that can be passed to a funcion that takes *A
Thanks, did my best to be as clear as possible..
Your code is working because you used a C-style cast, which can be a reinterpret_cast
, and it's my understanding that you can reinterpret_cast
between any two pointer types, even if it doesn't make sense. You must use a dynamic_cast
when casting up from a multiply inherited base to a more derived class. A static_cast
would yield a compile-time error. In fact, dynamic_cast
does both jobs at once.
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
}
}
This is an excellent example of why C-style casts should be avoided.
You can read about multiple inheritance here.
What you need to do is virtually inherit next classes :
class B : virtual public A {
int b;
//...methods..
};
class C : virtual public A {
int c1,c2;
};
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With