在下面代码中,父类指针指向了子类对象,通过 new 创建出来的子类对象的内存在堆空间,但 delete 时并没有调用子类的析构函数,如下图所示。
#include <iostream>
using namespace std;
class Animal
{
public:
Animal() { cout << "Animal::Animal()" << endl; }
void speak() { cout << "Animal::speak()" << endl; }
void run() { cout << "Animal::run()" << endl; }
~Animal() { cout << "Animal::~Animal()" << endl; }
};
class Cat : public Animal
{
public:
Cat() { cout << "Cat::Cat()" << endl; }
void speak() { cout << "Cat::speak()" << endl; }
void run() { cout << "Cat::run()" << endl; }
~Cat() { cout << "Cat::~Cat()" << endl; }
};
int main()
{
Animal* p = new Cat();
delete p;
return 0;
}
输出结果如下:
如果存在父类指针指向子类对象的情况,应该将父类的析构函数声明为虚函数。这样 delete 父类指针时,才会调用子类的析构函数,保证析构的完整性。
只要父类的析构函数是虚函数,那么子类的析构函数也自动变成虚函数,尽管两者名字不同。
结论:如果一个类想要做基类,那么必须要把这个类的析构函数声明为虚函数。
#include <iostream>
using namespace std;
class Animal
{
public:
Animal() { cout << "Animal::Animal()" << endl; }
void speak() { cout << "Animal::speak()" << endl; }
void run() { cout << "Animal::run()" << endl; }
virtual ~Animal() { cout << "Animal::~Animal()" << endl; }
};
class Cat : public Animal
{
public:
Cat() { cout << "Cat::Cat()" << endl; }
void speak() { cout << "Cat::speak()" << endl; }
void run() { cout << "Cat::run()" << endl; }
~Cat() { cout << "Cat::~Cat()" << endl; }
};
int main()
{
Animal* p = new Cat();
delete p;
return 0;
}
输出结果如下: