C++11之前,一直没有继承控制关键字。禁用一个类的进一步衍生是可能的但也很棘手。为避免用户在派生类中重载一个虚函数,你不得不向后考虑。

C++ 11添加了两个继承控制关键字:override和final。override确保在派生类中声明的重载函数跟基类的虚函数有相同的签名。final阻止类的进一步派生和虚函数的进一步重载。

虚函数重载

一个派生类可以重载在基类中声明的成员函数,这是面向对象设计的基础。然而像重载一个函数这么简单的操作也会出错。关于重载虚函数的两个常见错误如下:
无意中重载
签名不匹配

首先,我们来分析一下无意中重载的综合症。你可能只是通过声明了一个与基类的某个虚成员函数具有相同的名字和签名的成员函数而无意中重载了这个虚函数。编译器和读代码的人很难发现这个bug因为他们通常以为这个新函数是为了实现对基类函数的重载:

class A
{
public:
virtual void func();
};
class B: A{};
class F{};
class D: A, F
{
public:
void func();//meant to declare a new function but //accidentally overrides A::func};

阅读以上代码,你不能确定成员函数D::func()是否故意重载了A::func().它也可能是个偶然发生的重载,因为两个函数的参数列表和名字都碰巧一样。

签名不匹配是一个更为常见的情景。这导致意外创建一个新的虚函数(而不是重载一个已存在的虚函数),正如以下例子所示:

class  G
{
public:
virtual void func(int);
}; class H: G
{
public:
virtual void func(double);
};

这种情况下,程序员本打算在类H中重载G::func()的。然而,由于H::func()拥有不同的签名,结果创建了一个新的虚函数,而非对基类函数的重载:

H *p=new H;
p->func(5); //calls G::f
p->func(5.0); // calls H::f

碰到这种情况,不是所有的编译器都会给个警告,有时那样做会被设置成抑制这种警告。

基于上面的两个错误

在C++11中,通过使用新关键字override可以消除这两个bugs。override明确地表示一个函数是对基类中一个虚函数的重载。更重要的是,它会检查基类虚函数和派生类中重载函数的签名不匹配问题。如果签名不匹配,编译器会发出错误信息。

我们来看看override如何消除签名不匹配bug的:

class G
{
public:
virtual void func(int);
};
class H: G
{
public:
virtual void func(double) override; //compilation error
};

当处理到H::func()声明时,编译器会 在一个基类查找与之匹配的虚函数。

final函数和类

C++11的关键字final有两个用途。第一,它阻止了从类继承;第二,阻止一个虚函数的重载。我们先来看看final类吧。

程序员常常在没有意识到风险的情况下坚持从std::vector派生。在C++11中,无子类类型将被声明为如下所示:

class TaskManager {/*..*/} final;
class PrioritizedTaskManager: public TaskManager {
}; //compilation error: base class TaskManager is final

同样,你可以通过声明它为final来禁止一个虚函数被进一步重载。如果一个派生类试图重载一个final函数,编译器就会报错:

class A
{
pulic:
virtual void func() const;
};
class B: A
{
pulic:
void func() const override final; //OK
};
class C: B
{
pulic:
void func()const; //error, B::func is final
};

C::func()是否声明为override没关系,一旦一个虚函数被声明为final,派生类不能再重载它。

转自:http://www.cnblogs.com/minggong/p/6457726.html

C++11 override 和 final 关键字的更多相关文章

  1. C++11 override和final

    30多年来,C++一直没有继承控制关键字.最起码这是不容易的,禁止一个类的进一步衍生是可能的但也很棘手.为避免用户在派生类中重载一个虚函数,你不得不向后考虑. C++ 11添加了两个继承控制关键字:o ...

  2. [转][C++ 11]override and final - write clean and maintainable C++ code

    原文: http://arne-mertz.de/2015/12/modern-c-features-override-and-final/ Today I write about a pair of ...

  3. C++11之重写说明符override和final

    关于 本文代码演示环境: win10 + vs2017 一个困扰 之前MFC用的多了,发现一个问题: 子类窗口的某个函数是否重载了基类的函数.解决办法是: 打开基类的代码,一个个排查. 这只是一个具体 ...

  4. c++ 11 override final

