Antonio Antolcic
Antonio Antolcic

Reputation: 47

How is virtual function table generated in subclass

So I know that in c++ virtual methods are for each class stored in table and each instance has a pointer that points to that table. So my question how subclass table looks like. I will provide an assembler directive:

vtable for Derived:
    .long   0
    .long   _typeinfo for Derived
    .long   _Derived::set()
    .globl  _vtable for Base
    .section    .rdata$vtable for Base,"dr"
    .linkonce same_size
    .align 4

So, from here I can see that Derived has one virtual method which is set(), but the part which bugs me is vtable for Base. Does Derived vptr holds pointer to Base vptr or is it stored inside of Derived's vtable. I've noticed that in code compiler just stores vtable at 0 address of object, once in Base constructor and once in Derived. Why isn't vtable overwritten?

P.S. I don't really understand directives

EDIT:

class Base{
   virtual void print() {
       printf("Base");
   }
}

class Derived : Base{
   virtual void print(){
       printf("Derived");
   }
}

Upvotes: 0

Views: 923

Answers (1)

Jasper Kent
Jasper Kent

Reputation: 3676

Simple answer is: it depends on the compiler. The standard does not specify how this should be implemented, only how it should behave.

In practice, implementations tend to simply have a derived vtable which begins with the same structure as the base vtable, than appends the derived class methods on the end (that is to say new methods in the derived class, not overrides).

The vtable pointer just points the the beginning of the whole table. If the object is being accessed through a base pointer type, then no one should ever look beyond the end of the base class methods.

If the pointer is of the derived type, then the same pointer will allow access further down the table to virtual methods declared in the derived class.

ADDENDUM: Multiple Inheritance

Multiple inheritance follows the same basic concepts, but quickly becomes complex for obvious reasons. But there's one important feature to bear in mind.

A multiply derived class has one vtable pointer for each of its base classes, pointing to different vtables or different locations in the same vtable (implementation dependent).

But it's important to remember it's one per immediate base class per object.

Thus if you had a multiply derived class with one int of data and three immediate base classes, the size of each object would actually be 16 bytes (on a 32-bit system; more on 64-bit). 4 for the int and four each for each of the vtable pointers. Plus, of course, the sizes of each of the base classes themselves.

That means that in C++, interfaces are not cheap. (Obviously there are no true interfaces in C++, but a base class with no data and only pure virtual methods emulates it.) Each such interface costs the size of a pointer per object.

In languages like C# and Java, where interfaces are part of the language, there is a slightly different mechanism whereby all interfaces are routed through a single vtable pointer. This is slightly slower, but means only one vtable pointer per object, however many interfaces are implemented.

I'd still follow an interface style approach in C++ for design reasons, but always be aware of this additional overhead.

(And none of this even touches on virtual inheritance.)

Upvotes: 5

Related Questions