Будет ли созданный компилятором деструктор абстрактного базового класса виртуальным?
class Base
{
virtual void foo() = 0;
//~Base(); <-- No destructor!
};
Очевидно, что Base
будет выведено. Так говорит ли C++ деструктор, сгенерированный компилятором Base
должен быть виртуальным?
Спасибо!
4 ответа
Нет, деструктора не будет virtual
если вы не отметите это как таковой. Причина проста - вызовы могут быть сделаны практически как с помощью указателей, так и с помощью ссылок, и то, как и когда вы совершаете вызовы, практически не зависит от того, создаете ли вы объекты с new
, Если вы не создаете объекты с new
тебе не нужно delete
их и так вам не нужны виртуальные деструкторы.
Это не. Это близко к доказательству того, что деструктор не становится автоматически виртуальным:
#include <iostream>
struct BaseBase {
~BaseBase() {
std::cout << "~BaseBase\n";
}
};
struct Base : BaseBase
{
virtual void foo() = 0;
//~Base(); <-- No destructor!
};
struct Derived : Base {
void foo() { std::cout << "foo\n"; }
~Derived() {
std::cout << "~Derived\n";
}
};
int main() {
Base *p = new Derived();
delete p;
}
Эта программа на самом деле имеет неопределенное поведение, но я сильно подозреваю, что в вашей реализации она не печатает "~Derived". Если Base
если бы у него был виртуальный деструктор, то он не имел бы неопределенного поведения и вывел бы "~Derived".
Конечно, это на самом деле ничего не доказывает о стандарте. Любая реализация, на которой вы ее запускаете, может, в конце концов, быть не соответствующей. Но как только вы попробуете это на нескольких, вы поймете, что, что бы ни говорил стандарт, вам нужно указать виртуальный деструктор.
Нет, дтор не гарантированно будет виртуальным.
Когда объявляются классы, специально предназначенные для наследования, рекомендуется явно объявить виртуальный dtor. Обычно это прямой недостаток дизайна. На самом деле, я не могу вспомнить случай, когда не является недостатком дизайна опускать виртуальный dtor из базового класса.
Нет. Класс может иметь виртуальных членов, может быть получен и даже может быть распределен с помощью new
и удалены с delete
без виртуального деструктора.
Противозаконно (UB) уничтожить производный экземпляр с помощью delete
использование указателя на базу, если деструктор не объявлен виртуальным.
Конечно, нет никаких причин вообще не объявлять виртуальный деструктор, если ваш класс должен быть производным.