C++回顾day03---<纯虚函数和抽象类以及虚析构函数,delete使用>
一:纯虚函数和抽象类
纯虚函数是一个在基类中说明的虚函数,在基类中没有定义,要求任何派生类都定义自己的版本
纯虚函数为各个派生类提供一个公共接口
纯虚函数的形式:
virtual 类型 函数名(参数列表)=0;
一个具有纯虚函数的基类称为抽象类
注意:抽象类不能实例化对象
一个派生类继承抽象类但是未实现纯虚函数,则也变为抽象类,可以继续被继承实现
class Parent //抽象类
{
public:
Parent()
{
cout << "Parent construct" << endl;
} virtual void overrideFunc() = 0; //纯虚函数
}; class Child01:public Parent //未实现纯虚函数,所以还是一个抽象类,不能被实例化对象,可以被继承
{
public:
Child01()
{
cout << "Child01 construct" << endl;
}
}; class Child02 :public Parent //未实现纯虚函数,是抽象类,可以被继承实现
{
public:
Child02()
{
cout << "Child02 construct" << endl;
}
}; class ChildSon :public Child01
{
public:
ChildSon()
{
cout << "ChildSon construct" << endl;
} virtual void overrideFunc() //实现了纯虚函数,是一个可以实例化对象的类
{
cout << "ChildSon finish" << endl;
}
}; void main()
{
ChildSon c;
system("pause");
}

二:虚析构函数
(0)注意:构造函数不能是虚函数:建立一个派生类对象时,必须从类层次的根开始,沿着继承路径逐个调用基类的构造函数
(一)问题引出:未使用虚析构函数时会出现内存泄漏(当父类指针指向子类对象时)
class Parent //抽象类
{
public:
char *name;
public:
Parent(char* n)
{
name = (char *)malloc(strlen(n) + );
strcpy(name, n);
cout << "Parent construct" << endl;
} virtual void getInfo()
{
cout << "parent name:" << this->name << endl;
} ~Parent()
{
cout << "Parent distruct" << endl;
if (this->name)
{
delete this->name;
this->name = NULL;
}
}
}; class Child01:public Parent
{
public:
char *addr;
public:
Child01(char* n, char* a) :Parent(n)
{
addr = (char *)malloc(strlen(a) + );
strcpy(addr, a);
cout << "Child01 construct" << endl;
} virtual void getInfo()
{
cout << "child01 name:" << this->name << endl;
cout << "child01 addr:" << this->addr << endl;
} ~Child01()
{
cout << "Child01 distruct" << endl;
if (this->name)
{
delete name;
this->name = NULL; //释放后置空,是一个良好的习惯
}
if (this->addr)
{
delete addr;
this->addr = NULL;
}
}
}; void main()
{
Parent* p = new Child01("Liu","zz"); delete p; //会根据父类指针去调用父类析构函数:回顾前面多态 system("pause");
}

发现只调用了父类析构函数,释放了name变量,但是addr变量并没有进行释放,导致了内存泄漏
(二)问题解决:联系前面多态,使用虚析构函数--->会根据虚函数指针找到虚函数表从而调用子类析构函数(而)子类析构时候同构造相反方向去调用基类析构方法《重点》
class Parent //抽象类
{
public:
char *name;
public:
Parent(char* n)
{
name = (char *)malloc(strlen(n) + );
strcpy(name, n);
cout << "Parent construct" << endl;
} virtual void getInfo()
{
cout << "parent name:" << this->name << endl;
} virtual ~Parent()
{
cout << "Parent distruct" << endl;
if (this->name)
{
delete this->name;
this->name = NULL;
}
}
}; class Child01:public Parent
{
public:
char *addr;
public:
Child01(char* n, char* a) :Parent(n)
{
addr = (char *)malloc(strlen(a) + );
strcpy(addr, a);
cout << "Child01 construct" << endl;
} virtual void getInfo()
{
cout << "child01 name:" << this->name << endl;
cout << "child01 addr:" << this->addr << endl;
} virtual ~Child01()
{
cout << "Child01 distruct" << endl;
if (this->name)
{
delete name;
this->name = NULL; //释放后置空,是一个良好的习惯
}
if (this->addr)
{
delete addr;
this->addr = NULL;
}
}
}; void testfunc()
{
Parent* p = new Child01("Liu","zz"); delete p;
} void main()
{
testfunc(); system("pause");
}

三:回顾delete运算符
(一)注意:在C中使用malloc和free函数来分配和释放内存,在C++中扩展了new和delete运算符
(二)其中new和delete运算符使用:
new运算符的使用: 指针变量 = new 类型(常数);
指针变量 = new 类型[表达式];
delete运算符的使用: delete 指针变量
delete []指针变量
(三)重点:delete中使用的指针变量必须是一个new返回的指针变量《重点》
正确使用:
Parent* p = new Child01("Liu","zz");
delete p;
错误使用:
Child01 c("Liu", "zz");
Parent* p = &c;
delete p;

