Why is vptr required when a derived class does not override a virtual function?

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, the signature of the function fn defined in the base class is different from the signature of the function fn() defined in the class der , although the name of the function is the same. Therefore, the function defined in the der class hides the base function of the fn() class. Thus, the der class of fn cannot be called by calling p->fn(i) ; This is normal.

My point then, why sizeof class base or der is 4 if there is no VTABLE pointer? What does the VTABLE pointer need here?

+8
c ++ override virtual-functions vptr
source share
4 answers

Please note that this is implementation dependent and may vary for each compiler.

The requirement for vtable is that the base class is intended to be inherited and extended, and the class received from it can override the method.

The two classes Base and Derived can be in different translation units, and the compiler, when compiling the base class, will not know whether the method will be overridden or not. So, if it finds the virtual , it generates a vtable .

+6
source share

vtable is usually used not only for virtual functions, but is also used to identify the type of a class when executing some dynamic_cast or when a program accesses type_info for a class.

If the compiler detects that the virtual functions are never overridden and none of the other functions are used, it can simply remove the vtable pointer as an optimization.

Obviously, the author of the compiler did not consider it necessary to do this. Probably because it will not be used very often, and because you can do it yourself by removing virtual from the base class.

+1
source share

The compiler cannot optimize the vtable member variable from the 'base' class, because there may be another source file in the same or another project, which will 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 can be implemented somewhere else:

 ived::~ived() { delete[] p; } void ived::fn(int) { cout << "ived" << endl; } 

And somewhere else there might be a code like this:

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

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

As for calling destructors in derived classes, it should be considered mandatory: if you have any class with any virtual function, this class must also declare a virtual destructor.

+1
source share

Inheritance is an is-a relationship. der is-a base . base is 4 , der will be at least 4 . vftableptr is a member of base , he will be a member of der .

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

0
source share

All Articles