Компилятор не может оптимизировать vtable
переменную-член вне базового класса, поскольку в этом же или другом проекте может быть другой исходный файл, который будет содержать следующее:
struct ived : base {
ived() : p(new char[BIG_DATA_SIZE]) {}
virtual ~ived();
virtual void fn(int);
private:
char* p;
};
Деструктори fn
может быть реализован где-то еще:
ived::~ived() { delete[] p; }
void ived::fn(int) {
cout << "ived" << endl;
}
И где-то в другом месте может быть код, подобный этому:
base* object = new ived;
ived->fn(0);
delete object;
cout << sizeof(base) << endl;
Итак, возникнут две проблемы: виртуальная функцияived::fn
не вызывается, виртуальный деструктор не вызывается, поэтому BIG_DATA_SIZE
не удаляется.В противном случае sizeof(base)
здесь будет другим.Вот почему компиляторы всегда генерируют vtable
для любого класса с виртуальной функцией-членом или виртуальным базовым классом.
Что касается вызова деструкторов в производных классах, его необходимо рассматривать как обязательный: если у вас есть какой-либо класс с какой-либо виртуальной функцией, этот класс также должен объявить виртуальный деструктор.