正面回答:

当基类的析构函数不是虚函数,并且基类指针指向一个派生类对象,然后通过基类指针来删除这个派生类对象时,如果基类的析构函数不是虚析构函数,那么派生类的析构函数就不会被调用,从而产生内存泄漏

#include<iostream>
#include<bits/stdc++.h>
using namespace std; class A
{
public:
A()
{
cout<<"constructing A"<<endl;
}
~A()
{
delete p;
cout<<"destructing A"<<endl;
}
private:
int *p;
}; class B:public A
{
public:
B()
{
cout<<"constructing B"<<endl;
}
~B()
{
delete p;
cout<<"destructing B"<<endl;
}
private:
int *p;
}; int main()
{ A *a=new B();
delete a;
}
/*
constructing A
constructing B
destructing A
*/

分析:只调用了基类A的析构函数,而派生类B的析构函数却没有被调用,这时会产生内存泄漏

如果给基类A的析构函数是虚析构函数,那么便不会产生这个问题

#include<iostream>
#include<bits/stdc++.h>
using namespace std; class A
{
public:
A()
{
cout<<"constructing A"<<endl;
}
virtual ~A()
{
delete p;
cout<<"destructing A"<<endl;
}
private:
int *p;
}; class B:public A
{
public:
B()
{
cout<<"constructing B"<<endl;
}
~B()
{
delete p;
cout<<"destructing B"<<endl;
}
private:
int *p;
}; int main()
{ A *a=new B();
delete a;
}
/*
constructing A
constructing B
destructing B
destructing A
*/

此时派生类B的析构函数被调用了!内存泄漏的问题得以解决

注意构造函数和析构函数的执行顺序:

派生类构造时:先执行基类的构造函数,然后执行派生类的构造函数

派生类析构时:先执行派生类的析构函数,然后执行基类的析构函数

上面内存泄漏产生的必要条件:

1.基类析构函数不是虚析构函数

2.派生类对象的析构函数中有内存需要回收

3.基类指针指向派生类对象,通过删除该基类指针来删除派生类对象

那这种情况下为什么会产生内存泄漏呢?

这种情况下,当删除基类指针指向的派生类对象时不会触发动态绑定,虚函数是动态绑定的基础,现在基类的析构函数不是虚函数,所以不会发生动态绑定,而是静态绑定,指针的静态类型为基类类型,所以delete的时候只会调用基类的析构函数

结论:

人生建议,继承时,基类的析构函数中最好加上virtual。

【C++】C++中基类的析构函数为什么要用virtual虚析构函数?的更多相关文章

  1. C++中基类的析构函数为什么要用virtual虚析构函数

    知识背景 要弄明白这个问题,首先要了解下C++中的动态绑定. 关于动态绑定的讲解,请参阅:  C++中的动态类型与动态绑定.虚函数.多态实现 正题 直接的讲,C++中基类采用virtual虚析构函数是 ...

  2. C++-基类的析构函数为什么要加virtual虚析构函数(转)

    知识背景 要弄明白这个问题,首先要了解下C++中的动态绑定. 关于动态绑定的讲解,请参阅:  C++中的动态类型与动态绑定.虚函数.多态实现 正题 直接的讲,C++中基类采用virtual虚析构函数是 ...

  3. C++中基类虚析构函数的作用及其原理分析

    虚析构函数的理论前提是 执行完子类的析构函数,那么父类的虚构函数必然会被执行. 那么当用delete释放一个父类指针所实例化的子类对象时,如果没有定义虚析构函数,那么将只会调用父类的析构函数,而不会调 ...

  4. 基类的析构函数写成virtual虚析构函数

    虚函数作用:动态绑定,实现多态效果. 场景问题: 派生类中有资源需要回收,而在编程中采用多态,由基类的指针指向派生类,则在释放的时候,如果基类的析构函数不是virtual,则派生类的析构函数得不到释放 ...

  5. 详解C++中基类与派生类的转换以及虚基类

    很详细!转载链接 C++基类与派生类的转换在公用继承.私有继承和保护继承中,只有公用继承能较好地保留基类的特征,它保留了除构造函数和析构函数以外的基类所有成员,基类的公用或保护成员的访问权限在派生类中 ...

  6. C++多态性中基类析构函数声明为虚函数

    在用基类指针指向派生类时, 在基类析构函数声明为virtual的时候,delete基类指针,会先调用派生类的析构函数,再调用基类的析构函数. 在基类析构函数没有声明为virtual的时候,delete ...

  7. lua中基类和“继承机制”

    基类:基类定义了所有对于派生类来说普通的属性和方法,派生类从基类继承所需的属性和方法,且在派生类中增加新的属性和方法. 继承:继承是C++语言的一种重要机制,它允许在已定义的类的基础上产生新类. lu ...

  8. (转) C++中基类和派生类之间的同名函数的重载问题

    下面有关派生类与基类中存在同名函数 fn: class A { public: void fn() {} void fn(int a) {} }; class B : public A { publi ...

  9. c++中基类与派生类中隐含的this指针的分析

    先不要看结果,看一下你是否真正了解了this指针? #include<iostream> using namespace std; class Parent{ public: int x; ...

随机推荐

  1. elementui 自定义表头 renderHeader的写法 给增加el-tooltip的提示

    1.html <el-table-column prop="taxes" :render-header="renderHeader" width=&quo ...

  2. APS的未来会怎么样?历史给了你答案

    一项技术从概念推广到实际应用推广需要十五到二十年时间,21世纪的头十年是APS的概念推广时期,随着理论的成熟,软件的实用化,企业应用的深入,下一个十年,APS将是实际应用推广的时期. APS兴起 从上 ...

  3. CDH报错:ScmActive at bootup: Failed to validate the identity of Cloudera Manager.

    报错原因以及解决办法在官网: https://www.cloudera.com/documentation/enterprise/5-8-x/topics/cm_failover_db.html 1. ...

  4. 使用Git Flow规范!

    Git Flow常用的分支 Production 分支 也就是我们经常使用的Master分支,这个分支最近发布到生产环境的代码,最近发布的Release, 这个分支只能从其他分支合并,不能在这个分支直 ...

  5. Nginx Rewrite相关功能-rewrite指令

    Nginx Rewrite相关功能-rewrite指令 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任.

  6. MySQL索引(九)

    一.索引介绍 1.1 什么是索引 索引就好比一本书的目录,它会让你更快的找到内容. 让获取的数据更有目的性,从而提高数据库检索数据的性能. 分为以下四种: BTREE:B+树索引(基本上都是使用此索引 ...

  7. 在eclipse中安装使用lombok插件

    Eclipse安装lombok插件 1.下载lombok.jar,lombok.jar官方下载地址:https://projectlombok.org/download 2.双击下载好的lombak. ...

  8. ajax中responseText与responseXML区别

    1."responseText”属性以字符串形式返回HTTP响应:“responseXML”属性以XML形式返回HTTP响应.function getTel() {  var telText ...

  9. Python实战之ATM+购物车

    ATM + 购物车 需求分析 ''' - 额度 15000或自定义 - 实现购物商城,买东西加入 购物车,调用信用卡接口结账 - 可以提现,手续费5% - 支持多账户登录 - 支持账户间转账 - 记录 ...

  10. KDiff3使用指南

    http://kdiff3.sourceforge.net/ KDiff3 is a diff and merge program that compares or merges two or thr ...