浅谈c++中继承体系中易错点

目前,就我工作经验来看,在c++中继承体系中总爱搞错的有两点:

  1. 不把基类中需要覆盖的方法为设置为虚方法。
  2. 不把基类中的析构函数设置为虚方法。

就第一点而言,如果基类中需要覆盖的方法没有设置为虚方法会怎么样呢?后果就是继承了该类的子类,子类想要覆盖父类的方法,是不会成功的,在发生动态绑定的时候,父类依旧是调用父类的方法,并未调用子类的方法。来看看实列:

#include<iostream>
class Father {public:Father(){}~Father(){}void Show(){std::cout << "I'm your Father" << std::endl;}
};class Son : public Father {public:Son() {}~Son(){}void Show(){std::cout << "I'm your Son" << std::endl;}
};int main()
{Father* father = new Son;father->Show();system("pause");
}

读完代码我们先思考一下到底输出啥呢,是调用父亲的show()呢,还是调用Son的Show()?
输出:
I’m your Father
请按任意键继续. . .
果然父亲铁青着脸,调用了自己方法。儿子始终得不到润泽,可怜的娃啊。
是时候做出改变了,现在我们把父类的show()方法变为虚方法(virtual void Show(); ),再瞧瞧效果。

#include<iostream>class Father {public:virtual void Show(){std::cout << "I'm your Father" << std::endl;}
};class Son : public Father {public:void Show(){std::cout << "I'm your Son" << std::endl;}
};int main()
{... // 与上面一致
}

改变后的输出:
I’m your Son
请按任意键继续. . .
这种继承问题还是比较常见的。我们需要覆盖的方法一定要用virtual 关键子修饰,不然就算发生动态绑定,那么子类的方法也得不到调用,和我们心中预期相差甚远,甚至是错误。其实,要杜绝这类错误有一个很好的方法,只需在子类的方法上加上override即可。该关键字自动检测子类的方法是不是可以覆盖父类的方法,包括:父类的方法是不是虚方法,子类的方法是否和父类的方法一致。所以按照规范来写就是:

#include<iostream>
class Father {public:virtual void Show()... // 与上面一致
};class Son : public Father {public:virtual void Show() override...
};int main()
{...
}

所谓无规矩不成方圆嘛,按照规范来总会减少犯错的机会 _

第二个易错点,也是面试馆最爱问的问题,就是继承体系中,基类的析构方法一定要设置为虚方法。多一句嘴,如果面试馆总爱这样问,那么我们把要点说一下就可以了:
把基类析构函数设置为虚方法是为了防止内存泄漏的,怎么说呢?假如我们的派生类申请了一些内存,并在析构函数中释放,那么当删除基类指针的时候就不会调用子类的析构函数,为什么不会呢,刚刚我们不是做了实验吗,子类覆盖父类的方法,如果不是虚方法,就不会发生动态绑定,那么自然也就只调用父类自己的方法,子类的方法永远得不到调用,方法都得不到调用,怎么可能释放内存嘛,所以就发生内存泄漏了。当然,子类自身也是没有释放的,变成了野指针。造成内存泄漏。
人狠话不多,来,直接上代码,代码才是灵魂的归宿。

