We have a multiple inheritance hierarchy:
// A B
// \ /
// C
//
Both A
and B
are abstract classes. C is actually a templated class, so downcasting is near impossible if you have a B
and you want to access a member of it as an A
.
All A
's and B
's must be C
's, since that is the only concrete class in the hierarchy. Therefore, all A
's must be B
's, and vice versa.
I'm trying to debug something quickly where I have a B
that I need to access A::name
of. I can't downcast to C
because I don't know the templated type of it. So I'm writing code like below and surprisingly it doesn't work; and I'm wondering what gives.
struct A { virtual void go() = 0; std::string name; };
struct B { virtual void go() = 0; };
struct C : A, B { void go() override { } };
int main()
{
C c;
c.name = "Pointer wonders";
puts(c.name.c_str()); // Fine.
B* b = (B*)&c;
//puts(b->name.c_str()); // X no from compiler.
A* a1 = (A*)&c;
puts(a1->name.c_str()); // As expected this is absolutely fine
// "Cross" the hierarchy, because the B really must be a __C__, because of the purely virtual functions.
// neither A nor B can be instantiated, so every instance of A or B must really be a C.
A* a2 = (A*)b;
puts(a2->name.c_str()); // Why not??
// If you downcast first, it works
C* c2 = (C*)b;
A* a3 = (A*)c2;
puts(a3->name.c_str()); // fine
}