472,988 Members | 2,740 Online

# Size of classed with virtual functions

I have a doubt with size of classed with virtual functions
I have declared A,A1,A2 ,B , C, D some classes with no varaibles but a
vitual function each,
The size of A is as expected 4 bytes with one vtbl ptr
BUt when I derive the class B from class A (both have 1 virtual function
each ) the size remains still as 4 bytes .
class A = 4 bytes
class B :public A = 4 bytes
class C:public A,public A1 size = 8 Bytes
class D :public A,public A1,public A2 size = 12 bytes

Can some body explain this anamlous behavior
Thanks
Vijay
Jul 19 '05 #1
4 4379

"vijay" <ge********@yahoo.com> wrote in message
news:bf**********@news.mch.sbs.de...
I suppose the
"John Harrison" <jo*************@hotmail.com> wrote in message
news:bf************@ID-196037.news.uni-berlin.de...

"vijay" <ge********@yahoo.com> wrote in message
news:bf**********@news.mch.sbs.de...
I have a doubt with size of classed with virtual functions
I have declared A,A1,A2 ,B , C, D some classes with no varaibles but a vitual function each,
The size of A is as expected 4 bytes with one vtbl ptr
BUt when I derive the class B from class A (both have 1 virtual function each ) the size remains still as 4 bytes .
class A = 4 bytes
class B :public A = 4 bytes
class C:public A,public A1 size = 8 Bytes
class D :public A,public A1,public A2 size = 12 bytes

Can some body explain this anamlous behavior
Thanks
Vijay

class A has one vtable with one virtual function (4 bytes)
class B also has one vtable with two functions (4 bytes), the virtual
functions from A and B are combined into a single vtable, in other words B inherits A's virtual function.
class C multiply inherits, so it has two vtables, first vtable has 2
functions (one from A and one from C), second vtable has one function

(from
A1), but two vtables is 8 bytes no matter how many functions.
class D multiply inherits, three vtables, 12 bytes

john
=====================
I suppose the vtable u r refering to is inderiectly the vtbl ptr present

in the first 4 bytes of the object layout

Yes.
One more point I wanted to add is that the virtual function present in each class is only the destructor of the respective classes !!!
So from John's explanation I can deduce that
If a derived class is multiply inherited ,then first base class virtual
functions will be inherited in the VTable if the class B
That means to say class B obect layout will have a Vtblr ptr in its first 4 bytes which will point to a vtable which has 2 entries
1entry is destructor of class B and
2 entry destructor of class A
But for class C
First Vtbl ptr in first 4 bytes of obj layout will strore Vtbl address which has class c, class A virtual functions
Second vtbl ptr in next 4 bytes of object lay out will store vtbl address
which has class A1 virtual functions

Similarly for class D
But I wish to know why this is done this way
Why cant there be 1 Vtbl ptr which stores Vtbl which has all three
classes. ie Class C, Class A, Class A1 virtual functions ???? since class C inherits from both the classes!!!!

Thanks
Vijay

Of course its worth mentioning that different compiler can choose different
methods, but I'd imagine that class D has three vtable pointers because of
code like this

D d;
A2* a2 = &d;

a2 now points to the A2 object that is contained in d. So there must be a
complete A2 object inside each D object, with its own vtable. Thats why D
must have three vtables, because it is an aggregate of three sub objects,
each of which must be complete in its own right.

There's a book called 'Inside the C++ Object Model' by Stanley Lippman that
explains all this sort of stuff.

john
Jul 19 '05 #2
[snip]

Hey vjay,

the implementation of inheritance is implementation dependent, but allocated
somewhere else. For the 'common' implementation you state, picture the
following:

1. Each class (not instance), but each class has a table which contains
points to virutal functions. For example:
virtual ~A() -> 0x00FFAABB
virtual int getValue ->0x00AABBDD
...
This table is not included in the sizeof() function. It is located
somewhere.

2. Each instance of a singly-inhertied class has a pointer to the table( in
1) for its class. This is used to resolve virtual function calls.

3. Each instance of multiple-inherited class has 'n' pointers to tables of
its 'n' class it derived from.

Suppose classes A, B, and C exists and contain virtual functions
an instance of each looks like the following:

[Instance of class A,B, or C]
*************
vTable pointer
instance data
*************

So, a multiple inherited class might look like this:
class D derives from A,B, and C

[instance of class D]
**********************
vTable pointer of class D if class D contains any virtual functions
Instance of A
Instance of B
Instance of C
Instance of D data
**********************

Now why don't they just make a whole new virtual table for class B, that
includes all the entries for class A, B, and C instead of storing the
v-table ptr for A as part of the A-instance? Well suppose we have the
following legal code:

D *d = new D();
A* a = d;

What exactly would 'a' be pointer to if a single v-table-ptr were used for
D? It is this neccessity that basically forces each instance to have its
own v-table ptr.

