Чистый виртуальный деструктор в 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/


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
};

14
+1. Я думаю, что у Херба Саттера также есть хорошая информация об этом: gotw.ca/gotw/031.htm . Интересно отметить, что любая чисто виртуальная функция может иметь реализацию, а не только деструкторы.
— Фред Ларсон

6
Да, это то, что вы делаете в интервью, чтобы пугать своих интервьюеров;)
— dirkgently

1
По моему опыту, это не так уж редко.

@ Нил Баттерворт: какой?
— dirkgently

@Dirk - сценарий "любая функция". Нередко бывает, что он используется для реализации некоторого общего поведения.
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.