After learnt from : Why can't static_cast be used to down-cast when virtual inheritance is involved?
I'm expecting following code give me the result that shows the static_cast is wrong and dynamic_cast is right.
#include <stdio.h>
class A {
public:
virtual ~A() {}
int a;
};
class B : public virtual A {
int b;
};
class C : public virtual A {
int c;
};
class D : public B, public C {
int d;
};
int main() {
D obj;
A* a1 = &obj;
A* a2 = (A*)&obj;
A* a3 = dynamic_cast<A*>(&obj);
A* a4 = static_cast<A*>(&obj);
C* c = &obj;
A* a5 = c;
A* a6 = (A*)(c);
A* a7 = dynamic_cast<A*>(c);
A* a8 = static_cast<A*>(c);
B* b = &obj;
A* a9 = b;
A* a10 = (A*)b;
A* a11 = dynamic_cast<A*>(b);
A* a12 = static_cast<A*>(b);
printf("D: %llx %llx %llx %llx %llx\n", &obj, a1, a2, a3, a4);
printf("C: %llx %llx %llx %llx %llx\n", c, a5, a6, a7, a8);
printf("B: %llx %llx %llx %llx %llx\n", b, a9, a10, a11, a12);
}
However, gcc 8/9 gives me following reuslt, showing both static cast and dynamic cast is correct:
D: 7ffddb098a80 7ffddb098aa0 7ffddb098aa0 7ffddb098aa0 7ffddb098aa0
C: 7ffddb098a90 7ffddb098aa0 7ffddb098aa0 7ffddb098aa0 7ffddb098aa0
B: 7ffddb098a80 7ffddb098aa0 7ffddb098aa0 7ffddb098aa0 7ffddb098aa0
So what's the magic involved here? How can I make a case that reproduce the static_cast problem?
Note:
gcc8 with -fdump-lang-class
gives me following output:
Class D
size=48 align=8
base size=32 base align=8
D (0x0x7f0756155000) 0
vptridx=0 vptr=((& D::_ZTV1D) + 24)
B (0x0x7f0755f834e0) 0
primary-for D (0x0x7f0756155000)
subvttidx=8
A (0x0x7f075614c0c0) 32 virtual
vptridx=40 vbaseoffset=-24 vptr=((& D::_ZTV1D) + 104)
C (0x0x7f0755f83548) 16
subvttidx=24 vptridx=48 vptr=((& D::_ZTV1D) + 64)
A (0x0x7f075614c0c0) alternative-path
Not sure, but it seems like you confuse upcasting with downcasting. In your code there are only upcasts, and those are fine. You get the expected compiler error for example with this:
D obj;
A* a4 = static_cast<A*>(&obj);
D* d = static_cast<D*>(a4);
<source>: In function 'int main()':
<source>:26:28: error: cannot convert from pointer to base class 'A' to pointer to derived class 'D' because the base is virtual
26 | D* d = static_cast<D*>(a4);
| ^
If you remove the virtual inheritance in your example the static_cast
would fail as well, because then the cast is ambiguous.