C++多态的理解

2023-11-06

1.多态的概念及分类

多态是面向对象程序设计的一个重要特征。多态的字面意思就是多种状态,在面向对象的程序设计中,一个接口,多种实现即为多态。c++的多态性具体体现在编译和运行两个阶段。编译时多态是静态多态,在编译时就可以确定使用的接口。运行时多态是动态多态,具体引用的接口在运行时才能确定。

静态多态和动态多态区别其实只是在什么时候将函数实现和函数调用关联起来,是在编译时期还是运行时期,即函数地址是早绑定还是晚绑定。静态多态是指在编译期间就可以确定函数的调用地址,并产生代码,这是静态的,也就是说地址是早绑定。静态多态也被叫做静态联编。动态多态是指函数在运行期间才能确定函数的调用地址,这是动态的,也就是说地址是晚绑定。

1.1 静态多态

主要通过函数重载、泛型编程来实现。比如说,相同的函数名,可以通过不同的形参。重载出不同的函数,这就是多态的特性,但这里多态是编译阶段完成,也就是说编译器会将函数绑定到唯一确定的形式上去,这就是静态多态。

1.2 动态多态

动态多态是通过虚函数和类的继承来实现的。动态多态需要满足如下条件:

  1. 有继承关系;
  2. 子类要重写父类的虚函数(带virtual的函数);
  3. 父类指针指向子类对象;

1.3 虚函数、虚指针、虚表

对于类的成员函数,如果前面加上virtual,那么这个成员函数就是虚函数,这个类就是带有虚函数的类。带有虚函数的类比不带虚函数的类会多一个指针,这个指针就是虚指针,而 虚指针指向一个表,这个表就叫做虚表。虚表里面存的内容就是虚函数的地址。虚表是基于类的,也就是说任何带有虚函数的类都会有一张虚表,这张表是在编译时生成的。而虚指针是基于对象的,当初始化对象时,才会初始化虚指针,这是发生在程序运行时,也是动态多态的关键。

1.4 纯虚函数

纯虚函数是在基类中声明的虚函数,它在基类中是没有定义的,但要求任何派生类都要定义自己的实现方法。在基类中实现纯虚函数的方法是在函数原型后加=0,形如以下格式:

virtual void fun()=0;

  含有纯虚函数的类称之为抽象类,它不能生成对象即创建实列,只能创建它的派生类的实例。抽象类只能作为基类来使用,其纯虚函数的实现由派生类给出。如果派生类中没有重新定义纯虚函数,而只是继承基类的纯虚函数,则这个派生类仍然还是一个抽象类。如果派生类中给出了基类纯虚函数的实现,则该派生类就不再是抽象类了,它是一个可以建立对象的具体的类。

1.5 虚函数和纯虚函数之间的区别

  1. 当基类中的某个成员方法,在大多数情形下都应该由子类提供个性化实现,但基类也可以提供缺省备选方案的时候,该方法应该设计为虚函数。
  2. 当基类中的某个成员方法,必须由子类提供个性化实现的时候,应该设计为纯虚函数。

构造函数和析构函数可以是虚函数吗?

答案是:构造函数不能是虚函数,析构函数可以是虚函数且推荐最好设置为虚函数。

1.6 向上类型转换和向下类型转换

向下类型转换是基类转为派生类的强制类型转换,这种类型转换方式是不安全的;向上类型转换是派生类向基类的类型转换是安全的,如果发生多态,总是安全的。

//向下类型转换 基类转派生类 不安全的
Animal *animal=new Animal;
Cat *cat=(Cat*) animal;

//向上类型转换 派生类转基类 安全的
Cat * cat=new Cat;
Animal *ani=(Aniaml *) cat;

//如果发生多态 总是安全的
Animal *animal=new Cat;
Cat *cat=(Cat *)animal;

2.例子

地址早绑定

#include <iostream>
using namespace std;
//基类 水果类
class Fruit
{
public:
	void getClassName()
	{
		cout << "我是水果类" << endl;
	}

private:

};
//派生类 苹果类
class Apple:public Fruit
{
public:
	void getClassName()
	{
		cout << "我是苹果类" << endl;
	}

private:

};
//地址早绑定 在编译阶段就已经确定了是执行基类的getClassName()函数
void GetClassName(Fruit &fruit) {
	fruit.getClassName();
}
int main()
{
	Apple apple;
	GetClassName(apple);
	return 0;
}

