Multiple Inheritance (Multiple Base Classes)


Consider these classes:
class myClassBase
{
public:
    int baseMember;
    myClassBase() { baseMember = 0; }
    int baseMethod(int x) { return baseMember + x; }
};
class myClassBase2
{
public:
    int baseMember2;
    myClassBase2() { baseMember2 = 0; }
    int baseMethod2(int x) { return baseMember2 + x; }
};
class myClassDerived : public myClassBase, public myClassBase2
{
public:
    int derivedMember;
    myClassDerived() { derivedMember = 0; }
    int derivedMethod(int x) { return derivedMember + x; }
};

The equivalent C code will be -
struct myClassBase
{
    int baseMember;
};
struct myClassBase2
{
    int baseMember2;
};
struct myClassDerived
{
    struct myClassBase base;
    struct myClassBase2 base2;
    int derivedMember;
};
void myClassBase_ctor(struct myClassBase *this)
{
    this->baseMember = 0;
}
int myClassBase_baseMethod(struct myClassBase *this, int x)
{
    return this->baseMember + x;
}
void myClassBase2_ctor(struct myClassBase2 *this)
{
    this->baseMember2 = 0;
}
int myClassBase2_baseMethod(struct myClassBase2 *this, int x)
{
    return this->baseMember2 + x;
}
void myClassDerived_ctor(struct myClassDerived *this)
{
    myClassBase_ctor((struct myClassBase*)this);
    void *ptr = (void*)this + offsetof(struct myClassDerived, base2);
    myClassBase2_ctor((struct myClassBase2*)ptr);
    this->derivedMember = 0;
}
int myClassDerived_derivedMethod(struct myClassDerived *this, int x)
{
    return this->derivedMember + x;
}

Here is diagram describing the all three class relations:
inheritance with multiple base classes
Points to understand:
Now you can understand how this code works-
myClassDerived *derived = new myClassDerived;
void *ptr = derived;
myClassDerived * derived2 = (myClassDerived *)ptr;
myClassBase *base1 = (myClassBase *)ptr;

Question: What is the issue with this code?
myClassBase2 *base2 = (myClassBase2 *)ptr;

Here the myClassBase2 object is casted from a void pointer. The compiler has no idea what is the offset of the myClassBase2 in the given object. In this case the compiler points to the first byte which is wrong in this case. If you will cast the myClassDerived* to myClassBase2* then the compiler knows the offset of myClassBase2 in the myClassDerived. The compiler knows it from the inheritance structure of the derived class and hence it will generate code to point to correct offset in the derived class object.


up

Want to learn (C/C++ internals) directly from the author using video call? Learn more

Do you collaborate using whiteboard? Please try Lekh Board - An Intelligent Collaborate Whiteboard App