Будет ли созданный компилятором деструктор абстрактного базового класса виртуальным? - PullRequest
5 голосов
/ 12 августа 2011
class Base
{
    virtual void foo() = 0;
    //~Base();     <-- No destructor!
};

Очевидно, Base будет выведено.Итак, говорит ли C ++, что сгенерированный компилятором деструктор Base должен быть виртуальным?

Спасибо!

Ответы [ 4 ]

6 голосов
/ 12 августа 2011

Нет, деструктор не будет virtual, если вы не пометите его как таковой.Причина проста - вызовы могут быть сделаны практически как с помощью указателей, так и с помощью ссылок, и то, как и когда вы совершаете вызовы, фактически не связано с тем, создаете ли вы объекты с new.Если вы не создаете объекты с new, вам не нужно delete их, и поэтому вам не нужны виртуальные деструкторы.

2 голосов
/ 12 августа 2011

Это не так.Это близко к доказательству того, что деструктор не становится автоматически виртуальным:

#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».

Конечно, он на самом деле ничего не доказывает о стандарте.Любая реализация, на которой вы ее запускаете, может в конечном итоге быть несоответствующей.Но как только вы попробуете это на нескольких, вы поймете, что, что бы ни говорил стандарт, вам нужно указать виртуальный деструктор.

1 голос
/ 12 августа 2011

Нет. Класс может иметь виртуальных членов, может быть получен и даже может быть выделен с помощью new и удален с помощью delete без использования виртуального деструктора.

Недопустимым (UB) является уничтожение производного экземпляра с помощью delete с использованием указателя на базу , если деструктор не объявлен виртуальным.

Конечно, нет никаких оснований не объявлять виртуальный деструктор, если ваш класс должен быть производным.

1 голос
/ 12 августа 2011

Нет, dtor не гарантированно является виртуальным.

При объявлении классов, специально разработанных для наследования, рекомендуется явно объявить виртуальный dtor. Обычно это прямой недостаток дизайна. На самом деле, я не могу вспомнить случай, когда не является недостатком дизайна опускать виртуальный dtor из базового класса.

...