当前课程知识点:C++语言程序设计进阶 > 第八章 多态性 > 抽象类 > 抽象类
纯虚函数是一个在基类中声明的虚函数,它在该基类中没有定义具体的操作内容,要求各派生类根据实际需要定义自己的版本,纯虚函数的声明格式为:
virtual 函数类型 函数名(参数表) = 0;
带有纯虚函数的类称为抽象类
带有纯虚函数的类称为抽象类:
class 类名 { virtual 类型 函数名(参数表)=0; //其他成员…… }
抽象类为抽象和设计的目的而声明
将有关的数据和行为组织在一个继承层次结构中,保证派生类具有要求的行为。
对于暂时无法实现的函数,可以声明为纯虚函数,留给派生类去实现。
抽象类只能作为基类来使用。
不能定义抽象类的对象。
//8_6.cpp #include <iostream> using namespace std; class Base1 { public: virtual void display() const = 0; //纯虚函数 }; class Base2: public Base1 { public: virtual void display() const; //覆盖基类的虚函数 }; void Base2::display() const { cout << "Base2::display()" << endl; } class Derived: public Base2 { public: virtual void display() const; //覆盖基类的虚函数 }; void Derived::display() const { cout << "Derived::display()" << endl; } void fun(Base1 *ptr) { ptr->display(); } int main() { Base2 base2; Derived derived; fun(&base2); fun(&derived); return 0; }
大家好
回来继续学习
C++语言程序设计
这一节呢
我们来学习抽象类
我们知道
在现实中呢
有些概念是比较具体的
有些概念是比较抽象的
那么抽象的概念
虽然它有很多东西
是不落实的
但是呢
它也是需要的
那么我们写程序呢
就是为了解决现实中的问题
要对现实中的问题进行建模
然后写算法去解决它
所以我们在程序中呢
也要能够描述
略微抽象一些的概念
那么抽象类就是干这个的
那么具体来说
抽象类它怎么就抽象了呢
一些类在定义的时候呢
它代表某个抽象的概念
于是有些功能
它就无法落实 无法实现
比如说我们定义一个
二维图象类
那么它的面积怎么求
不同的二维图形
有不同的求面积公式 对吧
圆的面积
三角形的面积
它们的计算公式是不一样的
这个时候
你如果在它们的上级
定一个抽象的二维图形
在这个抽象的二维图形概念里面
你怎么去确定它的面积公式呢
那就确定不了
所以这样的概念反映在程序中呢
就会是抽象类
它其中有些函数
是由于信息不够具体
而无法实现
这就是纯虚函数
纯虚函数呢
是一个在基类中声明的虚函数
这样的函数
在基类中是无法具体实现的
是没有具体的实现的函数体
无法实现的意思是什么呢
不是说我们初学程序设计
功力不到 不会写
我就把它纯虚了
不实现
不是这个意思
所谓无法实现是
在基类定义的信息
它不够具体
于是呢
这个函数
它没办法规定具体的算法
但是
为了规定整个类
家族的统一的行为
和对外接口
又需要在比较高层次的基类中
定义这么一个函数
那这个时候呢
就可以在函数头之后
接一个等于0
表示没有函数体
这个注意
不是表示函数的运行结果
固定为0 不是的
是表示它没有函数体
这就是一个纯虚函数
带有纯虚函数的类呢
就叫做抽象类
为什么呢
因为这样的类
它还有些东西没有实现
所以它不能产生实例
也就是抽象类
它是不能定义对象的
那不能定义对象要它干什么
作基类用
这个基类是Baseclass
不是那个食之无味
弃之可惜的那个鸡肋
它还是很有用的
因为它可以规范
整个类家族的统一对外借口
那我们来看
这是纯虚函数
出现在类体里面的情况
这个类呢
可以有很多其他的函数
都有函数体实现
它跟所有其他类一样
但是只要里面有一个函数
是纯虚函数
虚函数末尾加个等于0
就是纯虚函数了
只要有这么一个纯虚函数
这个类就称为抽象类
抽象类
虽然它不能够实例化
但是它可以规定
这种对外接口的统一形式
规定了
这样的对外接口的统一形式
有什么好处呢
就可以使我们将基类对象
和各级不同派生类的对象
都按照统一的方式进行处理
因为它们都有同样的接口
那我们通过基类指针
可以接收不同派生类对象的地址
然后去调用
在基类中定义过的这个函数名
虽然在基类中没有实现
但是在它的派生类中实现了
这样的方法
就是我们配合着虚函数
这种动态绑定机制
去利用多态性的一种很好的方式
有了抽象类中
规范的这种统一的行为
那么就能够保证派生类
具有这种统一要求的行为
因为一个派生类
你如果不去实现那些
在基类中没有实现的纯虚函数
那么这个派生类呢
你仍然继续作为抽象类
还是没办法实例化
没办法定义对象
只有到某一级派生类
你实现了这个纯虚函数
它不再纯虚了
它有函数体了
那么这一个派生类
才不是抽象类了
它才可以用来定义对象
所以抽象类
是用来作为基类使用的
是不能够定义对象的
好 现在呢
我们对前面的例题
略作修改
大家来看看
抽象类它的表现是什么
我们还以
前面出现过的这个程序为例
这一次我们稍作修改
将Base1里面的这个display函数
给定义成纯虚函数
大家看它没有函数体了
这有一个等于0
表示它没有函数体
是个纯虚函数
现在这个Base1呢
就成了一个抽象类
Base2继承Base1
它实现了display函数
它不再是抽象类了
那么Derived也继承了Base2
也实现了这个display函数
现在我们在主函数中
就不能再定义Base1的对象了
我们只能定义Base1的指针
大家看
在这个fun函数中
我们依然可以定义
这个形参的类型
为Base1的指针
但是在主函数中
我们就不能再定义
Base1的对象了
因为它是一个抽象类
只能作为基类使用
它不能实例化
不能定义对象
现在我们定义了Base2的对象
和Derived对象
我们将这两个对象的地址
分别两次都传送给fun函数
然后用这个抽象基类
Base1的指针
分别指向过
对象Base2 对象Derived
去调用display函数
我们来看
正确地调用了Base2的display
和Derived的display
这个例题
跟前面例题的唯一不同点就是
将Base1的display函数
定义为纯虚函数
于是Base1成了抽象基类
它不能去产生对象了
-导学
--导学
-继承的基本概念和语法
-第七章 继承与派生--继承的基本概念和语法习题
-继承方式
-第七章 继承与派生--继承方式
-基类与派生类类型转换
-第七章 继承与派生--基类与派生类类型转换
-派生类的构造和析构
--派生类的构造函数
--派生类的析构函数
--第七章 继承与派生--派生类的构造和析构
-派生类成员的标识与访问
--虚基类
-第七章 继承与派生--派生类成员的标识与访问
-小结
--小结
-综合实例
--第七章综合实例
-实验七
--实验七
-导学
--导学
-第八章 多态性--导学
-运算符重载
--运算符重载的规则
-第八章 多态性--运算符重载
-虚函数
--虚函数
--虚析构函数
--虚表与动态绑定
-第八章 多态性--虚函数
-抽象类
--抽象类
--第八章 多态性--抽象类
-override与final
-第八章 多态性--override与final
-小结
--第八章小结
-综合实例
--第八章综合实例
-实验八
--实验八
- 第八章讲义
-导学
--导学
-模板
--函数模板
--类模板
-第九章 模板与群体数据--模板
-线性群体
--线性群体的概念
-第九章 模板与群体数据--线性群体
-数组
--数组类模板
-链表
--链表类模板
-第九章 模板与群体数据--链表
-栈
--栈类模板
--栈类模板课后习题
--例9-9 栈的应用课后习题
-队列
--队列类模板
-第九章 模板与群体数据--队列
-排序
--排序概述
--插入排序
--选择排序
--交换排序
-第九章 模板与群体数据--排序
-查找
--查找
--查找课后习题
-小结
--小结
-综合实例
--综合实例
-实验九
--实验九
- 第九章讲义
-导学
--导学
-泛型程序设计及STL的结构
--STL简介
-第十章 泛型程序设计与C++标准模板库--泛型程序设计及STL的结构
-迭代器
--迭代器
-第十章 泛型程序设计与C++标准模板库--迭代器
-容器的基本功能与分类
-第十章 泛型程序设计与C++标准模板库--容器的基本功能与分类
-顺序容器
--顺序容器的特征
--第十章 泛型程序设计与C++标准模板库--顺序容器
-关联容器
--集合
--映射
-第十章 泛型程序设计与C++标准模板库--关联容器
-函数对象
--函数对象
--函数适配器
-算法
--算法
-小结
--第十章小结
-综合实例
--综合实例
-实验十
--实验十
- 第十章讲义
-导学
--导学
-I/O流的概念及流类库结构
-第十一章 流类库与输入/输出--I/O流的概念及流类库结构
-输出流
--输出流概述
--向文本文件输出
--向二进制文件输出
--向字符串输出
-第十一章 流类库与输入/输出--输出流
-输入流
--输入流概述
--输入流应用举例
--从字符串输入
-第十一章 流类库与输入/输出--输入流
-输入/输出流
--输入/输出流
-第十一章 流类库与输入/输出--输入/输出流
-小结
--小结
-综合实例
--综合实例
-实验十一
--实验十一
- 第十一章讲义
-导学
--第12章导学
-异常处理的思想与程序实现
-第十二章 异常处理--异常处理的思想与程序实现
-异常处理中的构造与析构
-第十二章 异常处理--异常处理中的构造与析构
-标准程序库异常处理
-第十二章 异常处理--标准程序库异常处理
-小结
--第12章小结
-综合实例
--综合实例
-实验十二
--实验十二
- 第十二章讲义