#include<iostream>class Base {public:Base(){}//  故意不设置为虚方法~Base(){std::cout << " Base 析构完成..." << std::endl;}virtual void DoSomething() = 0;
};class Derive : public Base {public:Derive() :m_data(nullptr){m_data = new char[m_lenth];}~Derive(){delete[] m_data;std::cout << " Derive 析构完成..." << std::endl;}virtual void DoSomething() override{// ...}
private:// 既然是狠人,我们就new 500M内存// 这儿为什么不直接写524288000呢? 其实多个嘴,// c++有编译和运行阶段,像这种常量,编译阶段能计算出来的,// 编译器早就优化好了,根本就等不到运行时才算,所以啊,// 常量我们尽量写的直白点,像直接写524288000 这种魔鬼数字,鬼懂哦const unsigned int m_lenth = 500 * 1024 * 1024;char* m_data;
};int main()
{Base* base = new Derive;base->DoSomething();delete base;while (true){// 方便我们在任务管理器里看看内存到底有没有被回收}system("pause");return 0;
}

来看一下输出,和任务管理器的内存情况。
输出:
Base 析构完成…
就打印了这样一句话,可怜啊,子类的析构函数没有运行。难哦。
任务管理器:

瞧瞧500M 的内存还没有释放掉,这样的代码要是执行在服务器上,服务器那区区几百G的内存怎么够哦,几个循环就宕机。
我们在来改改代码,将父类的析构函数变为虚方法

#include<iostream>class Base {public:...virtual ~Base(){std::cout << " Base 析构完成..." << std::endl;}virtual void DoSomething() = 0;
};class Derive : public Base {public:... // 和上保持一致
private:...
};int main()
{Base* base = new Derive;base->DoSomething();delete base;while (true){// 方便我们在任务管理器里看看内存到底有没有被回收}system("pause");return 0;
}

再看下运行效果:
输出:
Derive 析构完成…
Base 析构完成…
任务管理器:

从输出看到父类调用了子类的析构函数,任务管理器里显示内存也已经被释放。从实践的效果来看,把父类的析构函数设为虚方法是很有必要,因为涉及到内存泄漏。本地运用到还好,内存耗尽重启就好了,服务器如果这样,直接要不成嘛。那时候影响的就不是一个人了,而是成千上万的用户。关于这方面的原理性讨论我就不说了,建议多看看:
《Primer c++ 第5版》第十五章
《Effective C++》07.多态基类声明virtual析构函数
最后再多句嘴,假如我们要继承第三方库的某个类,一定要长个心眼,看看这个基类是否有虚的析构函数。就比如我不可能继承一个std::string 吧,这直接是无稽之谈。他都没有虚的虚构函数。所以啊,万事得长个心眼。

浅谈c++中继承体系中易错点相关推荐

  1. 化学实验中计算机技术的应用,浅谈计算机在基础化学实验中的应用

    <浅谈计算机在基础化学实验中的应用.doc>由会员分享,可免费在线阅读全文,更多与<浅谈计算机在基础化学实验中的应用>相关文档资源请在帮帮文库(www.woc88.com)数亿 ...

  2. 计算机在英语教学中的应用课题,浅谈信息技术在英语教学中的应用

    浅谈信息技术在英语教学中的应用 毕业论文 摘要:随着信息技术的发展, 计算机多媒体技术和网络被广泛地应用在外语教学中, 改变了传统外语教学模式.现代化外语教学提高了外语教学水平, 从而培养高素质的外语 ...

  3. 计算机在汽车专业中的应用,浅谈计算机技术在汽车行业中的应用.doc

    浅谈计算机技术在汽车行业中的应用 摘要:文章围绕计算机技术在汽车性能测试方面的运用.计算机技术在汽车监控方面的运用.计算机技术在汽车检修方面的运用三个方面展开讨论,对计算机技术在汽车行业中的运用模式进 ...

  4. 自己动手写一个推荐系统,推荐系统小结,推荐系统:总体介绍、推荐算法、性能比较, 漫谈“推荐系统”, 浅谈矩阵分解在推荐系统中的应用...

    自己动手写一个推荐系统 废话: 最近朋友在学习推荐系统相关,说是实现完整的推荐系统,于是我们三不之一会有一些讨论和推导,想想索性整理出来. 在文中主要以工程中做推荐系统的流程着手,穿插一些经验之谈,并 ...

  5. 计算机在教学管理中应用浅论,浅谈多媒体在计算机教学中的应用

    浅谈多媒体在计算机教学中的应用 浅谈多媒体在计算机教学中的应用1 随着信息技术改革的发展和深入,多媒体教学越来越受到重视.计算机教学也顺府时代的潮流,计算机教学是抽象理论与实际操作结合起来的教学的系统 ...

  6. 运用计算机技术和语文教学,浅谈计算机技术在语文教学中的运用论文

    浅谈计算机技术在语文教学中的运用论文 1前言 随着信息技术的不断发展,计算机在生活中的广泛应用,尤其是计算机在课堂教学中的应用,给教学带来一场技术性的革命.计算机技术为学生带来一堂集声音.图像.趣味为 ...

  7. 浅谈ARCGIS在测绘项目中的一般应用

    浅谈ARCGIS在测绘项目中的 一般应用 一.概述 众所周知,ARCGIS是由Esri公司生产的一款的GIS平台.问世至今,已升级数代,现在比较常用的是ARCGIS10.2的版本.由于其强大及全面的地 ...

  8. 浅谈在游戏陪玩开发中常见的几种加密算法及实现

    前言 数字签名.信息加密是游戏陪玩开发前后端都经常需要使用到的技术,应用场景包括了用户登入.交易.信息通讯.oauth 等等,不同的应用场景需要游戏陪玩开发时使用到不同的签名加密算法,或者需要搭配不一 ...

  9. C++编程进阶5(内联函数、如何降低编译成本、处理继承体系中同名不同参的成员函数、私有虚函数)

    十七.内联函数 在https://blog.csdn.net/Master_Cui/article/details/106391552中,已经简单的说过内联函数的作用. 函数体较小的内联函数经过编译后 ...

最新文章

  1. pycharm多光标设置
  2. 【正一专栏】梅西终老巴萨可被裁判吹掉了已进之球
  3. CG CTF WEB SQL Injection
  4. android h5 ftp,HBuilderX ftp插件使用教程
  5. keras报错ValueError: No data provided for XXX
  6. “五月天才不短咧” TME live这样焕发线上Live演出的生命力
  7. Leetcode475.Heaters供暖器
  8. 故事的小黄花,从CSDN那年就飘着
  9. 专题三——枚举、模拟、排序
  10. mysql数据库中eof_数据库eof
  11. 少儿编程Scratch3.0初识
  12. php屏蔽微信网页投诉按钮,屏蔽微信(QQ)内置浏览器菜单中的投诉按钮
  13. java 调用企查查API查询企业信息
  14. 纯js图片验证码Captcha.js
  15. 喜报!签约招商证券,字根科技错别字检测再创佳绩
  16. 为Halide安装opencl支持
  17. 数据结构——一元n次多项式加法
  18. Blender动画笔记:Basic Jump Cycle(二)调整曲线和节奏
  19. 教程篇(6.0) 06. 证书操作 ❀ FortiGate 安全 ❀ Fortinet 网络安全专家 NSE 4
  20. idea跳到下一个断点_IDEA---断点调试Debug

热门文章

  1. Mac上docker下安装mongodb出错?
  2. 一文带你搞定线程池原理
  3. 【干货】史上最全的卫星导航术语200条
  4. mysql readtimeout_MySQL Timeout解析
  5. 实验记录 | mutect问题详解:No tribble type was provided on the command line and the type of the file?
  6. 北京大学曹健——Tensorflow笔记 01
  7. (6)实现自发光+光晕【镁条燃烧发出白光】
  8. python 清屏幕_python清理屏幕
  9. UXP插件开发下不用任何框架创建自己的插件并试运行
  10. Solidworks高版本如何转换为低版本