C++ override specifier (C++ override 说明符)

news2024/10/6 3:24:02

C++ override specifier [C++ override 说明符]

  • 1. C++ override specifier
  • 2. C++ override 说明符
  • 3. Compiler Error C2723
  • 4. Managing Virtual Methods: `override` and `final` (管理虚方法 `override` 和 `final`)
  • References

在派生类中用 override 修饰符定义虚函数时,编译器会验证直接或间接基类是否包含特征标相同的虚函数。如果不包含,就生成一个错误消息。

1. C++ override specifier

C++ documentation (C++ 文档)
https://learn.microsoft.com/en-us/cpp/cpp/
https://learn.microsoft.com/zh-cn/cpp/cpp/

override specifier (override 说明符)
https://learn.microsoft.com/en-us/cpp/cpp/override-specifier
https://learn.microsoft.com/zh-cn/cpp/cpp/override-specifier

You can use the override specifier to designate member functions that override a virtual function in a base class.
可以使用 override 说明符来指定覆盖基类中的虚成员函数。

override is context-sensitive and has special meaning only when it’s used after a member function declaration; otherwise, it’s not a reserved keyword.
override 是上下文相关的,只有在成员函数声明时使用才具有特殊含义;否则,它不是保留关键字。

Use override to help prevent inadvertent inheritance behavior in your code. The following example shows where, without using override, the member function behavior of the derived class may not have been intended. The compiler doesn’t emit any errors for this code.
使用 override 有助于防止你的代码中出现意外的继承行为。以下示例演示在未使用 override 的情况下,可能不打算使用派生类的成员函数行为。编译器不会发出此代码的任何错误。

class BaseClass {
	virtual void funcA();
	virtual void funcB() const;
	virtual void funcC(int = 0);
	void funcD();
};

class DerivedClass : public BaseClass {
	virtual void funcA();  // Works as intended

	// DerivedClass::funcB() is non-const, so it does not override BaseClass::funcB() const 
	// and it is a new member function
	virtual void funcB();

	// DerivedClass::funcC(double) has a different parameter type than BaseClass::funcC(int), 
	// so DerivedClass::funcC(double) is a new member function
	virtual void funcC(double = 0.0);
};

When you use override, the compiler generates errors instead of silently creating new member functions.
当使用 override 时,编译器会生成错误,而不会在不提示的情况下创建新的成员函数。

class BaseClass {
	virtual void funcA();
	virtual void funcB() const;
	virtual void funcC(int = 0);
	void funcD();
};

class DerivedClass : public BaseClass {
	virtual void funcA() override; // ok

	// Compiler error: DerivedClass::funcB() does not override BaseClass::funcB() const
	virtual void funcB() override;

	// Compiler error: DerivedClass::funcC(double) does not override BaseClass::funcC(int)
	virtual void funcC(double = 0.0) override;

	// Compiler error: DerivedClass::funcD() does not override the non-virtual BaseClass::funcD()
	void funcD() override;
};

To specify that functions cannot be overridden and that classes cannot be inherited, use the final specifier.
若要指定不能重写函数且不能继承类,请使用 final 说明符。

2. C++ override 说明符

派生类如果定义了一个函数与基类中虚函数的名字相同但是形参列表不同,这仍然是合法的行为。编译器将认为新定义的这个函数与基类中原有的函数是相互独立的,派生类的函数并没有覆盖掉基类中的版本。就实际的编程习惯而言,这种声明往往意味着发生了错误,因为我们可能原本希望派生类能覆盖掉基类中的虚函数,但是一不小心把形参列表弄错了。

在 C++11 新标准中我们可以使用 override 修饰符来说明派生类中的虚函数。如果我们使用 override 标记了某个函数,但该函数并没有覆盖已存在的虚函数,此时编译器将报错。

struct B {
	virtual void f1(int) const;
	virtual void f2();
	void f3();
};

struct D1 : B {
	void f1(int) const override;  // 正确:f1 与基类中的 f1 匹配
	void f2(int) override;  // 错误:B 没有 void f2(int) 形式的函数
	void f3() override;  // 错误:f3 不是虚函数
	void f4() override;  // 错误:B 没有名为 f4 的函数
};