C++回顾day03---<纯虚函数和抽象类以及虚析构函数,delete使用>的更多相关文章
- Java I/O(二)其他常用的输入输出流PrintStream等、标准流重定向
四.FilterOutputStream.PrintStream PrintStream是继承自FilterStream类的,例如标准输出流System.out就是著名的PrintStream类对象. ...
- java.IO输入输出流:过滤流:buffer流和data流
java.io使用了适配器模式装饰模式等设计模式来解决字符流的套接和输入输出问题. 字节流只能一次处理一个字节,为了更方便的操作数据,便加入了套接流. 问题引入:缓冲流为什么比普通的文件字节流效率高? ...
- Java中IO流,输入输出流概述与总结
总结的很粗糙,以后时间富裕了好好修改一下. 1:Java语言定义了许多类专门负责各种方式的输入或者输出,这些类都被放在java.io包中.其中, 所有输入流类都是抽象类InputStream(字节输入 ...
- 第27章 java I/O输入输出流
java I/O输入输出流 1.编码问题 import java.io.UnsupportedEncodingException; /** * java涉及的编码 */ public class En ...
- java 对象输入输出流
对象的输入输出流的作用: 用于写入对象 的信息读取对象的信息. 对象的持久化. 比如:用户信息. ObjectInputStream : 对象输入流 ...
- 【转】输入/输出流 - 全面掌握IO
File类: 程序中操作文件和目录都可以使用File类来完成即不管是文件还是目录都是使用File类来操作的,File能新建,删除,重命名文件和目录,但File不能访问文件内容本身,如果需要访问文件本身 ...
- 输入输出流(IO)
输入输出流(IO)文件(File)java.io.File用于表示文件(目录),也就是说程序员可以通过File类在程序中操作硬盘上的文件和目录.File类只用于表示文件(目录)的信息(名称.大小等), ...
- Java输入/输出流体系
在用java的io流读写文件时,总是被它的各种流能得很混乱,有40多个类,理清啦,过一段时间又混乱啦,决定整理一下!以防再忘 Java输入/输出流体系 1.字节流和字符流 字节流:按字节读取.字符流: ...
- JAVA Io 缓冲输入输出流
java中提供带缓冲的输入输出流.在打开文件进行写入或读取操作时,都会加上缓冲,提高了IO读写性能. 1. BufferedInputStream 缓冲输入流 2. BufferedOutputStr ...
- C++输入输出流
一.C++输入输出流的含义 以前所用到的输入和输出,都是以终端为对象的,即从键盘输入数据,运行结果输出到显示器屏幕上.从操作系统的角度看,每一个与主机相连的输入输出设备都被看作一个文件.程序的输入指的 ...
随机推荐
- linux 磁盘IO测试工具:FIO (同时简要介绍dd工具测试)
FIO是测试IOPS的非常好的工具,用来对硬件进行压力测试和验证.磁盘IO是检查磁盘性能的重要指标,可以按照负载情况分成照顺序读写,随机读写两大类. 目前主流的第三方IO测试工具有fio.iomete ...
- dynalist 配额
2018-8-29 dynalist 配额 提示有一个G的配额 就是使用的流量用光了.仅有1个G
- SQLServer之视图简介
视图定义 视图是一个虚拟表,其内容由查询定义. 同表一样,视图包含一系列带有名称的列和行数据. 视图在数据库中并不是以数据值存储集形式存在,除非是索引视图. 行和列数据来自由定义视图的查询所引用的表, ...
- 微信小程序——页面跳转及传参
小程序页面跳转 微信小程序的页面跳转依然是以传统的请求转发和请求重定向为主,tabbar的存在,有TAB页面的跳转. 为了微信小程序的简介方便,规定页面路径只能是十层,应尽量避免过多的交互方式. 1. ...
- 爬虫系列---selenium详解
一 安装 pip install Selenium 二 安装驱动 chrome驱动文件:点击下载chromedriver (yueyu下载) 三 配置chromedrive的路径(仅添加环境变量即可) ...
- .NET ORM框架之NHibernate
这段时间一直使用NHibernate,今天抽空总结一下. 1.什么是NHibernate? NHibernate是一个面向.NET环境的对象/关系数据库映射工具.对象/关系数据库映射(object/r ...
- idea spring-boot总结
1. 按自己重新配置spring-boot pom点进 mybatis-spring-boot-starter ,在要改的里面 <version>3.4.4</version> ...
- HBase案例:HBase 在人工智能场景的使用
近几年来,人工智能逐渐火热起来,特别是和大数据一起结合使用.人工智能的主要场景又包括图像能力.语音能力.自然语言处理能力和用户画像能力等等.这些场景我们都需要处理海量的数据,处理完的数据一般都需要存储 ...
- 2.[Andriod]Andriod Studio结合Visual Studio Emulator for Android调试Android App
0. 工欲善其事必先利其器 上一篇博客对比了一下Android和WinPhnoe的布局容器,后续篇章重点放在Android的开发上了. 说到开发就绕不开调试程序,调试Android App我们有2种选 ...
- SkylineGlobe7.0.1版本 通过鼠标左右平移模型对象
帮同事写了一段测试代码,如下: <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "ht ...