I have a far more complicated class structure than this, but boiling the problem down to its essence, this describes my scenario: I have two classes, A & B, that implement pure virtual base classes that share a common ancestor, and then a third class C that com-posits A & B. Finally, a template class that fills in the common methods in the pure virtual base:
struct I {
virtual void r()=0;
};
struct A : I {};
struct B : I {};
struct C : A, B {
void q(){
r(); // the problem is here.
}
};
struct D : C {
virtual void r(){
}
};
C* c = new D;
c->q();
My problem is, I can't see any way to get C::q to call r().
void C::q(){
r(); // is ambiguous
A::r(); // is pure virtual
B::r(); // also is pure virtual
D::r(); // C doesn't know about D
((D*)this)->r(); // is dubious and requires C to know about D.
}
How can I call the r() method from C so that the correct virtual method is called?
Sorry, I should have clarified that virtual inheritance can't be used here. I have found two solutions:
struct C : A, B {
virtual void r()=0;
...
OR
struct C : A, B {
using A::r;
...
Both appear to disambiguate the call to r() sufficiently for everything to resolve.
Redeclare method r as pure virtual in C:
struct C : A, B {
void q(){
r(); // the problem is here.
}
virtual void r()=0;
};
Try virtual inheritance
struct A : virtual I {};
struct B : virtual I {};
Tell the compiler which part of the hierarchy to follow:
struct C : A, B {
void q(){
A * p = this;
p->r(); // recent GCC compiles this
}
};
It's ambiguous because the compiler doesn't know which r()
to call, the one coming from A or the one coming from B.
The easy way is to write:
static_cast<A*>(this)->r();
or
static_cast<B*>(this)->r();
But I think that none of this is the answer you're looking for. You clean up the situation by inheriting through virtual
the interface I:
struct A : virtual I {};
struct B : virtual I {};
Now, you can call
void C::q() { r(); }
as you would expect. The simple explanation of this is that, by using virtual, class C gets only one "copy" of the interface I, not two. This disambiguates your code.
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