当前课程知识点:C++语言程序设计进阶 >  第八章 多态性 >  override与final >  override与final

返回《C++语言程序设计进阶》慕课在线视频课程列表

override与final在线视频

override与final

C++11:override 与 final

override

下列程序就仅仅因为疏忽漏写了const,导致多态行为没有如期进行

8-2.png

显式函数覆盖

- C++11 引入显式函数覆盖,在编译期而非运行期捕获此类错误。 - 在虚函数显式重载中运用,编译器会检查基类是否存在一虚拟函数,与派生类中带有声明override的虚拟函数,有相同的函数签名(signature);若不存在,则会回报错误。

 final



下一节:第八章小结

返回《C++语言程序设计进阶》慕课在线视频列表

override与final课程教案、知识点、字幕

大家好

欢迎回来继续学习

C++语言程序设计

这一节我们来学习

C++11标准提供的

override和final的新功能

我们知道多态行为的基础

是什么呢

是基类声明一个虚函数

然后呢

派生类要去覆盖这个虚函数的话

就要声明一个

原型完全一样的函数

但是有的时候呢

我们写程序可能会有疏漏

本意可能想写一个虚函数

去覆盖基类的虚函数

但是写的时候呢

可能参数表

或者是返回值

或者什么地方没有把它

定义的跟基类虚函数的原型

完全一致

这个时候

编译器并不会报错

因为编译器

并不知道我们的意图是说

这个函数

是一个覆盖基类虚函数的函数

编译器没办法知道我们这个意图

那所以呢

有的时候我们在派生类中

这个函数原型没有写对的话

就没有达到相应的目的

就实现不了多态了

而这个错误呢

却在运行中反映出来

还比较难调试和定位

这是一个因为疏忽造成了错误

于是没有能够实现多态性的例子

我们看在Base类里面

定义了一个虚函数f1

它是一个const

是一个常成员函数

那么在Derived类里面

我们本来是希望覆盖

这个虚函数f1的

所以定义了一个

同名的参数表也一样

返回值也一样的函数

在这里我们希望覆盖

基类继承过来的虚函数

那这个地方呢

它没有写这个vitual这个关键字

当然就是认为

这个语法规定

只要继承过来这个函数了

那派生类中的同原型的函数

自动都是虚函数了

不用写这个vitual关键字了

确实它是可以缺省的

但是就是疏忽了一点

const也是区别不同

重载函数的一个因素

所以这个有const

和没有const这两个函数原型

它是不同的

所以没有达到

写一个新的虚函数去覆盖

原有继承的虚函数的这样的效果

所以在主函数中

我们用基类的指针

去指向基类的对象

去指向派生类的对象

然后调用f1

结果呢

调用的都是基类的这个f1

没有实现我们希望的多态性

那么这样的错误

是很难查找的

在运行时发现结果

跟我们预期的不一样

但是要找到原因

还是有点麻烦的

那么怎么避免这种情况呢

后面要给大家介绍

C++11引入了一种

显示的函数覆盖的功能

这样的话

编译器在编译期间就会发现

你的本意是想覆盖基类的虚函数

但是你没有写对啊

它就能把这种错误发现

给我们指出来

那么这里呢

就要用到这个override

我们用override说明的函数

就必须在基类中找到

同样原型的这个虚函数

如果你在派生类中

写了一个函数

用override说明了

但是编译器在它的基类中

找不到

跟它相同原型的一个虚函数

编译器就会报错

说这个错了

你没有找到相同原型的这个函数

你就会发现

我想写一个函数去覆盖

结果没写对

那么这样我们就能把错误

在编译阶段就修改了

那这样就避免了运行时

那种不稳定性

运行时发生的错误

其实是挺难调试的

我们定义类的时候

是不是有的时候觉得这个类

它的功能都很关键

我定义了这样一个类

其他人就用就好了

我不希望它被继承和发展

实际上就是不希望它被扩展

这个继承呢

跟我们人类说的那个继承遗产呢

还是有差别的

只要是好东西

我们不会说不希望继承的

但是程序中的继承呢

意味着你一定要对它进行修改的

为什么呢

因为不需要修改

你可以直接使用

拿来用就行了

不用经过一个继承的环节

所以程序中的继承

和我们日常所理解的继承呢

还是些许差别的

所以有的时候呢

我们定义一个类

不希望它被继承

也就是不希望通过这个类

去派生出新类来

想用你就用

但是你不许改它

为什么呢

有时候有的类里面的功能

非常关键

你希望在整个系统中

就这样使用这样统一的功能

不希望它被

功能被覆盖 被修改

不希望接口被屏蔽 对吧

还有的时候呢

并不是一个类里面的所有功能

都如此的关键

可能就是个别的成员函数

它的算法你希望固定

希望在整个系统里面

都用严格的用这同样的算法

而不要去修改

这个时候呢

你可以说这个类可以被继承

但是这个函数不希望被修改

那么这个时候呢

你可以在函数上使用final

去说明

那这个函数就不能被覆盖了

那么现在

我们通过一个具体的例子

来演示一下这个final

我们看在定义Base1的时候呢

加了一个final来修饰

那就说明

定义Base1的人

指明了Base1

是不能派生出新类的

不能当做基类去继承的

那接下来呢

如果在程序的其他部分

我们尝试硬是要从Base1类

派生出Derived类

那么编译器就会报错

因为Base1是final

是不允许被继承的

再看下面这个例子

在Base2里面呢

我们声明这个函数f的时候