D1 中,f1override 说明符是正确的,因为基类和派生类中的 f1 都是 const 成员,并且它们都接受一个 int 并返回 void,所以 D1 中的 f1 正确地覆盖了它从 B 中继承而来的虚函数。

D1f2 的声明与 Bf2 的声明不匹配,显然 B 中定义的 f2 不接受任何参数而 D1f2 接受一个 int。因为这两个声明不匹配,所以 D1f2 不能覆盖 Bf2,它是一个新函数,仅仅是名字恰好与原来的函数一样而已。因为我们使用 override 所表达的意思是我们希望能覆盖基类中的虚函数而实际上并未做到,所以编译器会报错。

因为只有虚函数才能被覆盖,所以编译器会拒绝 D1f3。该函数不是 B 中的虚函数,因此它不能被覆盖。类似的,f4 的声明也会发生错误,因为 B 中根本就没有名为 f4 的函数。

3. Compiler Error C2723

‘function’ : ‘specifier’ specifier illegal on function definition

error C2723: '***': 'override' specifier illegal on function definition

'override' specifier is not allowed outside a class definition

The specifier cannot appear with a function definition outside of a class declaration. The override specifier can be specified only on a member function declaration within a class declaration.
说明符不能与类声明外部的函数定义同时出现,仅能对类声明内的成员函数声明指定 override 说明符。

4. Managing Virtual Methods: override and final (管理虚方法 overridefinal)

Virtual methods are an important component of implementing polymorphic class hierarchies, in which a base class reference or pointer can invoke the particular method appropriate to the type of object referred to. For instance, suppose the base class declares a particular virtual method, and you decide to provide a different version for a derived class. This is called overriding the old version. If you mismatch the function signature, you hide rather than override the old version.
虚方法对实现多态类层次结构很重要,让基类引用或指针能够根据指向的对象类型调用相应的方法,但虚方法也带来了一些编程陷阱。假设基类声明了一个虚方法,而你决定在派生类中提供不同的版本,这将覆盖旧版本。如果特征标不匹配,将隐藏而不是覆盖旧版本。

class Action {
	int a;

public:
	Action(int i = 0) : a(i) {}
	int Val() const { return a; };
	virtual void Func(char ch) const { std::cout << Val() << ch << "\n"; }
};

class Bingo : public Action {
public:
	Bingo(int i = 0) : Action(i) {}
	virtual void Func(char * ch) const { std::cout << Val() << ch << "!\n"; }
};

Because class Bingo uses Func(char * ch) instead of Func(char ch), Func(char ch) is hidden to a Bingo object.
由于类 Bingo 定义的是 Func(char * ch) 而不是 Func(char ch),将对 Bingo 对象隐藏 Func(char ch),这导致程序不能使用类似于下面的代码:

Bingo bingo(10);
bingo.Func('@');  // works for Action object, fails for Bingo object

With C++11, you can use the virtual specifier override to indicate that you intend to override a virtual function. Place it after the parameter list. If your declaration does not match a base method, the compiler objects.
在 C++11 中,可使用虚说明符 override 指出你要覆盖一个虚函数,将其放在参数列表后面。如果声明与基类方法不匹配,编译器将视为错误。

class Action {
	int a;

public:
	Action(int i = 0) : a(i) {}
	int Val() const { return a; };
	virtual void Func(char ch) const { std::cout << Val() << ch << "\n"; }
};

class Bingo : public Action {
public:
	Bingo(int i = 0) : Action(i) {}
	virtual void Func(char * ch) const override { std::cout << Val() << ch << "!\n"; }
};

A compile-time error message:

error C3668: 'Bingo::Func': method with override specifier 'override' did not override any base class methods

You may find that you want to prohibit derived classes from overriding a particular virtual method. To do so, place final after the parameter list. For example, the following code would prevent classes based on Action to redefine theFunc(char ch) function.
禁止派生类覆盖特定的虚方法,可在参数列表后面加上 final下面的代码禁止 Action 的派生类重新定义函数。

virtual void Func(char ch) const final { std::cout << Val() << ch << "\n"; }

The specifiers override and final do not quite have the status of keywords. Instead, they are labeled “identifiers with special meaning”. This means that the compiler uses the context in which they appear to decide if they have a special meaning. In other contexts, they can be used as ordinary identifiers (for example, as variable names or enumerations).
说明符 overridefinal 并非关键字,而是具有特殊含义的标识符。这意味着编译器根据上下文确定它们是否有特殊含义;在其他上下文中,可将它们用作常规标识符,如变量名或枚举。

