一:纯虚函数和抽象类

  1. 纯虚函数是一个在基类中说明的虚函数,在基类中没有定义,要求任何派生类都定义自己的版本
  2. 纯虚函数为各个派生类提供一个公共接口
  3. 纯虚函数的形式:
  4. virtual 类型 函数名(参数列表)=0
  5. 一个具有纯虚函数的基类称为抽象类
  1. 注意:抽象类不能实例化对象
  1. 一个派生类继承抽象类但是未实现纯虚函数,则也变为抽象类,可以继续被继承实现
  1. class Parent //抽象类
  2. {
  3. public:
  4. Parent()
  5. {
  6. cout << "Parent construct" << endl;
  7. }
  8.  
  9. virtual void overrideFunc() = 0; //纯虚函数
  10. };
  11.  
  12. class Child01:public Parent  //未实现纯虚函数,所以还是一个抽象类,不能被实例化对象,可以被继承
  13. {
  14. public:
  15. Child01()
  16. {
  17. cout << "Child01 construct" << endl;
  18. }
  19. };
  20.  
  21. class Child02 :public Parent  //未实现纯虚函数,是抽象类,可以被继承实现
  22. {
  23. public:
  24. Child02()
  25. {
  26. cout << "Child02 construct" << endl;
  27. }
  28. };
  29.  
  30. class ChildSon :public Child01
  31. {
  32. public:
  33. ChildSon()
  34. {
  35. cout << "ChildSon construct" << endl;
  36. }
  37.  
  38. virtual void overrideFunc()  //实现了纯虚函数,是一个可以实例化对象的类
  39. {
  40. cout << "ChildSon finish" << endl;
  41. }
  42. };
  43.  
  44. void main()
  45. {
  46. ChildSon c;
  47. system("pause");
  48. }

二:虚析构函数

(0)注意:构造函数不能是虚函数:建立一个派生类对象时,必须从类层次的根开始,沿着继承路径逐个调用基类的构造函数

(一)问题引出:未使用虚析构函数时会出现内存泄漏(当父类指针指向子类对象时)

  1. class Parent //抽象类
  2. {
  3. public:
  4. char *name;
  5. public:
  6. Parent(char* n)
  7. {
  8. name = (char *)malloc(strlen(n) + );
  9. strcpy(name, n);
  10. cout << "Parent construct" << endl;
  11. }
  12.  
  13. virtual void getInfo()
  14. {
  15. cout << "parent name:" << this->name << endl;
  16. }
  17.  
  18. ~Parent()
  19. {
  20. cout << "Parent distruct" << endl;
  21. if (this->name)
  22. {
  23. delete this->name;
  24. this->name = NULL;
  25. }
  26. }
  27. };
  28.  
  29. class Child01:public Parent
  30. {
  31. public:
  32. char *addr;
  33. public:
  34. Child01(char* n, char* a) :Parent(n)
  35. {
  36. addr = (char *)malloc(strlen(a) + );
  37. strcpy(addr, a);
  38. cout << "Child01 construct" << endl;
  39. }
  40.  
  41. virtual void getInfo()
  42. {
  43. cout << "child01 name:" << this->name << endl;
  44. cout << "child01 addr:" << this->addr << endl;
  45. }
  46.  
  47. ~Child01()
  48. {
  49. cout << "Child01 distruct" << endl;
  50. if (this->name)
  51. {
  52. delete name;
  53. this->name = NULL; //释放后置空,是一个良好的习惯
  54. }
  55. if (this->addr)
  56. {
  57. delete addr;
  58. this->addr = NULL;
  59. }
  60. }
  61. };
  62.  
  63. void main()
  64. {
  65. Parent* p = new Child01("Liu","zz");
  66. delete p;  //会根据父类指针去调用父类析构函数:回顾前面多态
  67.  
  68. system("pause");
  69. }

  1. 发现只调用了父类析构函数,释放了name变量,但是addr变量并没有进行释放,导致了内存泄漏