    C++ 11添加了两个继承控制关键字:override和final. override确保在派生类中声明的重载函数跟基类的虚函数有相同的签名.final阻止类的进一步派生和虚函数的进一步重载

  5. C++11学习笔记(5) —— override and final (转)

    原文转自 http://blog.csdn.net/fire_lord/article/details/8540592 1.简介 C++为我们提供了继承和虚函数的重写特性. 在派生类中,重写虚函数不强 ...

  6. Java第11次作业:什么是继承?继承的好处?什么是覆写?super()?构造代码块?子父类初始化顺序? 抽象类能用final声明吗?final关键字声明类 方法 变量以及全局常量?抽象类的构造方法?

    什么是继承? 继承是以父类为基础,子类可以增加新的数据或新的功能.子类不能选择性地继承父类.这种技术使得复用以前的代码非常容易. JAVA不支持多继承,单继承使JAVA的继承关系很简单,一个类只能有一 ...

  7. (转)深入理解Java中的final关键字

    转自:http://www.importnew.com/7553.html Java中的final关键字非常重要,它可以应用于类.方法以及变量.这篇文章中我将带你看看什么是final关键字?将变量,方 ...

  8. Java学习第三篇:类的三大特征,抽象类,接口,final关键字

    一.类的三大特征 1.封装性 (1).什么是封装 封装就是把抽象出的数据和对数据的操作封装在一起, 数据被保护在内部, 程序的其他部分只有通过被授权的操作(成员方法), 才能对数据进行操作. (2). ...

  9. 【Java基础】final关键字总结

    Java中的final关键字非常重要,它可以应用于类.方法以及变量.这篇文章中我将带你看看什么是final关键字?将变量,方法和类声明为final代表了什么?使用final的好处是什么?最后也有一些使 ...

随机推荐

  1. Hadoop基础-通过IO流操作HDFS

    Hadoop基础-通过IO流操作HDFS 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 一.上传文件 /* @author :yinzhengjie Blog:http://www ...

  2. SecureCRT for ubuntu 菜单消失

    两种解决方案. 1.先说网上查到的复杂的: 编辑CRT安装目录下的Global.ini 找到 D:"Show Menu Bar"=00000000 改成 D:"Show ...

  3. IIS 为应用程序池提供服务的进程在与 Windows Process Activation Service 通信时出现严重错误的解决方法

    系统环境:Windows Server 2008 R2 64位, IIS 7.0 错误信息: 为应用程序池提供服务的进程在与 Windows Process Activation Service 通信 ...

  4. Sidekiq定时任务时间设置

    minutely(2)                               #每2分钟执行一次 hourly.minute_of_hour(27)       #每小时的27分钟执行 dail ...

  5. getResource()和getResourceAsStream以及路径问题【转】【补】

    一 getResource 用JAVA获取文件,听似简单,但对于很多像我这样的新人来说,还是掌握颇浅,用起来感觉颇深,大常最经常用的,就是用JAVA的File类,如要取得c:/test.txt文件,就 ...

  6. rpmbuild打包php

    安装php依赖库 mkdir -pv ~/rpmbuild/{BUILD,RPMS,SOURCES,SPECS,SRPMS} php有一个依赖库,在yum源于epel源中都没有需要自己打包libico ...

  7. Springboot中Feign的使用总结

    Feign是Webservice服务的客户端,创建接口+注解就可完成,实现简单 客户端通过@EnableFeignClients开启Feign的支持功能 @SpringBootApplication ...

  8. [leetcode-108,109] 将有序数组转换为二叉搜索树

    109. 有序链表转换二叉搜索树 Given a singly linked list where elements are sorted in ascending order, convert it ...

  9. HDU 1023(卡特兰数 数学)

    题意是求一列连续升序的数经过一个栈之后能变成的不同顺序的数目. 开始时依然摸不着头脑,借鉴了别人的博客之后,才知道这是卡特兰数,卡特兰数的计算公式是:a( n )  =  ( ( 4*n-2 ) / ...

  10. GIT与SVN的比较

    Git: 1. 分布式版本控制2. 不需要网络,本地就可以操作版本控制3. 可以是公用的,可以分享4. 不依赖于中央服务器,即使服务器有问题也不会有影响5. 传输方式不一样,git要比svn快很多6. ...