C++ 虚函数 (virtual function) 介绍

2023-11-15

1. 什么是虚函数

C++ 对象有三大特性:继承、封装、多态;虚函数就是实现多态的一种方式。

虚函数是指加了 virtual 修饰词的类的成员函数,但 virtual 关键字并非强制必须要有的。

对于某些函数,当基类希望派生类重新定义合适自己的版本时,基类就把这些函数声明为虚函数

以下是一个虚函数的简单定义:

class Animal {
public:
	virtual void makeSound() {
		std::cout << "Animal makes a sound" << std::endl;
	}
};

注意:virtual 关键字只能出现在类内部的函数声明中,不能用于类外部的函数定义。

2. 虚函数与非虚函数的区别

在 C++ 中,基类必须将它的两种成员函数区分开:

  • 基类希望直接继承给派生类而不需要改写的函数。静态绑定,即解析过程发生在编译而非运行时
  • 基类希望派生类进行覆盖的函数:定义为虚函数。动态绑定,即根据对象类型不同,调用该虚函数时可能执行基类的版本,也可能执行某个派生类的版本;因此需要在程序运行时确定。

3. 派生类中的虚函数

由于只有在程序运行时才知道调用哪个版本的虚函数,因此所有虚函数都必须有定义,就是不使用虚函数,也必须定义它。

基类定义的虚函数在所有派生类中都是虚函数

C++11 允许派生类使用 override 关键字显式地注明哪个成员函数是改写的基类的虚函数,代码示例如下:

class Animal {
	virtual void makeSound() {
		std::cout << "Animal makes a sound." << std::endl;
	}
};

class Dog :public Animal {
	void makeSound() override {
		std::cout << "Dog makes a sound." << std::endl;
	}
};

完整代码示例如下:

#include <iostream>


class Animal {
private:
	int nums;
public:
	Animal() = default;
	Animal(int nums_) : nums(nums_) {};
	virtual void printNum() {
		std::cout << "The number of animals is: " << nums << std::endl;
	}
};


class Dog :public Animal {
private:
	int nums;
public:
	Dog() = default;
	Dog(int nums_) : nums(nums_) {};
	void printNum() override {
		std::cout << "The number of dog is: " << nums << std::endl;
	}
};


int main(){
	Animal animal(100);
	animal.printNum();   // The number of animals is: 100
	Dog dog(5);
	dog.printNum();      // The number of dog is: 5
	return 0;
}

4. 构造/析构函数可以是虚函数吗?

答案:

构造函数不能是虚函数,析构函数可以是虚函数且最好设置为虚函数

(1)构造函数不可以是虚函数

构造函数是在创建对象时执行的,而虚函数是程序运行时执行的;也就是说在创建对象时虚函数还没确定用那个版本呢,所以构造函数不可以是虚函数。

(2)析构函数可以是虚函数且最好写成虚函数

如果析构函数不是虚函数,则容易造成内存泄露。原因为:

若有父类指针指向子类对象存在,需要析构的是子类对象;但父类析构函数不是虚函数,则只析构了父类,造成子类对象没有及时释放,引起内存泄漏。

5. 纯虚函数

5.1 纯虚函数的定义

虚函数与纯虚函数的区别如下:

  • 虚函数:子类可以(也可以不)重新定义基类的虚函数,在基类中定义为 virtual void func() {}
  • 纯虚函数:子类必须提供纯虚函数的个性化实现,在基类中定义为 virtual void func() = 0 {} 或 virtual void func() const = 0 {}

以下是一个纯虚函数的简单定义(声明):

class Animal {
public:
	virtual void makeSound() = 0 {}
};

5.1 纯虚函数的特定

(1)含有纯虚函数的类称为抽象类,抽象类不能被实例化。

与纯虚函数不同的是,包含虚函数的类可以被实例化。

如下面的代码中对 Animal 抽象类的实例化会编译报错。

#include <iostream>

class Animal {
	// 这里的 = 0 没有任何实际意义,只起形式上的作用,告诉编译系统"这是纯虚函数"
	virtual void makeSound() = 0{}
};

int main(){
	Animal animal();   // 报错:不能实例化抽象类
	return 0;
}

(2)纯虚函数只需要声明,不需要定义。

