虽然我们已经知道了什么是继承和多态,也明白了多态依赖于继承,但是在多态中存在哪些问题呢?

多态中可能存在的内存泄露问题

例如下面的程序中,在圆形Circle的类中定义一个圆心的坐标,并且坐标是在堆中申请的内存,则在mian函数中通过基类指针操作派生类对象的成员函数是没有问题的,可是在销毁对象内存的时候则只是执行了基类的析构函数,派生类的析构函数却没有执行,这会导致内存泄漏。换句话说如果delete后边跟基类的指针则只会执行基类的析构函数,如果delete后面跟的是派生类的指针,那么它即会执行派生类的析构函数,也会执行基类的析构函数

class Shape
{
public:virtual double calcArea(){...}//虚函数
    Shape();~Shape();....
private:....
};
Shape::Shape()
{
cout<<"class Shape was created"<<endl;
}
Shape::~Shape()
{
cout<<"class Shape was deleted"<<endl;
}
class Circle:public Shape
{
public:Circle(int x,int y,double r);~Circle();virtual double calcArea();//此处可不加virtual,但系统默认加上
    ....
private:double m_dR;Coordinate *m_pCenter;      //坐标类指针
    ....
};
Circle::Circle(int x,int y,double r)
{m_pCenter=new Coordinate(x,y);m_dR=r;cout<<"class Circle was created"<<endl;
}
Circle::~Circle()
{delete m_pCenter;m_pCenter=NULL;cout<<"class Circle was deleted"<<endl;
}
....
int main()
{Shape *shape1=new Circle(5,6,4.0);//基类对象,改成Circle *circle=new Circle(5,6,4.0)则为派生类对象shape1->calcArea();delete shape1;shape1=NULL;//派生类对象的内存未回收return 0;
}

打印结果可见,派生类的析构函数并没有被执行,而只是回收了开辟给基类对象的空间,那如何解决这个问题呢,固然可以通过delete派生类对象实现,除此之外,还可以引入虚析构函数,你看普通的虚函数都可以实现多态的动态联编,那对于析构函数呢?虚析构函数也会在最后对象销毁内存时动态链接到派生类对象。
可以这样解释它:如果基类当中定义了虚析构函数,那么基类的虚函数表当中就会有一个基类的虚析构函数的入口指针,指向的是基类的虚析构函数,派生类的虚函数表当中也会产生一个派生类的虚析构函数的入口指针,指向的是派生类的虚析构函数,这个时候使用基类的指针指向派生类的对象,delete掉基类指针,就会通过指向的基类的对象找到基类的虚函数表指针,从而找到虚函数表,在虚函数表中找到派生类的虚析构函数,从而使得派生类的析构函数得以执行,派生类的析构函数执行之后系统会自动执行父类的虚析构函数。即整个执行过程是:
  1. 基类的构造函数;
  2. 派生类的构造函数;
  3. ......
  4. 派生类的析构函数;
  5. 基类的析构函数。

virtual关键字可以修饰普通的成员函数,也可以修饰析构函数,但并不是没有限制

virtual在函数中的使用限制

  • 普通函数不能是虚函数,也就是说这个函数必须是某一个类的成员函数,不可以是一个全局函数,否则会导致编译错误。
  • 静态成员函数不能是虚函数 static成员函数是和类同生共处的,他不属于任何对象,使用virtual也将导致错误。
  • 内联函数不能是虚函数 如果修饰内联函数 如果内联函数被virtual修饰,计算机会忽略inline使它变成存粹的虚函数。(inline将会在后面的博客中介绍)
  • 构造函数不能是虚函数,否则会出现编译错误。

转载于:https://www.cnblogs.com/cvtoEyes/p/8492247.html

