пожалуйста, пройдите мой код ниже:
#include "stdafx.h"#include <iostream>
#include <conio.h>
using namespace std;
class ClassA
{
protected:
int width, height;
public:
void set_values(int x, int y)
{
width = x;
height = y;
}
virtual int area()
{
return 100;
}
~ClassA()
{
cout << "base class destructor called" << endl;
}
};
class ClassB : public ClassA
{
public :
int area()
{
return (width * height);
}
~ClassB()
{
cout << "derived class destructor called" << endl;
}
};
int main()
{
ClassA *Ptr = new ClassB;
Ptr->set_values(10, 20);
cout << Ptr->area() << endl;
delete Ptr;
return 0;
}
В приведенном выше коде указатель содержит адрес объекта производного класса, поэтому он должен вызывать деструктор производного класса вместе с деструктором базового класса, когда я удаляю указатель, но почему он вызывает только деструктор базового класса. если я сделал деструктор базового класса виртуальным, то он вызывает деструктор как производного класса, так и деструктора базового класса. Почему? и в случае виртуальных функций и базовый, и производный класс имеют одно и то же имя функции, поэтому компилятор разрешает тот, который наиболее производен в производном классе, но здесь деструктор не будет иметь того же имени, что и компилятор, который будет вызывать тот, который он должен вызвать во время выполнения. пожалуйста, объясните мне, как
Вы должны сделать деструктор вашего базового класса virtual
для правильной работы полиморфного разрушения:
class ClassA
{
// ...
virtual ~ClassA()
// ^^^^^^^
// Add this!
{
cout << "base class destructor called" << endl;
}
};
Если вы этого не сделаете, вы получите Неопределенное поведение когда делаешь delete Ptr
,
если я сделал деструктор базового класса виртуальным, то он вызывает деструктор как производного, так и базового класса. Почему?
Это часть обычной последовательности уничтожения объектов. Когда вы уничтожаете объект, сначала вызывается деструктор класса этого объекта, а затем деструкторы всех нестатических членов класса этого объекта (в обратном порядке объявления), тогда деструкторы всех его базовых классов.
Таким образом, виртуальная диспетчеризация здесь выполняется правильно (если вы делаете деструктор вашего базового класса virtual
, конечно), в том смысле, что первый вызываемый деструктор является деструктором фактического типа времени выполнения вашего объекта (ClassB
). После этого деструктор базового класса ClassA
вызывается, а также является частью нормального процесса уничтожения.
но здесь деструктор не будет иметь такого же имени, как компилятор решает, какой из них он должен вызывать во время выполнения
Деструкторы специальные функции-члены. Каждый класс может иметь только один деструктор, поэтому их имя (которое должно совпадать с именем класса, с добавленным ~
характер) не имеет значения. Компилятор знает, какая функция является деструктором.
Потому что ваш деструктор базового класса должен быть virtual
,
Вот собственно неопределенное поведение так как ~ClassA()
не является virtual
так что все может случиться.
ClassA *Ptr = new ClassB;
///....
delete Ptr;
Вы должны пометить ваши деструкторы как виртуальные. В противном случае компилятор не знает, как вызвать деструктор самого производного.
virtual ~ClassA()
{
cout << "base class destructor called" << endl;
}