C ++ Виртуальный деструктор все еще нужен, если в производной нет элементов данных? - PullRequest
12 голосов
/ 15 октября 2010

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

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

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

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

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

Ответы [ 3 ]

9 голосов
/ 15 октября 2010

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

Да.

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

Что будет, если это будет сделано?

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

7 голосов
/ 15 октября 2010

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

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

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

2 голосов
/ 15 октября 2010

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

Правило CPP High Integrity 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! 
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...