senjes
senjes

Reputation: 23

C++ , Why Base class needs a VTable

From my understanding a VTable is necessary to call the most derived version of function. It will have entries about the most derived version of function ... My doubt is why we need to have a VTable for the base class. Since making calls with base object will always need to call the base class functions.

Upvotes: 2

Views: 1293

Answers (2)

mip
mip

Reputation: 8713

Since R Shau didn't like my edit, I provide my answer highly based on his.

VTable is a way to deal with polymorphism. While VTable is a technique widely used by C++ compilers, they are free to provide any other solution.

When a base class has one or more virtual member functions, the base class constructor assigns the VTable to an object.

The base class constructor has no way of knowing whether the real object being constructed is a base class object or a derived class object, so base object must keep pointer to point to valid VTable.

Example:

struct Base
{
    Base() {} 

    virtual void m() {}

    virtual ~Base() {}
};

struct Derived : public Base
{
    Derived() : Base() {}

    void m() override {}

    ~Derived() override {}
};

void foo()
{
    Base b;
    Derived d;

    Base * bPtr;
}

bPtr may point to Base

    bPtr = & b;
    bPtr->m();

or Derived

    bPtr = & d;
    bPtr->m();

Since bPtr is of type Base *, how to perform polymorphic call bPtr->m(), which should result in calling Base::m() if bPtr points to b and Derived::m() if bPtr points to d? Answer: look up for the address of m() method in VTable.

What happens when resolving bPtr->m() is something like that:

   bPtr pointing to Base object
   bPtr-> vtable_pointer -> VTable of Base -> m() -> points to address of Base::m()
   
   bPtr pointing to Derived object
   bPtr-> vtable_pointer -> VTable of Derived -> m() -> points to address of Derived::m()

So, without a VTable in base class, polymorphic calls could not be performed because at runtime it is not known if object pointed by bPtr is really a base class object or derived class object.

Upvotes: 3

R Sahu
R Sahu

Reputation: 206577

When a base class has one or more virtual member functions, the base class constructor assigns the VTable to an object.

The base class constructor has no way of knowing whether the real object being constructed is a base class object or a derived class object.

Example:

struct Base
{
    Base() {} 
    virtual ~Base() {}
};

struct Derived : public Base
{
    Derived() : Base() {}
    ~Derived() {}
};

void foo()
{
    Base b;
    Derived d;
}

Base::Base() gets called directly in the line

    Base b;

It gets called indirectly, via Derived::Derived() in the line

    Derived d;

How is the implementation of Base to know whether Base::Base() gets called directly for a Base or indirectly for a Derived? Without that knowledge, it has to make sure that it's behavior works for both of them -- which means set the VTable for both of them.

Upvotes: 1

Related Questions