继承和多态二:虚析构函数相关推荐

  1. 初入c++(六)虚函数实现多态,虚析构函数,虚函数表和多态实现机制,纯虚函数。

    1.c++多态的概念以及用途. 1.1虚函数实现多态 通过基类指针只能够访问派生类的成员变量,不能够访问派生类的成员函数. 解决问题的办法:使用虚函数(virtual function),只需要在函数 ...

  2. C++之继承探究(七):虚析构函数

    前文:C++之继承探究(六):虚函数和多态 虚析构函数   虚析构函数是为了解决基类的指针指向派生类对象,并用基类的指针删除派生类对象时防止子类的数据不会被释放造成内存泄露.   如果父类的析构不是虚 ...

  3. C#继承与多态 virtual虚方法的使用 在子类中使用override重写父类函数

    本片文章讲的是多态 子类重写父类函数的方式如下:在父类函数使用virtual,在子类函数中使用override 注意定义变量的时候要使用new来创建,而不要使用类名 变量名的方式,否则在使用时会报错& ...

  4. c++ map 析构函数_C++|类继承关系中的虚函数、虚析构函数、虚基类

    在继承关系中,虚函数.虚析构函数.虚基类中使用的关键字virtual都是在告诉编译器,此处要进行特殊处理: 虚函数:函数重写时的要求编译器动态绑定来实现多多态 : 虚析构函数:当基类指针指向在堆内实现 ...

  5. C++——虚函数、虚析构函数、纯虚函数、抽象类

    目录 一.虚函数 1.什么是虚函数? 2.虚函数的作用 3.虚函数的参数 4.虚函数代码示例 二.虚析构函数 1.什么是虚析构函数? 2.虚析构函数的作用 3. 构造函数 4.为什么构造函数不能是虚函 ...

  6. [C++]虚析构函数的作用

    C++中的虚析构函数到底什么时候有用的,什么作用呢. 一.虚析构函数的作用 总的来说虚析构函数是为了避免内存泄露,而且是当子类中会有指针成员变量时才会使用得到的.也就说虚析构函数使得在删除指向子类对象 ...

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

    参考http://blog.csdn.net/xiamentingtao/article/details/55517203 C++中的虚析构函数到底什么时候有用的,什么作用呢. 一.虚析构函数的作用 ...

  8. unique函数_C++智能指针2:(虚?)析构函数(标准与实现的差异)

    只要是有良心的 C++ 教材,总是会苦心孤诣地告诫初学者,在继承关系中,应该把父类的析构函数定义成虚函数.这已然成为一条铁律,如果违背,不仅有内存泄漏的风险,在多继承情况下甚至会出现未定义行为.因此, ...

  9. C++ 面向对象(二)多态 : 虚函数、多态原理、抽象类、虚函数表、继承与虚函数表

    目录 多态 多态的概念 多态的构成条件 虚函数 虚函数的重写 协变(返回值不同) 析构函数的重写(函数名不同) final和override final override 重载, 重写, 重定义对比 ...

最新文章

  1. IIS启动配置的一些命令
  2. 机器学习(MACHINE LEARNING)MATLAB求解状态转移矩阵
  3. 图片指定区域根据rgb值计算出对应的坐标地址_【水文】震惊!高考期间,这位学生居然能通过图片隐写实现文字通信!...
  4. I've got so many hongbaos(should it be translated as red bags?)
  5. 教师节送什么老师最开心?程序员三招解决家长送礼难题!
  6. C++读取.txt文本文件操作
  7. android开发收银系统源码,基于android的语音智能收银系统设计与实现-软件工程专业论文.docx...
  8. B站网页端下载视频,直接浏览器下载或者Java实现下载
  9. java重载和重写的区别_Java重载和重写的区别
  10. 文王八卦圖와 易經組織
  11. 笔记本损耗60 计算机提示,笔记本电池损耗60%多怎么处理!
  12. phaser入门例子
  13. 云开发平台开源应用中心一次体验
  14. Win11右键菜单还原Win10
  15. 怎样剪切视频中的一段音频
  16. -- 21、查询不同老师所教不同课程平均分从高到低显示
  17. 山居最大的好处,就是静
  18. linux网络编程(6)基于多进程的TCP服务器与客户端编程
  19. R语言学习笔记(十):重抽样与自助法
  20. 论文的参考文献,添加交叉引用,实现编号自动更新,及编号1无法自动更新问题解决方法!!!

热门文章

  1. timeSetEvent、回调函数、CCriticalSection
  2. java常用算法分析和实现 amp,Java常用算法实现
  3. linq from 多个sum_快手重拳打击劣质电商 7月以来封禁700多个团伙账号
  4. c语言文件压缩与解压缩实验报告,哈弗曼树的文件压缩和解压实验报告(C语言).doc...
  5. Web框架——Flask系列之Flask简介(一)
  6. LeetCode 978. 最长湍流子数组(DP)
  7. LeetCode 1221. 分割平衡字符串
  8. 逻辑斯谛回归模型( Logistic Regression,LR) 最大熵模型(Max Entropy,ME)
  9. LeetCode 563. 二叉树的坡度(DFS)
  10. POJ 1577 Falling Leaves(二叉查找树)