#c #virtual-destructor
#c #виртуальный деструктор
Вопрос:
У меня есть два класса:
class A {
public:
virtual void somefunction() = 0;
};
class B : public A {
public:
B();
~B();
void somefunction();
};
B::B() {}
void B::somefunction() {
// some code
}
Но с g я получаю ошибки:
class A has virtual functions and accessible non-virtual destructor
class B has virtual functions and accessible non-virtual destructor
Я понятия не имею, что это за ошибка… Где-то в блогах я читал, что это предупреждение компилятора. Как я могу решить проблему?
Ответ №1:
Это происходит потому, что ваш базовый класс A
не имеет виртуального деструктора. Например, если у вас был этот код:
int main()
{
A* a = new B;
delete a;
}
Тогда delete a
вызов не смог бы вызвать B
деструктор, потому что A
он не является виртуальным. (Это привело бы к утечке всех B
ресурсов.) Вы можете прочитать больше о виртуальных деструкторах здесь.
Добавьте виртуальный деструктор в свой базовый класс, и все должно быть в порядке.
class A
{
public:
virtual void somefunction() = 0;
virtual ~A() = default;
}
Комментарии:
1. @SPB Это означает, что не удалось найти реализацию вашего деструктора. Напишите тривиальный, если вам нечего на самом деле уничтожать.
A::~A() { }
должен это сделать.
Ответ №2:
Дайте классу A:
virtual ~A() { }
Таким образом, производные классы, такие как B, по-прежнему будут вызывать свой пользовательский деструктор, если вы delete
используете их через A*
.
Ответ №3:
Как правило большого пальца (IMHO) или, короче говоря, деструктор в базовом классе должен быть либо общедоступным и виртуальным, либо защищенным невиртуальным, чтобы предотвратить использование памяти leaks.by при этом вызываются деструкторы производного класса, и это предотвращает утечку памяти всякий раз, когда удаляется базовый указатель / ссылка, содержащий производный адрес / ссылку.
Комментарии:
1. Пока я согласен с этим. К сожалению, предупреждения GCC этого не делают. Т.е. он все равно будет выдавать это предупреждение при объявлении деструктора в базовом классе
protected
.
Ответ №4:
Если класс имеет виртуальные функции, то его деструктор также должен быть виртуальным. У вашего класса есть доступный деструктор, но он не виртуальный.