Ответ 1
Нет, деструкторы вызываются автоматически в обратном порядке построения. (Последние базовые классы). Не называйте деструкторы класса.
При переопределении класса в С++ (с виртуальным деструктором) я снова реализую деструктор как виртуальный в наследующем классе, но мне нужно вызвать базовый деструктор?
Если так, я представляю себе что-то вроде этого...
MyChildClass::~MyChildClass() // virtual in header
{
// Call to base destructor...
this->MyBaseClass::~MyBaseClass();
// Some destructing specific to MyChildClass
}
Я прав?
Нет, деструкторы вызываются автоматически в обратном порядке построения. (Последние базовые классы). Не называйте деструкторы класса.
Нет, вам не нужно вызывать базовый деструктор, базовый деструктор всегда вызывается вам производным деструктором. Пожалуйста, см. мой ответ здесь для порядка уничтожения.
Чтобы понять, зачем вам нужен виртуальный деструктор в базовом классе, см. следующий код:
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().
Что сказали другие, но также обратите внимание, что вам не нужно объявлять деструктор виртуальным в производном классе. Как только вы объявите деструктор виртуальным, как и в базовом классе, все производные деструкторы будут виртуальными независимо от того, объявляете их так или нет. Другими словами:
struct A {
virtual ~A() {}
};
struct B : public A {
virtual ~B() {} // this is virtual
};
struct C : public A {
~C() {} // this is virtual too
};
Нет. В отличие от других виртуальных методов, где вы явно вызываете метод Base из Derived в цепочку вызова, компилятор генерирует код для вызова деструкторов в обратном порядке, в котором были вызваны их конструкторы.
Нет. Он автоматически вызывается.
Нет, вы никогда не вызываете деструктор базового класса, он всегда вызывается автоматически, как указали другие, но вот подтверждение концепции с результатами:
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.