References

[1] Yongqiang Cheng, https://yongqiang.blog.csdn.net/
[2] C++ final specifier 禁止派生类和禁止重写函数, https://blog.csdn.net/chengyq116/article/details/104477726
[3] C++ Primer Plus, 6th Edition, https://www.informit.com/store/c-plus-plus-primer-plus-9780321776402

  • Managing Virtual Methods: override and final

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1904249.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

华为OSPF配置DR和BDR与指定DR

基础配置 <Huawei>sys #进入配置模式 Enter system view, return user view with CtrlZ. [Huawei]un in en #关闭报文弹窗 Info: Information center is disabled. [Huawei]sys R1 #设备名更改为R1 [R1]int g0/0/0 …

Vue3中的Composables组合式函数,Vue3实现minxins

Vue3中的Composables是什么 Vue3中的Composables 简单理解其实就是类React Hooks式的组合式函数封装方法。 Vue官方称为Composables 组合式函数。 1.抽离复用逻辑时 Vue2写法 &#xff08;1&#xff09;Vue2 中的mixins混入器写法缺点 (Vue3 optionsApi写法同理) 新建minxins…

硅纪元视角 | 中国电信“星辰大模型·软件工厂”,两分钟完成应用开发,效率飞跃!

在数字化浪潮的推动下&#xff0c;人工智能&#xff08;AI&#xff09;正成为塑造未来的关键力量。硅纪元视角栏目紧跟AI科技的最新发展&#xff0c;捕捉行业动态&#xff1b;提供深入的新闻解读&#xff0c;助您洞悉技术背后的逻辑&#xff1b;汇聚行业专家的见解&#xff0c;…

动手学深度学习(Pytorch版)代码实践 -循环神经网络- 56门控循环单元(`GRU`)

56门控循环单元&#xff08;GRU&#xff09; 我们讨论了如何在循环神经网络中计算梯度&#xff0c; 以及矩阵连续乘积可以导致梯度消失或梯度爆炸的问题。 下面我们简单思考一下这种梯度异常在实践中的意义&#xff1a; 我们可能会遇到这样的情况&#xff1a;早期观测值对预测…

Windows电脑下载、安装VS Code的方法

本文介绍Visual Studio Code&#xff08;VS Code&#xff09;软件在Windows操作系统电脑中的下载、安装、运行方法。 Visual Studio Code&#xff08;简称VS Code&#xff09;是一款由微软开发的免费、开源的源代码编辑器&#xff0c;支持跨平台使用&#xff0c;可在Windows、m…

C++ 模版进阶

目录 前言 1. 非类型模版参数 1.1 概念与讲解 1.2 array容器 2. 模版的特化 2.1 概念 2.2 函数模版特化 2.3 类模版特化 2.3.1 全特化 2.3.2 偏特化 3.模版的编译分离 3.1 什么是分离编译 3.2 模版的分离编译 3.3 解决方法 4. 模版总结 总结 前言 本篇文章主要…

在mac下 Vue2和Vue3并存 全局Vue2环境创建Vue3新项目(Vue cli2和Vue cli4)

全局安装vue2 npm install vue-cli -g自行在任意位置创建一个文件夹vue3&#xff0c;局部安装vue3,注意不要带-g npm install vue/cli安装完成后&#xff0c;进入目录&#xff0c;修改vue为vue3 找到vue3/node-moudles/.bin/vue&#xff0c;把vue改成vue3。 对环境变量进行配置…

【6】图像分类部署

【6】图像分类部署 文章目录 前言一、将pytorch模型转为ONNX二、本地终端部署2.1. ONNX Runtime部署2.2. pytorch模型部署&#xff08;补充&#xff09; 三、使用flask的web网页部署四、微信小程序部署五、使用pyqt界面化部署总结 前言 包括将训练好的模型部署在本地终端、web…

在Linux操作系统中去修复/etc/fstab文件引起的系统故障。

