класс имеет виртуальные функции и доступный невиртуальный деструктор

#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:

Если класс имеет виртуальные функции, то его деструктор также должен быть виртуальным. У вашего класса есть доступный деструктор, но он не виртуальный.