结果

 

地址晚绑定

#include <iostream>
#include <opencv2/opencv.hpp>
using namespace std;
using namespace cv;
//基类 水果类
class Fruit
{
public:
	//加上virtual
	virtual void getClassName()
	{
		cout << "我是水果类" << endl;
	}

private:

};
//派生类 苹果类
class Apple:public Fruit
{
public:
	void getClassName()
	{
		cout << "我是苹果类" << endl;
	}

private:

};
//派生类 香蕉类
class Banana :public Fruit
{
public:
	void getClassName()
	{
		cout << "我是香蕉类" << endl;
	}
};
//给父类加上virtual 关键字 地址晚绑定 在运行时再确定调用谁的getClassName()
void GetClassName(Fruit &fruit) {
	fruit.getClassName();
}
int main()
{
	Apple apple;
	Banana banana;
	//GetClassName(apple);
	GetClassName(banana);
	waitKey(10000);
	//return 0;
}

 结果

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

C++多态的理解 的相关文章

  • 编译时运算符

    有人可以列出 C 中可用的所有编译时运算符吗 C 中有两个运算符 无论操作数如何 它们的结果始终可以在编译时确定 它们是sizeof 1 and 2 当然 其他运算符的许多特殊用途可以在编译时解决 例如标准中列出的那些整数常量表达式 1 与
  • 如何使用 C# 中的参数将用户重定向到 paypal

    如果我有像下面这样的简单表格 我可以用它来将用户重定向到 PayPal 以完成付款
  • 没有强命名的代码签名是否会让您的应用程序容易被滥用?

    尝试了解authenticode代码签名和强命名 我是否正确地认为 如果我对引用一些 dll 非强命名 的 exe 进行代码签名 恶意用户就可以替换我的 DLL 并以看似由我签名但正在运行的方式分发应用程序他们的代码 假设这是真的 那么您似
  • “构建”构建我的项目,“构建解决方案”则不构建

    我刚刚开始使用VS2010 我有一个较大的解决方案 已从 VS2008 成功迁移 我已将一个名为 Test 的控制台应用程序项目添加到解决方案中 选择构建 gt 构建解决方案不编译新项目 选择构建 gt 构建测试确实构建了项目 在失败的情况
  • 动态加载程序集的应用程序配置

    我正在尝试将模块动态加载到我的应用程序中 但我想为每个模块指定单独的 app config 文件 假设我的主应用程序有以下 app config 设置
  • 秒表有最长运行时间吗?

    多久可以Stopwatch在 NET 中运行 如果达到该限制 它会回绕到负数还是从 0 重新开始 Stopwatch Elapsed返回一个TimeSpan From MSDN https learn microsoft com en us
  • 在哪里可以找到列出 SSE 内在函数操作的官方参考资料?

    是否有官方参考列出了 GCC 的 SSE 内部函数的操作 即 头文件中的函数 除了 Intel 的 vol 2 PDF 手册外 还有一个在线内在指南 https www intel com content www us en docs in
  • 类模板参数推导 - clang 和 gcc 不同

    下面的代码使用 gcc 编译 但不使用 clang 编译 https godbolt org z ttqGuL template
  • 如何使用 ICU 解析汉字数字字符?

    我正在编写一个使用 ICU 来解析由汉字数字字符组成的 Unicode 字符串的函数 并希望返回该字符串的整数值 五 gt 5 三十一 gt 31 五千九百七十二 gt 5972 我将区域设置设置为 Locale getJapan 并使用
  • OleDbDataAdapter 未填充所有行

    嘿 我正在使用 DataAdapter 读取 Excel 文件并用该数据填充数据表 这是我的查询和连接字符串 private string Query SELECT FROM Sheet1 private string ConnectStr
  • 在 ASP.NET 5 中使用 DI 调用构造函数时解决依赖关系

    Web 上似乎充斥着如何在 ASP NET 5 中使用 DI 的示例 但没有一个示例显示如何调用构造函数并解决依赖关系 以下只是众多案例之一 http social technet microsoft com wiki contents a
  • 显示UnityWebRequest的进度

    我正在尝试使用下载 assetbundle统一网络请求 https docs unity3d com ScriptReference Networking UnityWebRequest GetAssetBundle html并显示进度 根
  • 如何设计以 char* 指针作为类成员变量的类?

    首先我想介绍一下我的情况 我写了一些类 将 char 指针作为私有类成员 而且这个项目有 GUI 所以当单击按钮时 某些函数可能会执行多次 这些类是设计的单班在项目中 但是其中的某些函数可以执行多次 然后我发现我的项目存在内存泄漏 所以我想
  • while 循环中的 scanf

    在这段代码中 scanf只工作一次 我究竟做错了什么 include
  • 如何在整个 ASP .NET MVC 应用程序中需要授权

    我创建的应用程序中 除了启用登录的操作之外的每个操作都应该超出未登录用户的限制 我应该添加 Authorize 每个班级标题前的注释 像这儿 namespace WebApplication2 Controllers Authorize p
  • 如何查看网络连接状态是否发生变化?

    我正在编写一个应用程序 用于检查计算机是否连接到某个特定网络 并为我们的用户带来一些魔力 该应用程序将在后台运行并执行检查是否用户请求 托盘中的菜单 我还希望应用程序能够自动检查用户是否从有线更改为无线 或者断开连接并连接到新网络 并执行魔
  • 哪种 C 数据类型可以表示 40 位二进制数?

    我需要表示一个40位的二进制数 应该使用哪种 C 数据类型来处理这个问题 如果您使用的是 C99 或 C11 兼容编译器 则使用int least64 t以获得最大的兼容性 或者 如果您想要无符号类型 uint least64 t 这些都定
  • 如何在文本框中插入图像

    有没有办法在文本框中插入图像 我正在开发一个聊天应用程序 我想用图标图像更改值 等 但我找不到如何在文本框中插入图像 Thanks 如果您使用 RichTextBox 进行聊天 请查看Paste http msdn microsoft co
  • 如何防止用户控件表单在 C# 中处理键盘输入(箭头键)

    我的用户控件包含其他可以选择的控件 我想实现使用箭头键导航子控件的方法 问题是家长控制拦截箭头键并使用它来滚动其视图什么是我想避免的事情 我想自己解决控制内容的导航问题 我如何控制由箭头键引起的标准行为 提前致谢 MTH 这通常是通过重写
  • 使用.NET技术录制屏幕视频[关闭]

    Closed 这个问题正在寻求书籍 工具 软件库等的推荐 不满足堆栈溢出指南 help closed questions 目前不接受答案 有没有一种方法可以使用 NET 技术来录制屏幕 无论是桌面还是窗口 我的目标是免费的 我喜欢小型 低

