С++ - это виртуальный деструктор, который все еще необходим, если нет элементов данных в производном?

Предположим, что у меня этот код

class Base{
  public:
        int getVal();
  private:
         int a, b;
};

class Derived::public Base{
    public:
         void printVal();
};

int main(){
    Base *b = new Derived();
    delete b;    
}

Я знаю, что виртуальный деструктор будет правильно удалять вещи, но плохо ли удалять с помощью базового указателя (когда нет виртуального деструктора), даже если нет виртуальных функций и нет элементов данных в производном классе? Что произойдет, если это будет сделано?

Ответ 1

Для данных примитивного типа ваш пример, скорее всего, будет работать на практике. Фактически, использование vtable может фактически помешать работе (поэтому здесь может быть какое-то законное использование), но технически undefined, для 5.3-5.4:

Если статический тип операнда [ оператор удаления] отличается от его динамический тип, статический тип должен быть базовым классом операнда динамический тип и статический тип иметь виртуальный деструктор или поведение undefined.

На самом деле все зависит от "кучи" данных в вашем классе, и поскольку в вашем случае нет выделенных кучей элементов (в вашем случае), вы должны быть в порядке, но это определенно запах кода.

Ответ 2

Неправильно ли удалять базовый указатель (если нет виртуального деструктора), даже если в производном классе нет никаких элементов данных и нет элементов данных?

Да.

Поведение undefined независимо от содержимого производного класса.

Что произойдет, если это будет сделано?

Все может случиться.

Ответ 3

Виртуальный дескриптор в производном классе необходим для правильного вызова производного деструктора (полиморфизма), когда производный объект создается с помощью указателя на базовый класс.

Правило CPP с высокой степенью целостности 3.3.2 Написание "виртуального" деструктора для базовых классов. (QACPP 2116)

Оправдание. Если объект когда-либо будет уничтожен с помощью указателя на его базовый класс, то этот базовый класс должен иметь виртуальный деструктор. Если деструктор базового класса не является виртуальным, будет вызван только деструктор для базового класса. В большинстве случаев деструкторы должны быть виртуальными, поскольку обслуживание или повторное использование могут добавлять производные классы, которым требуется виртуальный деструктор.

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

void foo() {  
   Derived* d = new Derived; delete d; // correctly calls derived destructor 
} 
void boo() { 
   Derived* d = new Derived; Base* b = d; delete b; // problem! does not call derived destructor! 
}