这个虚函数f

把它声明为final了

那就说明这个函数

是不能被覆盖的

那接下来

看我们虽然可以从Base2

派生出Derived2

但是

在Derived2这个类中如果尝试

重新定义一个函数f

去覆盖那个继承而来的虚函数

编译器也会报错

因为Base2里面的函数f

是final 是不允许被覆盖的

这个override和final

虽然是C++11提供的新功能

但是它并不是语言的关键字

也就是说

它只在特定的地方

具有特定的含义

在其他地方

如果你用override和final

做一般的标志符使用呢

也仍然是可以的

但是建议大家不要这样用

你就当它是关键字

不要在别的地方

拿它当标志符用

这样免得你的程序可读性

受到影响

C++语言程序设计进阶课程列表:

第七章 继承与派生

-导学

--导学

-继承的基本概念和语法

--继承的基本概念和语法

-第七章 继承与派生--继承的基本概念和语法习题

-继承方式

--继承方式简介及公有继承

--私有继承和保护继承

-第七章 继承与派生--继承方式

-基类与派生类类型转换

--基类与派生类类型转换

-第七章 继承与派生--基类与派生类类型转换

-派生类的构造和析构

--派生类的构造函数

--派生类的构造函数举例

--派生类的复制构造函数

--派生类的析构函数

--第七章 继承与派生--派生类的构造和析构

-派生类成员的标识与访问

--访问从基类继承的成员

--虚基类

-第七章 继承与派生--派生类成员的标识与访问

-小结

--小结

-综合实例

--第七章综合实例

-实验七

--实验七

-第七章讲义

第八章 多态性

-导学

--导学

-第八章 多态性--导学

-运算符重载

--运算符重载的规则

--双目运算符重载为成员函数

--单目运算符重载为成员函数

--运算符重载为非成员函数

-第八章 多态性--运算符重载

-虚函数

--虚函数

--虚析构函数

--虚表与动态绑定

-第八章 多态性--虚函数

-抽象类

--抽象类

--第八章 多态性--抽象类

-override与final

--override与final

-第八章 多态性--override与final

-小结

--第八章小结

-综合实例

--第八章综合实例

-实验八

--实验八

- 第八章讲义

第九章 模板与群体数据

-导学

--导学

-模板

--函数模板

--类模板

-第九章 模板与群体数据--模板

-线性群体

--线性群体的概念

-第九章 模板与群体数据--线性群体

-数组

--数组类模板

--例9-4数组类应用举例

-链表

--链表的概念与结点类模板

--链表类模板

-第九章 模板与群体数据--链表

-栈

--栈类模板

--栈类模板课后习题

--例9-9 栈的应用

--例9-9 栈的应用课后习题

-队列

--队列类模板

-第九章 模板与群体数据--队列

-排序

--排序概述

--插入排序

--选择排序

--交换排序

-第九章 模板与群体数据--排序

-查找

--查找

--查找课后习题

-小结

--小结

-综合实例

--综合实例

-实验九

--实验九

- 第九章讲义

第十章 泛型程序设计与C++标准模板库

-导学

--导学

-泛型程序设计及STL的结构

--泛型程序设计的基本概念

--STL简介

-第十章 泛型程序设计与C++标准模板库--泛型程序设计及STL的结构

-迭代器

--迭代器

-第十章 泛型程序设计与C++标准模板库--迭代器

-容器的基本功能与分类

--容器的基本功能与分类

-第十章 泛型程序设计与C++标准模板库--容器的基本功能与分类

-顺序容器

--顺序容器的基本功能

--顺序容器的特征

--顺序容器的插入迭代器与适配器

--第十章 泛型程序设计与C++标准模板库--顺序容器

-关联容器

--关联容器分类和基本功能

--集合

--映射

--多重集合和多重映射

-第十章 泛型程序设计与C++标准模板库--关联容器

-函数对象

--函数对象

--函数适配器

-算法

--算法

-小结

--第十章小结

-综合实例

--综合实例

-实验十

--实验十

- 第十章讲义

第十一章 流类库与输入/输出

-导学

--导学

-I/O流的概念及流类库结构

--I/O流的概念及流类库结构

-第十一章 流类库与输入/输出--I/O流的概念及流类库结构

-输出流

--输出流概述

--向文本文件输出

--向二进制文件输出

--向字符串输出

-第十一章 流类库与输入/输出--输出流

-输入流

--输入流概述

--输入流应用举例

--从字符串输入

-第十一章 流类库与输入/输出--输入流

-输入/输出流

--输入/输出流

-第十一章 流类库与输入/输出--输入/输出流

-小结

--小结

-综合实例

--综合实例

-实验十一

--实验十一

- 第十一章讲义

第十二章 异常处理

-导学

--第12章导学

-异常处理的思想与程序实现

--异常处理的思想与程序实现

-第十二章 异常处理--异常处理的思想与程序实现

-异常处理中的构造与析构

--异常处理中的构造与析构

-第十二章 异常处理--异常处理中的构造与析构

-标准程序库异常处理

--标准程序库异常处理

-第十二章 异常处理--标准程序库异常处理

-小结

--第12章小结

-综合实例

--综合实例

-实验十二

--实验十二

- 第十二章讲义

override与final笔记与讨论

也许你还感兴趣的课程:

© 柠檬大学-慕课导航 课程版权归原始院校所有,
本网站仅通过互联网进行慕课课程索引,不提供在线课程学习和视频,请同学们点击报名到课程提供网站进行学习。