因为纯虚函数一定会被重新,所以在基类中声明即可,不需要定义。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

C++ 虚函数 (virtual function) 介绍 的相关文章

  • .NET 单点登录

    我一直在尝试使用 C 为 NET Web 应用程序实现 WEB SSO 服务提供程序插件 我将使用 shibboleth 身份提供商 我已经使用 OpenSAML 库为 java 应用程序实现了相同的功能 我想知道在 NET 应用程序中使用
  • Caliburn.Micro - ShowDialog() 如何关闭对话框?

    EDIT 新信息 刚刚设法让记录器工作 老实说 我不知道 cm 有一个 并且在尝试使用时收到此消息TryClose TryClose requires a parent IConductor or a view with a Close m
  • 平滑手绘曲线

    我有一个允许用户绘制曲线的程序 但这些曲线看起来不太好 它们看起来摇摇欲坠 而且是手绘的 所以我想要一种能够自动平滑它们的算法 我知道平滑过程中存在固有的模糊性 因此它不会每次都完美 但这种算法似乎确实存在于多个绘图包中 并且它们工作得很好
  • 最新 .Net MongoDb.Driver 的连接问题

    我创建了一个 MongoLab 沙箱数据库 我与 MongoChef 连接 效果很好 我通过 Nuget 安装了 MongoDB Driver 2 2 2 我编写了一些简单的 C 演示代码 但就是无法使其工作 连接字符串是直接从 Mongo
  • 如何从 Qt 应用程序通过 ODBC 连接到 MySQL 数据库?

    我有一个新安装的 MySQL 服务器 它监听 localhost 3306 从 Qt 应用程序连接到它的正确方法是什么 原来我需要将MySQL添加到ODBC数据源 我在遵循这个视频教程后做到了这一点 https youtu be K3GZi
  • ContentDialog 未与 UWP 中心对齐

    据我所知 ContentDialog的默认行为应该是使其在 PC 上居中并在移动设备上与顶部对齐 但就我而言 即使在 PC 上我也将其与顶部对齐 但我不明白发生了什么 我正在使用代码隐藏来创建它 这是我正在使用的代码片段 Creates t
  • 无法加载程序集问题

    我收到以下错误 无法加载程序集 错误详细信息 System BadImageFormatException 无法加载文件或程序集 文件 或其依赖项之一 该程序集是由比当前加载的运行时更新的运行时构建的 无法加载 该程序集是使用 Net Fr
  • opencv中如何去除二值图像噪声?

    将图像转换为二值图像 黑白 后如果有任何噪音怎么办 我消除了那些不需要的噪音 您可以看到下图的黑色区域内有一些白噪声 我该如何去除噪声 使用opencv http img857 imageshack us img857 999 blackn
  • 如何减少 MinGW g++ 编译器生成的可执行文件的大小?

    我有一个简单的 Hello world C 程序 在 Win XP 下由 MinGW g 编译器编译为 500kB 可执行文件 有人说这是由于iostream的库和静态链接libstdc dll Using s链接器选项有点帮助 减少了 5
  • 如何让XmlReader读取C#中的属性?

    我有一个 XML Stream 其中包含以下 XML 内容
  • 如何从外语线程调用Python函数(C++)

    我正在开发一个程序 使用 DirectShow 来抓取音频数据 媒体文件 DirectShow 使用线程将音频数据传递给回调 我的程序中的函数 然后我让该回调函数调用另一个函数 Python 中的函数 我使用 Boost Python 来包
  • 使用数据绑定,如何将包含表情符号的文本绑定到标签并使其正确显示?

    我正在编写一个应用程序来连接 WordPress BuddyPress API 该应用程序将允许用户通过 API 相互发送消息 当这些消息包含表情符号时 我很难正确显示它们 以下是 API 返回的消息文本的简短示例 Hi x1f642 ho
  • DataGridView 行背景颜色没有改变

    我想根据加载时的特定条件更改 DGV 行的背景颜色 即使在 Windows 窗体中也是如此 但我看不到任何 DGV 行的颜色有任何变化 谁能告诉我如何解决这个问题 private void frmSecondaryPumps Load ob
  • Type.GetInterfaces() 仅适用于声明的接口

    首先 像这样的问题有很多 也许有些OP甚至在问同样的问题 问题是这些问题的答案 无论是否接受 都没有真正回答这个问题 至少我找不到 如何确定类直接声明的接口 而不是由父级或声明的接口继承的接口 e g interface I interfa
  • 如何将System.Windows dll添加到Visual Studio 2010 Express?

    我正在开发一个小型应用程序C and VS2010 as IDE with NET框架4 我想用CaptureSource类以便从笔记本电脑的网络摄像头捕获视频 为此我需要添加一个命名空间System Windows DependencyO
  • C 变量声明的效率 [重复]

    这个问题在这里已经有答案了 例如 在 C 中声明一个变量需要多长时间int x or unsigned long long var 我想知道它是否会让我的代码在类似的事情中更快 for conditions int var 0 code 这
  • 当我的进程被终止时到底会发生什么?

    我有一个包含本机代码和托管代码的混合进程 在 Windows Server 2003 上运行 当我从进程资源管理器中终止进程时 它会进入 100 cpu 的状态 并在消失之前保持这种状态一段时间 有时甚至 10 分钟 在此期间我无法 杀死
  • Boost.asio和异步链,unique_ptr?

    我对异步编程不太熟悉 我有一个问题 我的问题如下 给出 boost asio 中 C 11 的 echo server 示例 http www boost org doc libs 1 60 0 doc html boost asio ex
  • 从脚本启用/禁用 GameObject 组件 [Unity3D]

    我需要获取一个脚本中设置的布尔值 放入名为 bouclier 的变量 以启用或禁用游戏对象 该变量位于游戏对象 Player 中 此处右下角 我需要启用或禁用这个游戏对象 Bouclier01 为此 我将脚本附加到游戏对象 Bouclier
  • 在windows + opengl中选择图形设备

    我知道如何使用 openGL 打开窗口 使用 Win32 或其他工具包 但是当系统有2块显卡时 如何选择要渲染的图形设备 我的编程语言是 C 我专注于 Windows 但任何示例都将受到欢迎 编辑 也许更好地解释我的问题是个好主意 以便添加