随机推荐

  • 毕业设计-基于机器学习的新冠肺炎疫情预测精度研究

    目录 前言 课题背景和意义 实现技术思路 一 国内新冠肺炎疫情的统计分析 二 基于机器学习模型的新冠肺炎疫情研究 三 基于深度学习模型的新冠肺炎疫情研究 实现效果图样例 最后 前言 大四是整个大学期间最忙碌的时光 一边要忙着备考或实习为毕业
  • CentOS 7 搭建CA证书服务器

    一 实验环境 CA 192 168 199 141 Apache 192 168 199 143 二 实验步骤 1 CA证书服务器的配置 1 1 安装openssl工具 默认使安装完成的 root CA yum install y open
  • 十进制转8421_BCD码

    目录 一 BCD码简介 二 十进制转8421BCD码转换思路 三 程序编写 四 仿真验证 总结 一 BCD码简介 BCD码 Binary Coded Decimal 用4位二进制数来表示1位十进制数中的0 9这10个数码 是一种二进制的数字
  • JAVASCRIPT调用WEBSERVICE

    HTML端代码
  • inno setup打包脚本总结

    inno setup是比较简单好用的一款打包工具 下面以打包HelloWorld exe为例进行说明 一 打包目录的建立 创建source目录 用于放置主程序 依赖dll 资源等待打包文件 创建output目录 用于存放生成的安装包 Hel
  • BRDF详解(包括:irradiance,radiance,intensity,立体角)

    BRDF BRDF是双向反射分布函数 Bidirectional Reflectance Distribution Function BRDF 用来定义给定入射方向上的辐射照度 irradiance 如何影响给定出射方向上的辐射率 radi
  • 将GAN用于语义分割

    深度学习已经在图像分类 检测 分割 高分辨率图像生成等诸多领域取得了突破性的成绩 但是它也存在一些问题 首先 它与传统的机器学习方法一样 通常假设训练数据与测试数据服从同样的分布 或者是在训练数据上的预测结果与在测试数据上的预测结果服从同样
  • 使用char型数组过程中遇到的问题

    简述 最近开发中用到了char数组来接收数据 在使用中遇到了一些问题 这里记录一下 同时也回顾一下char数组的用法 代码之路 事例一 char aa 0 首先 我们要知道 0长度的数组在ISO C和C 的规格说明书中是不允许的 用VS20
  • 用人工智能压缩图像的尝试2

    收集42亿个8 8像素图 对它们排序 让形状接近的图排在接近的位置 然后输入ANN1 它以8 8 3字节为输入 32比特为输出 再训练ANN2 它以32比特index为输入 8 8的pixels为输出 总数据量为 8 8 3 4 B 4G
  • python中generate什么意思_python generate怎么用

    generate语句允许细化时间 Elaboration time 的选取或者某些语句的重复 这些语句可以包括模块实例引用的语句 连续赋值语句 always语句 initial语句和门级实例引用语句等 细化时间是指仿真开始前的一个阶段 此时
  • HNCTF week1

    Xor 代码分析 puts please input your flag scanf s Str 输入22个字符串 if strlen Str 22 printf strlen error exit 0 将输入的22个字符与0x34进行异或
  • vue学习之父子组件及插槽

    父子组件 父子组件是组件之间的一种关系 这个关系并不是绝对的 而是相对的 通常 如果在A组件中 使用 了B组件 那么就称A组件为B组件的父组件 相应地 B组件就称为A组件的子组件
  • 动手学CV-目标检测入门教程5:损失函数

    3 5 损失函数 本文来自开源组织 DataWhale CV小组创作的目标检测入门教程 对应开源项目 动手学CV Pytorch 的第3章的内容 教程中涉及的代码也可以在项目中找到 后续会持续更新更多的优质内容 欢迎 如果使用我们教程的内容
  • php数组转xml

    span style font family none ar array span auth gt array user gt customer password gt password context gt 4 owner gt arra
  • 二、一个简单的两层神经网络的实现

    目录 一 numpy实现 二 pytorch实现 1 手动求导 2 自动求导 三 torch nn torch optim实现实现 1 torch nn实现自动求导 2 optim选择并执行各种优化方法 3 继承torch nn Modul
  • 16课:关于Springboot和@Cacheable注解拉去缓存,@CacheEvict清空缓存的原理

    16课 关于Springboot和 Cacheable注解拉去缓存 CacheEvict清空缓存的原理 简介 代码展示 1 pox xml 2 application properties文件 3 RedisCacheableConfig缓
  • ARM开发板介绍及SRAM和SDRAM的区别

    开发板型号 tiny 4412 核心板 exynos4412 三星 SOC ARM架构 ARMv7 架构 coretex A9系列 四核1 4Ghz 32 bit SRAM 256K ROM 16K DDR SDRMD 1Gbyts 内存物
  • vue父组件监听子组件生命周期

    还是记一下吧 总是忘 通过在子组件生命周期里公开一个事件 通过父组件监听 在子组件中 mounted this emit mounted mounted 触发了 父组件监听
  • 解决AD 敷铜连不上焊盘的问题

    一 如下选择 第二步 点击 添加 新建一个网络点 GND 网络名 GND 然后点击 确定 第三步 选择需要连线的焊盘 Net处选择 GND 第四步 选择敷铜按钮 网络选项中 链接到网络选择 GND 结果
  • C++多态的理解

    1 多态的概念及分类 多态是面向对象程序设计的一个重要特征 多态的字面意思就是多种状态 在面向对象的程序设计中 一个接口 多种实现即为多态 c 的多态性具体体现在编译和运行两个阶段 编译时多态是静态多态 在编译时就可以确定使用的接口 运行时