Yamin
Jul 19 '05 #3

"Yamin" <ab*****@sdfdasfsd.com> wrote in message
news:Sb********************@news02.bloor.is.net.ca ble.rogers.com...

"Yamin" <ab*****@sdfdasfsd.com> wrote in message
news:Q9********************@news02.bloor.is.net.ca ble.rogers.com...
[snip]

Hey vjay,

the implementation of inheritance is implementation dependent, but allocated
somewhere else. For the 'common' implementation you state, picture the
following:

1. Each class (not instance), but each class has a table which contains
points to virutal functions. For example:
virtual ~A() -> 0x00FFAABB
virtual int getValue ->0x00AABBDD
...
This table is not included in the sizeof() function. It is located
somewhere.

2. Each instance of a singly-inhertied class has a pointer to the

table( in
1) for its class. This is used to resolve virtual function calls.

3. Each instance of multiple-inherited class has 'n' pointers to tables

of
its 'n' class it derived from.

Suppose classes A, B, and C exists and contain virtual functions
an instance of each looks like the following:

[Instance of class A,B, or C]
*************
vTable pointer
instance data
*************

So, a multiple inherited class might look like this:
class D derives from A,B, and C

[instance of class D]
**********************
vTable pointer of class D if class D contains any virtual functions
Instance of A
Instance of B
Instance of C
Instance of D data
**********************

Now why don't they just make a whole new virtual table for class B, that

That should be class D
includes all the entries for class A, B, and C instead of storing the
v-table ptr for A as part of the A-instance? Well suppose we have the
following legal code:

D *d = new D();
A* a = d;

What exactly would 'a' be pointer to if a single v-table-ptr were used for D? It is this neccessity that basically forces each instance to have its own v-table ptr.

Yamin

Ya , I know this reason, But my idea asking this question is in different
frame,
Why should first deried inherited class as explained by John shud get
clubbed with base class
Again look at my question, why is the size of B is 4 bytes and not 8 bytes,,

well John
U r explanation is good, But well any way I wish to read it again and get
back to u if I am still at doubt
Vijay

Jul 19 '05 #4

"vijay" <ge********@yahoo.com> wrote in message
news:bf**********@news.mch.sbs.de...

"Yamin" <ab*****@sdfdasfsd.com> wrote in message
news:Sb********************@news02.bloor.is.net.ca ble.rogers.com...

"Yamin" <ab*****@sdfdasfsd.com> wrote in message
news:Q9********************@news02.bloor.is.net.ca ble.rogers.com...
[snip]

Hey vjay,

the implementation of inheritance is implementation dependent, but allocated
somewhere else. For the 'common' implementation you state, picture the following:

1. Each class (not instance), but each class has a table which contains points to virutal functions. For example:
virtual ~A() -> 0x00FFAABB
virtual int getValue ->0x00AABBDD
...
This table is not included in the sizeof() function. It is located
somewhere.

2. Each instance of a singly-inhertied class has a pointer to the

table( in
1) for its class. This is used to resolve virtual function calls.

3. Each instance of multiple-inherited class has 'n' pointers to
tables
of
its 'n' class it derived from.

Suppose classes A, B, and C exists and contain virtual functions
an instance of each looks like the following:

[Instance of class A,B, or C]
*************
vTable pointer
instance data
*************

So, a multiple inherited class might look like this:
class D derives from A,B, and C

[instance of class D]
**********************
vTable pointer of class D if class D contains any virtual functions
Instance of A
Instance of B
Instance of C
Instance of D data
**********************

Now why don't they just make a whole new virtual table for class B,
that
That should be class D
includes all the entries for class A, B, and C instead of storing the
v-table ptr for A as part of the A-instance? Well suppose we have the
following legal code:

D *d = new D();
A* a = d;

What exactly would 'a' be pointer to if a single v-table-ptr were used

for D? It is this neccessity that basically forces each instance to have its own v-table ptr.

Yamin

Ya , I know this reason, But my idea asking this question is in different
frame,
Why should first deried inherited class as explained by John shud get
clubbed with base class
Again look at my question, why is the size of B is 4 bytes and not 8

bytes,,
well John
U r explanation is good, But well any way I wish to read it again and get
back to u if I am still at doubt
Vijay

When you have a simple case like

class A { virtual void f(); };
class B : public A { virtual void f(); virtual void g(); };

Then A and B can safely share the same vtable. The vtable for B will have
B::f(), B::g() in that order. If you then write

B b;
A* a_ptr = &b;

then it doesn't matter that a_ptr has a vtable with entries for f and g,
because you can't call g using a_ptr, the compiler will prevent that.

a_ptr->f(); // OK, calls B::f()
a_ptr->g(); // illegal, no such function in A

john
Jul 19 '05 #5

This thread has been closed and replies have been disabled. Please start a new discussion.