Size of classed with virtual functions

V

vijay

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
 
J

John Harrison

vijay said:
I suppose the

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
 
Y

Yamin

[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
 
V

vijay

Yamin said:
Yamin said:
[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
 
J

John Harrison

vijay said:
Yamin said:
Yamin said:
[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
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
474,127
Messages
2,570,755
Members
47,315
Latest member
robertsoker

Latest Threads

Top