如果/etcfstab文件中发生错误&#xff0c;有可能导致系统无法正常启动。 比如&#xff1a;系统里的一块磁盘被删除&#xff0c;但是/etc/fstab中关于这块磁盘的信息依然被保存在文件/etc/fstab中。 主要看倒数后两行&#xff0c;系统提示&#xff0c;敲ctrlD或者是直接输入密码…

LeetCode 744, 49, 207

目录 744. 寻找比目标字母大的最小字母题目链接标签思路代码 49. 字母异位词分组题目链接标签思路代码 207. 课程表题目链接标签思路代码 744. 寻找比目标字母大的最小字母 题目链接 744. 寻找比目标字母大的最小字母 标签 数组 二分查找 思路 本题比 基础二分查找 难的一…

redhat7.x 升级openssh至openssh-9.8p1

1.环境准备&#xff1a; OS系统&#xff1a;redhat 7.4 2.备份配置文件&#xff1a; cp -rf /etc/ssh /etc/ssh.bak cp -rf /usr/bin/openssl /usr/bin/openssl.bak cp -rf /etc/pam.d /etc/pam.d.bak cp -rf /usr/lib/systemd/system /usr/lib/systemd/system.bak 3.安装…

阿里云存储应用

如何做好权限控制 小浩在梳理门户网站静态资源时&#xff0c;发现有些资源是仅内部员工可访问&#xff0c;有些资源是特定的注册客户可访问&#xff0c;还有些资源是匿名客户也可以访问。针对不同场景、不同用户&#xff0c;小浩该如何规划企业门户网站静态资源的权限控制呢&a…

解析商场智能导视系统背后的科技:AR导航与大数据如何助力商业运营

在布局复杂的大型商场中&#xff0c;顾客常常面临寻找特定店铺的挑战。商场的规模庞大&#xff0c;店铺众多&#xff0c;使得顾客在享受购物乐趣的同时&#xff0c;也不得不面对寻路的难题。维小帮商场智能导航导视系统的电子地图、AR导航营销能为顾客提供更加便捷的购物体验。…

Linux—网络设置

目录 一、ifconfig——查看网络配置 1、查看网络接口信息 1.1、查看所有网络接口 1.2、查看具体的网络接口 2、修改网络配置 3、添加网络接口 4、禁用/激活网卡 二、hostname——查看主机名称 1、查看主机名称 2、临时修改主机名称 3、永久修改主机名称 4、查看本…

2023年了,还在手动px转rem吗?

px-to-rem 使用amfe-flexible和postcss-pxtorem在webpack中配置px转rem npm i amfe-flexible -Snpm i postcss-pxtorem -D在main.js中 import flexible from amfe-flexible Vue.use(flexible);index.html中 <meta name"viewport" content"widthdevice-w…

用 Echarts 画折线图

https://andi.cn/page/621503.html

Floyd判圈算法——环形链表(C++)

Floyd判圈算法(Floyd Cycle Detection Algorithm)&#xff0c;又称龟兔赛跑算法(Tortoise and Hare Algorithm)&#xff0c;是一个可以在有限状态机、迭代函数或者链表上判断是否存在环&#xff0c;求出该环的起点与长度的算法。 …

Java语言程序设计篇一

Java语言概述 Java语言起源编程语言最新排名名字起源Java语言发展历程Java语言的特点Java虚拟机垃圾回收Java语言规范Java技术简介Java程序的结构Java程序注意事项&#xff1a;注释编程风格练习 Java语言起源 1990年Sun公司提出一项绿色计划。1992年语言开发成功最初取名为Oak…

vue3使用方式汇总

1、引入iconfont阿里图库图标&#xff1a; 1.1 进入阿里图标网站&#xff1a; iconfont阿里&#xff1a;https://www.iconfont.cn/ 1.2 添加图标&#xff1a; 1.3 下载代码&#xff1a; 1.4 在vue3中配置代码&#xff1a; 将其代码复制到src/assets/fonts/目录下&#xff1…

大众点评2024年全球必吃榜清单

大众点评2024年全球必吃榜清单共2797家&#xff0c;奇怪的是官方并没有发布详细清单&#xff0c;只发布了新闻通稿介绍大概情况。这里做一些整理。 按城市分布情况&#xff0c;数量如下 上海 144 北京 137 成都 96 重庆 93 广州 81 深圳 79 武汉 69 苏州 67 杭州 61 …