(二)问题解决:联系前面多态,使用虚析构函数--->会根据虚函数指针找到虚函数表从而调用子类析构函数(而)子类析构时候同构造相反方向去调用基类析构方法《重点》

  1. class Parent //抽象类
  2. {
  3. public:
  4. char *name;
  5. public:
  6. Parent(char* n)
  7. {
  8. name = (char *)malloc(strlen(n) + );
  9. strcpy(name, n);
  10. cout << "Parent construct" << endl;
  11. }
  12.  
  13. virtual void getInfo()
  14. {
  15. cout << "parent name:" << this->name << endl;
  16. }
  17.  
  18. virtual ~Parent()
  19. {
  20. cout << "Parent distruct" << endl;
  21. if (this->name)
  22. {
  23. delete this->name;
  24. this->name = NULL;
  25. }
  26. }
  27. };
  28.  
  29. class Child01:public Parent
  30. {
  31. public:
  32. char *addr;
  33. public:
  34. Child01(char* n, char* a) :Parent(n)
  35. {
  36. addr = (char *)malloc(strlen(a) + );
  37. strcpy(addr, a);
  38. cout << "Child01 construct" << endl;
  39. }
  40.  
  41. virtual void getInfo()
  42. {
  43. cout << "child01 name:" << this->name << endl;
  44. cout << "child01 addr:" << this->addr << endl;
  45. }
  46.  
  47. virtual ~Child01()
  48. {
  49. cout << "Child01 distruct" << endl;
  50. if (this->name)
  51. {
  52. delete name;
  53. this->name = NULL; //释放后置空,是一个良好的习惯
  54. }
  55. if (this->addr)
  56. {
  57. delete addr;
  58. this->addr = NULL;
  59. }
  60. }
  61. };
  62.  
  63. void testfunc()
  64. {
  65. Parent* p = new Child01("Liu","zz");
  66.  
  67. delete p;
  68. }
  69.  
  70. void main()
  71. {
  72. testfunc();
  73.  
  74. system("pause");
  75. }

三:回顾delete运算符

(一)注意:在C中使用malloc和free函数来分配和释放内存,在C++中扩展了new和delete运算符

(二)其中new和delete运算符使用:

  1. new运算符的使用:
  2.  
  3. 指针变量 = new 类型(常数);
  4. 指针变量 = new 类型[表达式];
  1. delete运算符的使用:
  2.  
  3. delete 指针变量
  4. delete []指针变量

(三)重点:delete中使用的指针变量必须是一个new返回的指针变量《重点》

正确使用:

  1. Parent* p = new Child01("Liu","zz");
  2.  
  3. delete p;

错误使用:

  1. Child01 c("Liu", "zz");
  2. Parent* p = &c;
  3.  
  4. delete p;

