TecHNooB
Diamond Member
Cliffs: Why does pab == pac? (see code)
I'm reading a vanilla COM book about how to implement basic COM in C++. The trick is basically encapsulated in this piece of code (I think).
The class hierarchy is basically a diamond (A top, B left, C right, D bottom) and uses non virtual inheritance. Somehow, with this code, you get a hybrid between virtual and nonvirtual inheritance behavior but I don't know how/why.
Basically, you start by making a D object and a pointer to D. Because the inheritance is nonvirtual, there are two copies of A and you have to select which A you want (B's A or C's A). So if you want to get a pointer to A, you have to first cast to B or C and then to A.
Somehow, // #1 (see comment in code) always casts the pointer to the same A. What is happening in memory/compiler land that causes this to happen?
Note: Some includes are missing.
I'm reading a vanilla COM book about how to implement basic COM in C++. The trick is basically encapsulated in this piece of code (I think).
The class hierarchy is basically a diamond (A top, B left, C right, D bottom) and uses non virtual inheritance. Somehow, with this code, you get a hybrid between virtual and nonvirtual inheritance behavior but I don't know how/why.
Basically, you start by making a D object and a pointer to D. Because the inheritance is nonvirtual, there are two copies of A and you have to select which A you want (B's A or C's A). So if you want to get a pointer to A, you have to first cast to B or C and then to A.
Somehow, // #1 (see comment in code) always casts the pointer to the same A. What is happening in memory/compiler land that causes this to happen?
Note: Some includes are missing.
Code:
#include "stdafx.h"
#include <iostream>
using namespace std;
struct A
{
virtual void Afoo() = 0;
};
struct B : A
{
virtual void Bfoo() = 0;
};
struct C : A
{
virtual void Cfoo() = 0;
};
class D : public B, public C
{
public:
virtual void Afoo(){ cout << "AFOO" << endl; }
virtual void Bfoo(){ cout << "BFOO" << endl; }
virtual void Cfoo(){ cout << "CFOO" << endl; }
};
int _tmain(int argc, _TCHAR* argv[])
{
D *pd = new D();
// #1
A *pab = static_cast<B*>((void*)pd);
A *pac = static_cast<C*>((void*)pd);
cout << "pab = " << pab << endl;
cout << "pac = " << pac << endl;
B *pb = pd;
C *pc = pd;
pb->Bfoo();
pc->Cfoo();
cout << "pb = " << pb << endl;
cout << "pc = " << pc << endl;
// #2
A *pab2 = pb;
A *pac2 = pc;
cout << "pab2 = " << pab2 << endl;
cout << "pac2 = " << pac2 << endl;
D *pd2 = new D();
A *pab3 = static_cast<B*>((void*)pd2);
A *pac3 = static_cast<C*>((void*)pd2);
cout << "pab3 = " << pab3 << endl;
cout << "pac3 = " << pac3 << endl;
B *IB = dynamic_cast<B*>(pab);
C *IC = dynamic_cast<C*>(pac);
IB->Bfoo();
IC->Cfoo();
return 0;
}
Last edited: