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.
Alexey Omelchenko
source share