Чистый виртуальный деструктор в C ++

163

Это неправильно писать:

class A {
public:
    virtual ~A() = 0;
};

для абстрактного базового класса?

По крайней мере, это компилируется в MSVC ... Будет ли сбой во время выполнения?

Иван Кречетов
источник
9
Может компилироваться, но есть ли ссылка?
Mooing Duck

Ответы:

218

Да. Вам также нужно реализовать деструктор:

class A {
public:
    virtual ~A() = 0;
};

inline A::~A() { }

должно хватить.

И так как это получило отрицательное голосование, я должен уточнить: если вы извлекаете что-то из A и затем пытаетесь удалить или уничтожить это, в Aконечном итоге будет вызван деструктор. Поскольку он чистый и не имеет реализации, возникнет неопределенное поведение. На одной популярной платформе это вызовет обработчик purecall и аварийное завершение работы.

Изменить: исправление декларации, чтобы быть более совместимым, скомпилировано с http://www.comeaucomputing.com/tryitout/

MSN
источник
16
Хм, да, это так. Pure only означает, что производный класс также должен предоставлять реализацию.
MSN
72
Реализация чисто виртуальных функций на самом деле является законной. Очень полезно для обеспечения реализации по умолчанию, но заставляет подклассы вызывать ее явно.
jmucchiello
6
MSN и обратите внимание, что если у вас есть это определение в заголовке, вам нужно поставить «inline» перед ним, чтобы избежать нарушения ODR (одно правило определения)
Йоханнес Шауб - litb
2
Почему A :: ~ A () должны быть явно определены, так как я думал, что для каждого объекта есть деструктор по умолчанию? Как и в любом типе наследования, цепочка деструкторов всегда вызывается, и деструктор базового класса не всегда должен быть определен.
JeffD
11
Лучший способ это сделать - объявив деструктор, он не будет автоматически реализован для вас.
MSN
49

Приватные деструкторы: они выдадут вам ошибку при создании объекта производного класса - не иначе. Диагностика может появиться, хотя.

12.4 Деструкторы

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

Класс с чистым виртуальным деструктором является абстрактным классом. Обратите внимание:

10.4 Абстрактные классы

2 Чистая виртуальная функция должна быть определена только в том случае, если она вызывается с помощью или, как если бы с (12.4), синтаксис квалифицированного идентификатора (5.1).

[ Примечание : объявление функции не может предоставить ни чистый спецификатор, ни определение - конечное примечание]

Взятые прямо с черновика:

struct C {
   virtual void f() = 0 { }; // ill-formed
};
dirkgently
источник
14
+1. Я думаю, что у Херба Саттера также есть хорошая информация об этом: gotw.ca/gotw/031.htm . Интересно отметить, что любая чисто виртуальная функция может иметь реализацию, а не только деструкторы.
Фред Ларсон
6
Да, это то, что вы делаете в интервью, чтобы пугать своих интервьюеров;)
dirkgently
1
По моему опыту, это не так уж редко.
@ Нил Баттерворт: какой?
dirkgently
@Dirk - сценарий "любая функция". Нередко бывает, что он используется для реализации некоторого общего поведения.