Деструктор по умолчанию в подклассах базового класса с виртуальным деструктором

У меня есть базовый класс A с виртуальным деструктором. A имеет потомков B а также C которые используют деструктор по умолчанию. Безопасно ли удалять объект C через указатель на A?

В частности, рассмотрим этот пример кода:

class A {
 public:
      A(){};
      virtual ~A() {/* code here */};
 };
 class B: public A {
      B() {/* code....*/};
      /* NO DESTRUCTOR SPECIFIED */
   };
 class C: public B {/*same as above, no destructor */};
 class D: public B {/* same as above, no destructor*/}

Код для запуска выглядит примерно так:

A* getAPointer(void); /* a function returning a C or a D*/
A* aptr=getAPointer();
/* aptr is declared as A*, but points to either an object of class C 
  or class D*/
delete aptr;

Это delete aptr безопасный? Делает ли это правильно: если aptr указывает на объект класса C, aptr первые звонки Cдеструктор, то Bдеструктор, и наконец Aдеструктор?

3 ответа

Решение

Безопасно ли удалять объект C через указатель на A?

Да, это абсолютно безопасно, так как все деструкторы в классах B, C а также D будет неявно виртуальным.

От:

15.4 Деструкторы [class.dtor]

10 Деструктор может быть объявлен виртуальным (13.3) или чисто виртуальным (13.4); если какие-либо объекты этого класса или любого производного класса созданы в программе, деструктор должен быть определен. Если у класса есть базовый класс с виртуальным деструктором, его деструктор (объявленный пользователем или неявно) является виртуальным.

Как A имеет виртуальный деструктор, то B, а также C, D соответственно есть виртуальные деструкторы и:

delete aptr;

работает правильно.

Да, это безопасно. Добавление virtual для деструкторов ваших производных классов является излишним.

Рассмотрим, как работает механизм. когда delete используется, среда выполнения должна знать, с какого деструктора должна начинаться цепочка уничтожения. Если статический тип delete операнд имеет virtual деструктор, тогда и этого достаточно для того, чтобы среда выполнения знала, что он должен принять дополнительные меры, и проверить динамический тип.

В вашем случае он обнаруживает, что динамический тип C, так C::~C называется. C::~C автоматически приводит к B::~B и это автоматически приводит к A::~A,

Требование к Cх (или Bх) деструктор virtual было бы бессмысленно. В конце концов, среда выполнения должна выяснить динамические C в любом случае, если A::~A является virtual, На этом этапе все равно, C::~C является virtual или нет. Какая разница это будет иметь?

Безопасно ли удалять объект C через указатель на A?

Да. поскольку Aдеструктор виртуален, Cдеструктор будет называться. Это просто из-за того, как работает динамическая диспетчеризация.

Другие вопросы по тегам