Чистий віртуальний деструктор на 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
Гм, так. Чистий лише похідний клас також повинен забезпечити реалізацію.
MSN

72
Реалізація чистих віртуальних функцій насправді легальна. Дуже корисно для забезпечення реалізації за замовчуванням, але змушує підкласи чітко називати її.
jmucchiello

6
MSN і зауважте, якщо у вас є таке визначення у заголовку, перед цим потрібно поставити "встроєне", щоб уникнути порушення ODR (одне правило визначення)
Йоханнес Шауб - ліб

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
Так, це те, що ви робите в інтерв'ю, щоб
вигадати

1
Насправді, на моєму досвіді, це не все так часто.

@Neil Butterworth: Який?
примхливо

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