C++回顾day03---<纯虚函数和抽象类以及虚析构函数,delete使用>的更多相关文章

  1. Java I/O(二)其他常用的输入输出流PrintStream等、标准流重定向

    四.FilterOutputStream.PrintStream PrintStream是继承自FilterStream类的,例如标准输出流System.out就是著名的PrintStream类对象. ...

  2. java.IO输入输出流:过滤流:buffer流和data流

    java.io使用了适配器模式装饰模式等设计模式来解决字符流的套接和输入输出问题. 字节流只能一次处理一个字节,为了更方便的操作数据,便加入了套接流. 问题引入:缓冲流为什么比普通的文件字节流效率高? ...

  3. Java中IO流,输入输出流概述与总结

    总结的很粗糙,以后时间富裕了好好修改一下. 1:Java语言定义了许多类专门负责各种方式的输入或者输出,这些类都被放在java.io包中.其中, 所有输入流类都是抽象类InputStream(字节输入 ...

  4. 第27章 java I/O输入输出流

    java I/O输入输出流 1.编码问题 import java.io.UnsupportedEncodingException; /** * java涉及的编码 */ public class En ...

  5. java 对象输入输出流

    对象的输入输出流的作用: 用于写入对象 的信息读取对象的信息. 对象的持久化. 比如:用户信息.              ObjectInputStream   : 对象输入流            ...

  6. 【转】输入/输出流 - 全面掌握IO

    File类: 程序中操作文件和目录都可以使用File类来完成即不管是文件还是目录都是使用File类来操作的,File能新建,删除,重命名文件和目录,但File不能访问文件内容本身,如果需要访问文件本身 ...

  7. 输入输出流(IO)

    输入输出流(IO)文件(File)java.io.File用于表示文件(目录),也就是说程序员可以通过File类在程序中操作硬盘上的文件和目录.File类只用于表示文件(目录)的信息(名称.大小等), ...

  8. Java输入/输出流体系

    在用java的io流读写文件时,总是被它的各种流能得很混乱,有40多个类,理清啦,过一段时间又混乱啦,决定整理一下!以防再忘 Java输入/输出流体系 1.字节流和字符流 字节流:按字节读取.字符流: ...

  9. JAVA Io 缓冲输入输出流

    java中提供带缓冲的输入输出流.在打开文件进行写入或读取操作时,都会加上缓冲,提高了IO读写性能. 1. BufferedInputStream 缓冲输入流 2. BufferedOutputStr ...

  10. C++输入输出流

    一.C++输入输出流的含义 以前所用到的输入和输出,都是以终端为对象的,即从键盘输入数据,运行结果输出到显示器屏幕上.从操作系统的角度看,每一个与主机相连的输入输出设备都被看作一个文件.程序的输入指的 ...

随机推荐

  1. Docker 启动,进入容器,查看log命令

    1.启动一个容器 docker run -d -P training/webapp python app.py -d:让容器在后台运行. -P:将容器内部使用的网络端口映射到我们使用的主机上. 如果需 ...

  2. LeetCode算法题-Minimum Index Sum of Two Lists(Java实现)

    这是悦乐书的第272次更新,第286篇原创 01 看题和准备 今天介绍的是LeetCode算法题中Easy级别的第139题(顺位题号是599).假设Andy和Doris想要选择一家餐馆吃晚餐,他们都有 ...

  3. C#基础知识之Dictionary

    最近使用了Dictionary,出现了意想不到的错误,先记录一下自己遇到的问题以及目前我的解决方法,然后温习一下Dictionary的基础用法. 一.自己遇到的问题 1.代码如下: namespace ...

  4. C#基础知识之反射

    http://blog.csdn.net/educast/article/details/2894892 两个现实中的例子:1.B超:大家体检的时候大概都做过B超吧,B超可以透过肚皮探测到你内脏的生理 ...

  5. Windows 版 SourceTree 免登录跳过初始设置的方法

    首先去官网下载最新的sourcetree安装包,点击打开下载地址. 下载完成后安装,等到他自启动开始提示你登录的时候,打开“我的电脑(此电脑)”,在最上边的输入栏输入%LocalAppData%\At ...

  6. bsp makefile2

    1. grep "bsp_dir" -r ./  -s  --exclude-dir "*.git" 用这个加快目录定位-- 2.编译所有子目录 for dir ...

  7. bootstrapt 使用遇到问题

    1.布局的时候什么时候用xs,sm,md,lg? small grid (≥ 768px) = .col-sm-*, medium grid (≥ 992px) = .col-md-*, large ...

  8. SpringMVC项目读取不到外部CSS文件的解决办法及总结

    昨天,在写一个新需求的时候,因为没有前端同事的对接,无奈只有自己写css,js放到ssm结构的后台项目中,因为之前开发都是把前端文件放在一个专门的服务器上,一直没有关注服务端项目读取静态资源的问题,运 ...

  9. CF1120D Power Tree

    沙发~~ 题意简述 给你一棵有根树,定义叶子为度数为1的点. 你可以以$ w_x \(的代价控制\)x\(点.选择控制之后可以给它的子树里的叶子加 上\)t (t \in Z )$. 你要以最小的总代 ...

  10. PS制作水火相溶特效文字图片

    最终效果 一.新建一个1400*900像素的画布. 二.由上到下拉一个深灰到纯黑径向渐变. 三.输入字母S,并用ctrl+t拉到适合的大小,并且降低不透明度. 四.拖入水花素材(如果大家有水花笔刷的话 ...