Если у меня есть базовый класс с виртуальным деструктором. Имеет производный класс для объявления виртуального деструктора также?
class base {
public:
virtual ~base () {}
};
class derived : base {
public:
virtual ~derived () {} // 1)
~derived () {} // 2)
};
Конкретные вопросы:
final
, чтобы предотвратить его переопределение в производных классах, но это не мешает ему быть виртуальным. virtual
для виртуальных функций в производных классах для ясности. Людям не нужно проходить весь путь вверх по иерархии наследования, чтобы понять, что функция виртуальная. Кроме того, если ваш класс копируемый или перемещаемый без необходимости объявлять ваши собственные конструкторы копирования или перемещения, объявление деструктора любого типа (даже если вы определяете его как default
) заставит вас объявить копию и переместить конструкторы и операторы присваивания, если они вам нужны, поскольку компилятор больше не будет их вставлять. Небольшое замечание по пункту 3. В комментариях было указано, что если деструктор не объявлен, компилятор генерирует деструктор по умолчанию (который все еще является виртуальным). И эта функция по умолчанию - встроенная.
Встроенные функции потенциально подвергают большую часть вашей программы изменениям в других частях вашей программы и затрудняют двоичную совместимость разделяемых библиотек. Кроме того, усиление связи может привести к частой перекомпиляции перед лицом определенных видов изменений. Например, если вы решите, что вам действительно нужна реализация для вашего виртуального деструктора, тогда каждый фрагмент кода, который его вызвал, необходимо будет перекомпилировать. В то время как если бы вы объявили его в теле класса, а затем определили его пустым в файле .cpp
, вы могли бы изменить его без перекомпиляции.
Я по-прежнему предпочитаю опускать его, когда это возможно. На мой взгляд, это загромождает код, и компилятор иногда может делать немного более эффективные вещи с реализацией по умолчанию, а не с пустой.Но есть ограничения, которые могут сделать это плохим выбором.
1 / Да 2 / Да, он будет сгенерирован компилятором 3 / Выбор между объявлением его виртуальным или нет должен соответствовать вашему соглашение о переопределении виртуальных членов - ИМХО, есть хорошие аргументы в обе стороны, просто выберите один и следуйте ему.
Я бы пропустил его, если это возможно, но есть одна вещь, которая может побудить вас объявить это: если вы используете сгенерированный компилятором, он неявно встроен. Есть время, когда вы хотите избежать встроенных членов (например, динамических библиотек).
Виртуальная функция-член сделает неявно любую перегрузку этой функции виртуальной.
Таким образом, виртуальный объект в 1) является «необязательным», деструктор базового класса, являющийся виртуальным, делает все дочерние деструкторы виртуальными.