Нужно ли явно указывать базовый виртуальный деструктор?

При переопределении класса в С++ (с виртуальным деструктором) я снова реализую деструктор как виртуальный в наследующем классе, но мне нужно вызвать базовый деструктор?

Если так, я представляю себе что-то вроде этого...

MyChildClass::~MyChildClass() // virtual in header
{
    // Call to base destructor...
    this->MyBaseClass::~MyBaseClass();

    // Some destructing specific to MyChildClass
}

Я прав?

Ответ 1

Нет, деструкторы вызываются автоматически в обратном порядке построения. (Последние базовые классы). Не называйте деструкторы класса.

Ответ 2

Нет, вам не нужно вызывать базовый деструктор, базовый деструктор всегда вызывается вам производным деструктором. Пожалуйста, см. мой ответ здесь для порядка уничтожения.

Чтобы понять, зачем вам нужен виртуальный деструктор в базовом классе, см. следующий код:

class B
{
public:
    virtual ~B()
    {
        cout<<"B destructor"<<endl;
    }
};


class D : public B
{
public:
    virtual ~D()
    {
        cout<<"D destructor"<<endl;
    }
};

Когда вы выполните:

B *pD = new D();
delete pD;

Тогда, если у вас не было виртуального деструктора в B, вызывается только ~ B(). Но поскольку у вас есть виртуальный деструктор, вызывается первая ~ D(), затем ~ B().

Ответ 3

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

struct A {
   virtual ~A() {}
};

struct B : public A {
   virtual ~B() {}   // this is virtual
};

struct C : public A {
   ~C() {}          // this is virtual too
};

Ответ 4

Нет. В отличие от других виртуальных методов, где вы явно вызываете метод Base из Derived в цепочку вызова, компилятор генерирует код для вызова деструкторов в обратном порядке, в котором были вызваны их конструкторы.

Ответ 5

Нет. Он автоматически вызывается.

Ответ 6

Нет, вы никогда не вызываете деструктор базового класса, он всегда вызывается автоматически, как указали другие, но вот подтверждение концепции с результатами:

class base {
public:
    base()  { cout << __FUNCTION__ << endl; }
    ~base() { cout << __FUNCTION__ << endl; }
};

class derived : public base {
public:
    derived() { cout << __FUNCTION__ << endl; }
    ~derived() { cout << __FUNCTION__ << endl; } // adding call to base::~base() here results in double call to base destructor
};


int main()
{
    cout << "case 1, declared as local variable on stack" << endl << endl;
    {
        derived d1;
    }

    cout << endl << endl;

    cout << "case 2, created using new, assigned to derive class" << endl << endl;
    derived * d2 = new derived;
    delete d2;

    cout << endl << endl;

    cout << "case 3, created with new, assigned to base class" << endl << endl;
    base * d3 = new derived;
    delete d3;

    cout << endl;

    return 0;
}

Выход:

case 1, declared as local variable on stack

base::base
derived::derived
derived::~derived
base::~base


case 2, created using new, assigned to derive class

base::base
derived::derived
derived::~derived
base::~base


case 3, created with new, assigned to base class

base::base
derived::derived
base::~base

Press any key to continue . . .

Если вы установите деструктор базового класса как виртуальный, что следует сделать, то результаты для случая 3 будут такими же, как и для случаев 1 и 2.