Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Vtables

2 views
Skip to first unread message

vishnupriya...@gmail.com

unread,
Oct 14, 2007, 12:28:00 AM10/14/07
to
Will there be seperate Vtable for base class and derived class or
same
vtable will be shared by both?(virtual function being defined in both)


--
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]

Lance Diduck

unread,
Oct 14, 2007, 8:50:18 AM10/14/07
to
On Oct 14, 12:28 am, "vishnupriya.sureshb...@gmail.com"

<vishnupriya.sureshb...@gmail.com> wrote:
> Will there be seperate Vtable for base class and derived class or
> same
> vtable will be shared by both?(virtual function being defined in both)

You can think of the vtbl as a static array of function pointers, so
for example
struct B{
virtual int foo();
virtual void bar();
virtual ~B(){}};
would have a compiler generated construct that kind of looks like:
B::vtbl[]={&B::~B,&B::foo,&B::bar};
and a B instance would have a "hidden member" that is initialized in
every constructor
B::B():vptr(B::vtbl){}
When you make a derived class, then it looks like
struct D:B{
void foo();//override
virtual double bar2();//new function
};
the vtbl looks like
D::vtbl[]={&D::~D,&D::foo,&B::bar,&D::bar2};

and of course D's constructor makes vptr point to this table.
so when you have something like
B* b=new D;
b->foo();
the compiler generates code like:
*((b->vptr)+1)();//call second entry in D's vtbl


For the case of non virtual MI, there is a vptr for each inheritance
chain:
struct B2{virtual blah();virtual ~B2(){};int d;};
struct D2:B2,D{};
Now a compiler may construct the vtbl like
D2::vtbl[]={&D2::~D2 ,&B2::blah,&D2::~D2,&D::foo,&B::bar,&D::bar2};
and put two vptrs in D2, and initialized like
D2::D2():B2.vptr(vtbl),D.vptr(vtbl+2){}
Normally these vptr are the first data member in the object layout, it
may look like
struct D2_layout{
B2_vptr;
int B2_d;
D_vptr;
};
so a compiler may implement it something like
D2*d2=new D2;
d2->foo();//call foo defined by B
*((D*)((char*)d2+sizeof(B2))->vptr+1)();
//find the correct vptr, and call function found there

For virtual inheritance, the vptr essentially becomes a "virtual data
member" so if you had
struct VD:virtual B{};
struct VD2:virtual B{void bar();};//override bar
struct V:VD,VD2{};

there is (conceptually) a member placed in the VD and VD2 subobjects,
that point to the common B subobject. This B subobject vptr is made to
point to the V vtbl. So you have something like:
V::vtbl[&V::~V(),&B::foo,&VD2::bar]
with a constructor
V::V():B.vptr(V::vtbl),VD.B_ptr(&B),VD2.B_ptr(&B),B_ptr(&B)
VD*vd=new V;
vd->bar();
becomes something like
*(vd->B_ptr->vptr+1)();//call bar defined by VD2

This is all C++ pseudo code, and what the compiler actually does is
implementation specific. The standard does not require that virtuals
be implemented in terms of vtbls at all in fact.

The best book to find out more is Lippmans "Inside the C++ Object
Model"
Lance

jtorj...@yahoo.com

unread,
Oct 14, 2007, 7:40:51 PM10/14/07
to
On 14 Oct, 07:28, "vishnupriya.sureshb...@gmail.com"

<vishnupriya.sureshb...@gmail.com> wrote:
> Will there be seperate Vtable for base class and derived class or
> same
> vtable will be shared by both?(virtual function being defined in both)
>

First: why do you ask?
Second: why would you care?
Third: this is implementation dependent :)

Best,
John


--
http://John.Torjo.com -- C++ expert
... call me only if you want things done right

0 new messages