help-gplusplus
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: Virtual inheritance and vtables?


From: Colin D Bennett
Subject: Re: Virtual inheritance and vtables?
Date: Fri, 19 Oct 2007 16:34:24 -0700
User-agent: Thunderbird 2.0.0.6 (X11/20070912)

Samuli wrote:
> class A {int a;};
> 
> class B : public virtual A{};
> ...
> There are no virtual functions, so I thought there would be no
> extra pointers (to vtable) needed either. But it doesn't seem to 
> play out that way. 
> What information does that pointer point to? Why is it neccesary? 
> Can I avoid the generation of that extra pointer somehow, while still 
> using virtual base classes?

There is unavoidable overhead in using virtual base classes, so only use
them when they are to right tool for the job.

The reason is that A subobjects of instances of classes derived from B
must still be shared among all inherited classes where A is a virtual base.

For example:

#include <iostream>
class A {public: int a;};
class B : public virtual A{};
class C : public virtual A{};
class D : public B, public C {};

void use_B(B& b) { b.a = 42; }
int use_C(C& c) { return c.a; }

int main()
{
        D d;
        use_B(d);
        int value = use_C(d);
        std::cout << "c.a is " << value << '\n';
        std::cout << "sizeof(A)=" << sizeof(A) << '\n';
        std::cout << "sizeof(B)=" << sizeof(B) << '\n';
        std::cout << "sizeof(C)=" << sizeof(C) << '\n';
        std::cout << "sizeof(D)=" << sizeof(D) << '\n';
}

The output on my machine is:
c.a is 42
sizeof(A)=4
sizeof(B)=8
sizeof(C)=8
sizeof(D)=12

The data member of class A has been made public so that we can directly
access it, but that doesn't affect the object layout. Access to b.a and
c.a must use indirection through a pointer so that they both end up
accessing the same memory location. Instances of class D must have
subjects of both B and C. The when a B& is passed to use_B(), it is the
address of the B subobject within the D object that is passed. Likewise,
for use_C(), the C subobject's address is passed in.

Here is g++'s generated IA-32 assembly code for the functions using a
reference to a B object and a reference to a C object:

_Z5use_BR1B:  ;; void use_B(B& b)
        movl    4(%esp), %eax     ; get address of b -> %eax
        movl    (%eax), %edx      ; get A subobject offset -> %edx
        movl    -12(%edx), %edx   ;
        movl    $42, (%eax,%edx)  ;
        ret

_Z5use_CR1C:  ;; int use_C(C& c)
        movl    4(%esp), %edx
        movl    (%edx), %eax
        movl    -12(%eax), %eax
        movl    (%edx,%eax), %eax
        ret

Anyway, it's an interesting issue, but that's how virtual bases work.

Regards,
Colin





reply via email to

[Prev in Thread] Current Thread [Next in Thread]