Say we have the classic multiple inheritance schema:
class Base {
int baseMember;
};
class A : public Base {
int aMember;
};
class B : public Base {
int bMember;
};
class Derived : public A, public B {
int derivedMember;
};
This will lay out Derived objects in memory like this:
- Base's fields <-- (Base*)(A*)this | (A*)this | this
- A's fields
- Base's fields <-- (Base*)(B*)this | (B*)this
- B's fields
- Derived's fields
To prevent Base's fields from being duplicated, the default method is to inherite Base virtually from A and B:
class A : public virtual Base {
...
class B : public virtual Base {
This will cause the following layout:
- Offset to Base's fields <-- (A*)this | this
- A's fields
- Offset to Base's fields <-- (B*)this
- B's fields
- Derived's fields
- Base's fields <-- (Base*)this | (Base*)(A*)this | (Base*)(B*)this
This solves the problem, with the tradeoff that you have to apply the offset to access Base's fields (and virtual functions) from the other classes.
But why is the following not possible?
- Base's fields <-- (Base*)(B*)this | (Base*)(A*)this | (A*)this | this
- A's fields
- Offset to Base's fields <-- (B*)this
- B's fields
- Derived's fields
This would allow A and Derived to access Base without overhead, with no duplication and even shirinking the size by 1 integer. However, if I try it, the compiler still duplicates Base's fields (puts them behind B's fields).
note: I know similar questions have been asked, but I've not seen anything about why this isn't possible.
EDIT: Looking back at it 4 years later, it might have something to do with the fact that the "Offset to Base's fields" in Derived would have to be negative.