Question

class base {
public:
    void virtual fn(int i) {
        cout << "base" << endl;
    }
};

class der : public base{
    public:
    void  fn(char i) {
        cout << "der" << endl;
    }
};

int main() {

    base* p = new der;
    char i = 5;
    p->fn(i);
    cout << sizeof(base);
    return 0;
}

Here signature of function fn defined in base class is different from signature of function fn() defined in der class though function name is same. Therefore, function defined in der class hides base class function fn(). So class der version of fn cannot be called by p->fn(i) call; It is fine.

My point is then why sizeof class base or der is 4 if there is no use of VTABLE pointer? What is requirement of VTABLE pointer here?

Was it helpful?

Solution

Note that this is highly implementation dependent & might vary for each compiler.

The requirement for presence of vtable is that the Base class is meant for Inheritance and extension, and a class deriving from it might override the method.

The two classes Base and Derived might reside in different Translation Unit and the compiler while compiling the Base class won't really know if the method will be overidden or not. So, if it finds the keyword virtual it generates the vtable.

OTHER TIPS

The vtable is usually not only used for virtual functions, but it is also used to identify the class type when you do some dynamic_cast or when the program accesses the type_info for the class.

If the compiler detects that no virtual functions are ever overridden and none of the other features are used, it just could remove the vtable pointer as an optimization.

Obviously the compiler writer hasn't found it worth the trouble of doing this. Probably because it wouldn't be used very often, and because you can do it yourself by removing the virtual from the base class.

The compiler cannot optimize out vtable member variable out of 'base' class, because there could be another source file within the same or another project which would contain the following:

struct ived : base {
    ived() : p(new char[BIG_DATA_SIZE]) {}
    virtual ~ived();
    virtual void fn(int);
private:
    char* p;
};

The destructor and fn could be implemented somewhere else:

ived::~ived() { delete[] p; }

void ived::fn(int) {
    cout << "ived" << endl;
}

And somewhere in another place there could be code like this:

base* object = new ived;
ived->fn(0);
delete object;
cout << sizeof(base) << endl;

So, there would be two problems: virtual function ived::fn not called, virtual destructor not called, so BIG_DATA_SIZE not deleted. Otherwise, sizeof(base) here would be different. That is why compilers always generate vtable for any class with a virtual member function or a virtual base class.

Regarding calling destructors in derived classes, it must be considered as a must: if you have any class with any virtual function, that class shall also declare a virtual destructor.

Inheritance is a is-a relationship. der is-a base. base has size 4, der will have at least size 4. vftableptr is a member of base, it will be a member of der.

base has a virtual method, so it will have a pointer to the virtual table, regardless of whether you use it or not.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top