How is C++'s multiple inheritance implemented?

故事扮演 提交于 2019-11-30 04:44:13

The following paper from the creator of C++ describes a possible implementation of multiple inheritance:

Multiple Inheritance for C++ - Bjarne Stroustrup

There was this pretty old MSDN article on how it was implemented in VC++.

And then, if I do a cast:

SecondBase base = (SecondBase *) object_with_base1_and_base2_parents;

The compiler must consider whether to alter or not the original pointer. Similar tricky things with virtuals.

With non-virutal inheritance this is less tricky than you might think - at the point where the cast is compiled, the compiler knows the exact layout of the derived class (after all, the compiler did the layout). Usually all that happens is a fixed offset (which may be zero for one of the base classes) is added/subtracted from the derived class pointer.

With virutal inheritance it is maybe a bit more complex - it may involve grabbing an offset from a vtbl (or similar).

Stan Lippman's book, "Inside the C++ Object Model" has very good descriptions of how this stuff might (and often actually does) work.

Parents are arranged in the order that they're specified:

class Derived : A, B {} // A comes first, then B

class Derived : B, A {} // B comes first, then A

Your second case is handled in a compiler-specific manner. One common method is using pointers that are larger than the platform's pointer size, to store extra data.

This is an interesting issue that really isn't C++ specific. Things get more complex also when you have a language with multiple dispatch as well as multiple inheritance (e.g. CLOS).

People have already noted that there are different ways to approach the problem. You might find reading a bit about Meta-Object Protocols (MOPs) interesting in this context...

Its entirely down to the compiler how it is done, but I beleive its generally done througha heirarchical structure of vtables.

I have performed simple experiment:

class BaseA { int a; };
class BaseB { int b; };
class Descendant : public BaseA, BaseB {};
int main() {
        Descendant d;
        BaseB * b = (BaseB*) &d;
        Descendant *d2 = (Descendant *) b;
        printf("Descendant: %p, casted BaseB: %p, casted back Descendant: %p\n", &d, b, d2);
}

Output is:

Descendant: 0xbfc0e3e0, casted BaseB: 0xbfc0e3e4, casted back Descendant: 0xbfc0e3e0

It's good to realise that static casting does not always mean "change the type without touching the content". (Well, when data types do not fit each other, then there will be also an interference into content, but it's different situation IMO).

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!