为什么delete基类指针时会调用基类的析构函数
时间: 2023-10-14 10:04:30 浏览: 102
当我们使用 `delete` 关键字删除一个基类指针时,实际上会调用基类的析构函数而不是派生类的析构函数。这是因为基类的析构函数是虚函数,派生类会继承该虚函数并且可以覆盖该虚函数。在运行时,编译器会根据指针实际指向的对象类型来确定要调用的虚函数,因此可以确保正确调用派生类的析构函数。但是当我们删除一个基类指针时,编译器只知道它指向的是一个基类对象,因此只会调用基类的析构函数,而不会调用派生类的析构函数。如果我们需要销毁一个派生类对象,我们应该使用派生类的指针来删除它,或者将基类的析构函数定义为虚析构函数。
相关问题
通过基类的指针删除派生对象时,通常情况下只调用基类的析构函数。但是,删除一个派生类的对象时应该先调派生类析构函数,然后调用基类的析构函数。解决办法:把基类的析构函数声明为虚析构函数
是的,当我们通过基类的指针删除派生类的对象时,如果基类的析构函数不是虚函数,那么通常情况下只会调用基类的析构函数,而不会调用派生类的析构函数,这可能导致资源泄漏和未定义的行为。
为了解决这个问题,我们需要将基类的析构函数声明为虚析构函数。虚析构函数是在基类中声明的虚函数,它在派生类中被重写,并确保在通过基类指针删除派生类对象时正确地调用派生类的析构函数,然后再调用基类的析构函数。
通过将基类的析构函数声明为虚析构函数,可以确保在删除派生类对象时正确地释放资源,避免内存泄漏和未定义的行为。因此,当我们设计一个基类用于派生其他类时,应该将其析构函数声明为虚析构函数。
借助虚析构函数编写以下程序:基类 Shape,其中定义了一个虚函数 printInfo() 。 两个派生类 Rectangle 和 Circle , 它们都重写 了 prinfInfo() 函数。使用基类指针数组来存储 Rectangle 和 Circle 对 象的地址,并依次调用它们的 printInfo() 函数。使用 delete 运算符来 删除指向 Shapes 对象的指针,需要使用虚析构函数以确保正确地调 用派生类的析构函数。
以下是程序代码:
```c++
#include <iostream>
using namespace std;
class Shape{
public:
virtual void printInfo(){
cout << "This is a shape." << endl;
}
virtual ~Shape(){};
};
class Rectangle: public Shape{
public:
void printInfo(){
cout << "This is a rectangle." << endl;
}
~Rectangle(){
cout << "Rectangle destructor called." << endl;
}
};
class Circle: public Shape{
public:
void printInfo(){
cout << "This is a circle." << endl;
}
~Circle(){
cout << "Circle destructor called." << endl;
}
};
int main(){
Shape* shapes[2];
shapes[0] = new Rectangle();
shapes[1] = new Circle();
for(int i=0; i<2; i++){
shapes[i]->printInfo();
delete shapes[i];
}
return 0;
}
```
程序首先定义了一个基类 Shape,其中定义了一个虚函数 printInfo()。然后定义了两个派生类 Rectangle 和 Circle,它们都重写了 printInfo() 函数。
程序接着定义了一个 Shape 类型的指针数组 shapes,用来存储 Rectangle 和 Circle 对象的地址。接下来使用循环依次调用它们的 printInfo() 函数,并使用 delete 运算符来删除指向 Shapes 对象的指针。需要使用虚析构函数来确保正确地调用派生类的析构函数。
程序输出结果为:
```
This is a rectangle.
Rectangle destructor called.
This is a circle.
Circle destructor called.
```
可以看到,程序成功地调用了派生类的析构函数。这是因为基类 Shape 的析构函数被声明为虚析构函数,这样在删除指向派生类对象的基类指针时就会调用派生类的析构函数。
阅读全文