2010-10-15 1 views
10

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

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

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

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

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

ответ

5

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

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

Это действительно все зависит от «heapness» данных в своем классе, а так как нет ни одного куч распределённых пользователей (в вашем случае), вы должны быть хорошо, но это, безусловно, код запах.

+2

Спасибо, Дэвид. – snk

+3

Опасно полагаться на вещи, которые, скорее всего, будут работать, и предположить, что вы «должны быть в порядке». Гораздо лучше написать код, который работает _will_, тогда вы, знаете, все в порядке. –

+0

Джеймс, я буду уверен, что всегда есть виртуальный деструктор. Это просто гипотетический вопрос, заданный кем-то, и у него не было ответа. Еще раз спасибо вам. – snk

9

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

Да.

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

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

Все может произойти.

+1

Большое спасибо Джеймсу. – snk

+3

+1 для «Все может случиться». Что-нибудь! Абсолютно ничего! :) – ybungalobill

2

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

Правило высокой точности Целочисленности 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! 
} 
+0

Я думаю, вы имели в виду, что ваш деструктор назывался '~ Derived', а не' ~ C' ... –

+0

@ Майк Эллери, да, это то, что я хотел иметь в виду. Я исправил код. – ArBR