随机推荐

  • Python面试准备_排序算法

    最常问的Python排序算法 1 冒泡排序 核心算法 选取每个元素 依次跟右边的元素比较 def my sort arr if not isinstance arr list return None i控制比较多少轮 最后1个元素可以不比
  • qtcpsocket调用write和read函数写数据乱码问题解决方法

    参考以下博客QTcpSocket通信乱码解决方法 http blog csdn net zouhao619 article details 7100752 qtcpsocket写中文会乱码 在写入前和读出后进行处理一下就可以正常显示 如先调
  • etcd键值操作

    etcd 删除键值 1 查询所有键值 curl http 10 0 2 255 9001 v2 keys services recursive true 2 删除键值 curl http 10 0 22 39 9001 v2 keys ke
  • 在 Win10 中加快微软账户登录速度的解决方案

    修改DNS即可
  • 2022年中职组网络安全国赛A模块解析第二套

    2022年全国职业院校技能大赛 中职组 网络安全竞赛试题 2 总分100分 赛题说明 一 竞赛项目简介 网络安全 竞赛共分A 基础设施设置与安全加固 B 网络安全事件响应 数字取证调查和应用安全 C CTF夺旗 攻击 D CTF夺旗 防御等
  • Unix_Linux_AIX_常用命令总结

    目录 Java常用知识总结 前言 常用链接 Shell 自动化 处理相关 需要使用到的命令 编码思想 编码规范 shell脚本 循环处理 1 循环小火车 2 循环cup性能 各种命令 0 cd 1 uname 2 ifconfig 3 wh
  • PHP入门-PHP OOP类的继承(构造函数;public、protected和private;self、parent、final )

    0x00 写在前面 从零学习php 最终目的实现代码审计入门 软件采用sublime text 环境使用phpstudy搭建 需要有简单的html基础和php基础 跟随流沙前辈视频学习记录 OOP编程即面对对象编程 本篇学习面向对象中的继承
  • STM32(一)STM32简介

    一 什么是STM32 意法半导体 ST 集团于1988年6月成立 是由意大利的SGS微电子公司和法国Thomson半导体公司合并而成 1998年5月 SGS THOMSON Microelectronics将公司名称改为意法半导体有限公司
  • Linux下的硬件驱动——USB设备(上)(驱动配置部分)

    USB设备越来越多 而Linux在硬件配置上仍然没有做到完全即插即用 对于Linux怎样配置和使用他们 也越来越成为困扰我们的一大问题 本文着力从Linux系统下设备驱动的架构 去阐述怎样去使用和配置以及怎样编制USB设备驱动 对于一般用户
  • python程序基本格式

    缩进风格 恰当的空格 缩进问题 逻辑行首的空白 空格和制表符 用来决定逻辑行的缩进层次 从而用来决定语句的分组 语句从新行的第一列开始 缩进风格统一 每个缩进层次使用 单个制表符 或四个空格 IDE会自动将制表符设置成4个空格 Python
  • 软件测试过程

    目录 软件测试过程模型 计划和控制 测试计划 分析与设计 实现与执行 评估与报告 结束活动 标准的测试流程包括 计划与控制 分析与设计 实现与执行 评估与报告和结束活动 实际测试过程中分为 测试计划 测试方案 测试用例 测试执行 测试报告五
  • 用VS Code搞Qt6:编译源代码与基本配置

    优质资源分享 学习路线指引 点击解锁 知识定位 人群定位 Python实战微信订餐小程序 进阶级 本课程是python flask 微信小程序的完美结合 从项目搭建到腾讯云部署上线 打造一个全栈订餐系统 Python量化交易实战 入门级 手
  • JAVA(Spring)学习笔记---->Scope(作用域)

    这篇文章笔者和大家来聊一聊Spring中的两个标签配置范围 即singleton和prototype 前者意味单例的 后者则是多例的 Scope取值 实例化个数 实例化时机 对象创建 对象运行 对象销毁 singleton 单例 饿汉式 1
  • 华为配置端口流量统计

    配置端口流量统计 方便我们检查端口流量使用情况 排除问题 进行优化管理 以下是端口流量 统计的配置方法 步骤如下 a 先定义acl 匹配ping的源 目的IP地址 x和y是您这边测试的地址 ACL的编号自己随便定义 必须是3000以上 具体
  • Selenium图片下载到本地的实例

    目录 一 实例 指定网站 下载到本地的图片 今天与大家分享一个小案例 简单来说就是通过Selenium爬取京东 html页面的商品信息 图片 一 实例 指定网站 下载到本地的图片 效果展示 下载到本地图片 最后的通过Selenium下载到本
  • docker--扩展学习-理论--01

    docker 扩展学习 理论 01 一 Docker的应用场景 Web 应用的自动化打包和发布 自动化测试和持续集成 发布 在服务型环境中部署和调整数据库或其他的后台应用 从头编译或者扩展现有的 OpenShift 或 Cloud Foun
  • 微信开发

    近期在做模板消息推送用户的时候 遇到了报错码40001 但这是腾讯的万能报错码 感觉什么都是这个码顶锅 其实access token并不一定是真的过期导致的 先放一个官方调试工具在这 微信公众平台接口调试工具 1 有可能access tok
  • Python第三方库——rdflib

    实验要求 使用Python的第三方库rdflib 执行核心代码 如操作RDF OWL 执行SPARQL语句 参考资料 rdflib及其使用方法 rdflib 5 0 0 实验过程 在PyCharm上安装第三方库 点击PyCharm左下方的T
  • 如何设计日志系统_如何快速搭建日志系统

    易哥 高级软件架构师 网络工程师 数据库工程师 注册电气工程师 我们开发的业务系统通常会提供给很多人使用 那在使用的过程中 日志系统变得非常重要 日志系统记录的用户行为有以下的作用 从系统用户角度看 它展示了用户自身的操作历史和具体对象的变
  • C++ 虚函数 (virtual function) 介绍

    文章目录 1 什么是虚函数 2 虚函数与非虚函数的区别 3 派生类中的虚函数 4 构造 析构函数可以是虚函数吗 5 纯虚函数 5 1 纯虚函数的定义 5 1 纯虚函数的特定 1 什么是虚函数 C 对象有三大特性 继承 封装 多态 虚函数就是