网站首页 > 文章精选 正文
虚析构函数
C++中基类采用virtual虚析构函数是为了防止内存泄漏。假设派生类中申请了内存空间,需要在析构函数中释放内存;若基类中采用的是非虚析构函数,当删除基类指针指向的派生类对象时就不会触发动态绑定,因而只会调用基类的析构函数,而不会调用派生类的析构函数。那么在这种情况下,派生类中申请的空间就得不到释放从而产生内存泄漏。所以,为了防止这种情况的发生,C++中基类的析构函数应采用virtual虚析构函数。
下面是基类和派生类中都没有虚析构函数的一个实例:
#include <iostream>
using namespace std;
class Base
{
public:
Base() //Base的构造函数
{
name = new char[100];
cout << "Base constructor" << endl;
}
~Base() //Base的析构函数
{
delete name;
name = nullptr;
cout << "Base destructor" << endl;
}
virtual void print()
{
cout << "Do something in class Base!" << endl;
};
private:
char* name;
};
class Derived : public Base
{
public:
Derived() //Derived的构造函数
{
name = new char[100];
cout << "Derived constructor" << endl;
}
~Derived() //Derived的析构函数
{
delete name;
name = nullptr;
cout << "Derived destructor" << endl;
}
void print()
{
cout << "Do something in class Derived!" << endl;
};
private:
char* name;
};
int main()
{
Derived* Test1 = new Derived(); //Derived类的指针
Test1->print();
delete Test1;
cout << endl;
Base* Test2 = new Derived(); //Base类的指针
Test2->print();
delete Test2;
return 0;
}
运行结果:
从运行结果可以看出,当通过基类指针删除派生类对象时,派生类的析构函数根本没有调用,name指针创建之后没有删除,导致内存泄漏。原因时派生类重写了基类析构函数,虽然派生类和基类的析构函数名字不同,但是编译器对析构函数做了特殊处理。在内部,派生类和基类的析构函数名字是一样的。所以当基类的析构函数为非虚函数时,就不能构成多态,基类的析构函数隐藏了派生类的析构函数,所以只能调用基类的析构函数。
下面是基类定义虚析构函数的一个实例:
#include <iostream>
using namespace std;
class Base
{
public:
Base() //Base的构造函数
{
name = new char[100];
cout << "Base constructor" << endl;
}
virtual ~Base() //Base的析构函数
{
delete name;
name = nullptr;
cout << "Base destructor" << endl;
}
virtual void print()
{
cout << "Do something in class Base!" << endl;
};
private:
char* name;
};
class Derived : public Base
{
public:
Derived() //Derived的构造函数
{
name = new char[100];
cout << "Derived constructor" << endl;
}
~Derived() //Derived的析构函数
{
delete name;
name = nullptr;
cout << "Derived destructor" << endl;
}
void print()
{
cout << "Do something in class Derived!" << endl;
};
private:
char* name;
};
int main()
{
Derived* Test1 = new Derived(); //Derived类的指针
Test1->print();
delete Test1;
cout << endl;
Base* Test2 = new Derived(); //Base类的指针
Test2->print();
delete Test2;
return 0;
}
运行结果:
从运行结果可以看出,定义了虚析构函数后,用一个基类的指针删除一个派生类的对象时,派生类的析构函数也被调用了。原因是当基类析构函数定义为虚函数后,删除对象时会直接调用派生类的析构函数,由于派生类析构时会先调用基类的析构函数,所以就把派生类和继承的基类都析构了。
总结:
- 基类的析构函数不加virtual关键字:当基类的析构函数不声明成虚析构函数,派生类继承基类,基类的指针指向派生类时,delete删除基类的指针,只调动基类的析构函数,而不调动派生类的析构函数。
- 基类的析构函数加virtual关键字:当基类的析构函数声明成虚析构函数,派生类继承基类,基类的指针指向派生类时,delete删除基类的指针,先调动派生类的析构函数,再调动基类的析构函数。
- 由于基类的析构函数为虚函数,所以派生类会在所有属性的前面形成虚表,而虚表内部存储的就是基类的虚函数。
- 当delete基类的指针时,由于派生类的析构函数与基类的析构函数构成多态,所以得先调动派生类的析构函数;之所以再调动基类的析构函数,是因为delete的机制所引起的,delete 基类指针所指的空间,要调用基类的析构函数。
猜你喜欢
- 2025-05-28 军事训练须走进“云”深处
- 2025-05-28 一文学会Eigen库
- 2025-05-28 宝鸡老师整理全国卷—抽象函数有魅力探究通法更给力
- 2025-05-28 是什么、为什么、怎么办?这里有个答案
- 2025-05-28 MySQL数据库的预处理详解
- 2025-05-28 彻底搞清楚内存泄漏的原因,如何避免内存泄漏,如何定位内存泄漏
- 2025-05-28 步步惊心,看“降魔神兵”如何克敌制胜……
- 2025-05-28 二进制兼容的C++接口
- 2025-05-28 C++面试题总结(二)
- 2025-05-28 C++真的很难学好?大师告诉你程序设计要怎么做
- 最近发表
- 标签列表
-
- newcoder (56)
- 字符串的长度是指 (45)
- drawcontours()参数说明 (60)
- unsignedshortint (59)
- postman并发请求 (47)
- python列表删除 (50)
- 左程云什么水平 (56)
- 计算机网络的拓扑结构是指() (45)
- 编程题 (64)
- postgresql默认端口 (66)
- 数据库的概念模型独立于 (48)
- 产生系统死锁的原因可能是由于 (51)
- 数据库中只存放视图的 (62)
- 在vi中退出不保存的命令是 (53)
- 哪个命令可以将普通用户转换成超级用户 (49)
- noscript标签的作用 (48)
- 联合利华网申 (49)
- swagger和postman (46)
- 结构化程序设计主要强调 (53)
- 172.1 (57)
- apipostwebsocket (47)
- 唯品会后台 (61)
- 简历助手 (56)
- offshow (61)
- mysql数据库面试题 (57)