【C++】多态 ⑩ ( 不建议将所有函数都声明为 virtual 虚函数 | 多态的理解层次 | 父类指针和子类指针步长 )

news2024/11/27 21:50:43

文章目录

  • 一、不建议将所有函数都声明为 virtual 虚函数
  • 二、多态的理解层次
  • 三、父类指针和子类指针步长


对象可以直接获取到自身封装的 普通函数 , 如果要访问虚函数 , 需要增加一次寻址操作 , 因此 这里建议不需要将有 多态 需求的函数声明为 虚函数 ;

C++ 中 指向某类型对象的 指针 的 运算 , 是 根据 指针类型 进行的 , 指针 自增 ++ , 指针的地址值 会增加 指针类型字节大小 ;

指针的 步长 是 根据 指针 指向的 内存空间 的数据类型确定的 ;

子类 继承 父类 , 如果 子类 没有添加任何 成员函数 与 成员方法 , 那么子类指针 与 父类指针 的步长是相同的 ;





一、不建议将所有函数都声明为 virtual 虚函数



C++ 类中 , 每个 成员函数 都可以声明为 virtual 虚函数 , 但是 这样会降低 运行效率 , 每次访问 成员函数 时 , 都需要通过 vptr 指针获取 虚函数表 中的函数地址 , 显然会极大的降低效率 ;

在这里插入图片描述

如果 调用 非虚函数 , 可以直接通过 对象 获取到 非虚函数 的地址 , 不必通过 vptr 指针 从 虚函数表 中获取 函数地址 ;


显然 , 对象可以直接获取到自身封装的 普通函数 , 如果要访问虚函数 , 需要增加一次寻址操作 , 因此 这里建议不需要将有 多态 需求的函数声明为 虚函数 ;





二、多态的理解层次



多态的理解层次 :

  • 多态实现效果 : 相同的代码调用 , 有不同的表现形态 ; 父类指针 可 指向子类对象 , 使用父类指针 调用 虚函数 可执行 子类对应的函数 ;
  • 多态实现条件 : ① 继承 , ② 虚函数重写 , ③ 父类指针/引用指向子类对象 ;
    • 父类指针 可以 指向 父类对象 , 也可以指向 不同的 子类对象 ;
    • 通过 父类指针 调用 virtual 虚函数 , 会根据实际的对象类型调用不同的 虚函数 , 而不是死板的调用父类的成员函数 ;
  • 多态实现原理 : 虚函数 对应 动态联编 , 非虚函数 对应 静态联编 ;
    • 有 虚函数 的类 , 在 编译时 , 会生成 虚函数表 , 对应类中生成一个 vptr 指针指向 虚函数表 ;
    • vptr 指针 是 与 对象绑定的 , 调用时 从 对象的 虚函数表 中查找虚函数 ;
    • 通过 父类指针 访问虚函数时 , 直接根据 实际对象 的 vptr 指针找该对象的 虚函数表 , 然后调用 虚函数表 中的 虚函数 ;
  • 多态意义 : 多态是 设计模式 的基础 , 是 软件框架 的基础 ;




三、父类指针和子类指针步长



指针数据类型 : C++ 中 指针 是 数据类型 的 一种 , 对 指针 进行 自增 ++ 或 自减 – 操作 , 指针的 地址值 是根据 指针类型 改变的 ;

指针运算 : C++ 中 指向某类型对象的 指针 的 运算 , 是 根据 指针类型 进行的 , 指针 自增 ++ , 指针的地址值 会增加 指针类型字节大小 ;

如 : 指针 Student* p , 其类型是 自定义的 Student 类型 , 则 p++ 的计算结果是 p 指针的地址值 加上 sizeof(*p) 对象的字节长度 ;


显然 父类 与 子类 对象 的 字节大小是不同的 , 在进行数组操作 , 或 指针运算时 , 指针 或 数组 的类型 必须一致 , 一定不能使用多态 ;


指针步长自增 是 根据 声明的 类型 进行自增的 , 不是根据 指针实际指向的对象类型的大小进行自增的 ;


指针的 步长 是 根据 指针 指向的 内存空间 的数据类型确定的 ;


子类 继承 父类 , 如果 子类 没有添加任何 成员函数 与 成员方法 , 那么子类指针 与 父类指针 的步长是相同的 ;


代码示例 :

#include "iostream"
using namespace std;

// 父类
class Parent {
public:
	virtual void fun()
	{
		cout << "执行 父类 Parent 的 virtual void fun(int a) 函数" << endl;
	}
	int a;
};

// 子类
class Child : public Parent {
public:
	virtual void fun()
	{
		cout << "执行 子类 virtual void fun(int a) 函数" << endl;
	}
	int b;
};

int main() {

	Parent* p = NULL;
	Child* c = NULL;

	Child array[] = {Child(), Child(), Child()};

	p = array;
	c = array;

	p->fun();
	c->fun();

	// 步长加 1 , 然后继续调用
	// 指针步长自增 是 根据 声明的 类型 进行自增的 
	// 不根据 实际的类型 自增 
	p++;
	c++;

	// 父类指针 自增 后 , 增加的是 父类的步长
	// 此时指向的位置 不是 元素的首地址 , 肯定会出错
	//p->fun();
	// 子类步长加 1 , 指针正常
	c->fun();

	// 控制台暂停 , 按任意键继续向后执行
	system("pause");

	return 0;
}

执行结果 :
执行 子类 virtual void fun(int a) 函数
执行 子类 virtual void fun(int a) 函数
执行 子类 virtual void fun(int a) 函数
Press any key to continue . . .

在这里插入图片描述

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

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

相关文章

有什么好用的仓库配件管理软件?如何实现企业配件管理智能化?

在当今高度信息化的商业环境中&#xff0c;企业运营的效率和管理的重要性日益凸显。对于许多企业来说&#xff0c;仓库配件管理是一个关键的环节&#xff0c;它不仅涉及到物品的存储和分发&#xff0c;还与企业的成本控制和运营流程紧密相关。然而&#xff0c;管理仓库配件是一…

C++快餐——C++11(3)

应该在脖子上长一个自己的脑袋 文章目录 function包装器bind绑定普通函数绑定成员函数std::bind优点 线程库thread类创建线程线程管理线程标识 原子性操作库(atomic)lock_guard与unique_lockstd::lock_guardstd::unique_lock mutex的种类总结 function包装器 C11引入了一个名为…

ubuntu启动报错error: proc_thermal_add, will cont

如题&#xff0c;ubuntu启动报错error: proc_thermal_add, will cont 截图如下&#xff1a; 困扰了我很久&#xff0c;差点就打算重装系统&#xff0c;准备放弃了&#xff0c;但是感谢国外的老哥&#xff0c;写了一篇非常详细的解决方案&#xff0c;我搬过来。 解决方案&#…

基础课14——文本标注

人工智能界流传一句俏皮话&#xff1a;“有多少人工&#xff0c;就有多少智能。” 1.人工智能数据标注介绍 2018年9月&#xff0c;百度智能云与山西综改示范区达成合作&#xff0c;在太原共同建立了百度&#xff08;山西&#xff09;人工智能基础数据产业基地&#xff08;简称…

AI时代,ChatGPT与文心一言选哪一个?

&#x1f388;个人公众号:&#x1f388; :✨✨✨ 可为编程✨ &#x1f35f;&#x1f35f; &#x1f511;个人信条:&#x1f511; 为与不为皆为可为&#x1f335; 你们平时都是在什么情况下使用GPT的呢&#xff1f;为何使用&#xff1f;都使用什么平台的&#xff1f; 针对以上问…

高防CDN的特点与作用

高级防护CDN是一种专门设计用于提供出色的网络安全功能的内容分发网络。它通过采用分布式节点、智能路由和强大的安全机制&#xff0c;旨在确保网站在面临各种网络攻击时保持安全&#xff0c;同时提供内容的快速传递和优化功能。那么&#xff0c;高级防护CDN有哪些独特的特点和…

win10pycharm和anaconda安装和环境配置教程

windows10 64位操作系统下系统运行环境安装配置说明 下载和安装Anaconda&#xff0c;链接https://www.anaconda.com/download 下载完后&#xff0c;双击exe文件 将anaconda自动弹出的窗口全部关掉即可&#xff0c;然后配置高级系统变量 根据自己的路径&#xff0c;配置…

前端移动高级web详细解析五

响应式布局方案 媒体查询 Bootstrap框架 01-媒体查询 基本写法 max-width&#xff1a;最大宽度&#xff08;小于等于&#xff09; min-width&#xff1a;最小宽度&#xff08;大于等于&#xff09; 书写顺序 min-width&#xff08;从小到大&#xff09; max-width&…

IDEA上也能用Postman了?

Postman是大家最常用的API调试工具&#xff0c;国产API调试工具 Apipost 推出IDEA插件&#xff0c;写完代码就可以调试接口并一键生成接口文档&#xff01;而且还可以根据已有的方法帮助您快速生成 url 和 params。Apipost Helper API 调试工具 API 管理工具 API 搜索工具。…

领先实践|IDEO 最佳设计思维和策略框架

设计思维是一种以人为本的创新方法&#xff0c;它从人类的角度出发&#xff0c;考虑技术上可行和经济上可行的内容。框架可以成为实现设计思维、策略和系统设计的有用工具。本文由此展开阐述 IDEO 的最佳设计思维和策略框架。 01. 设计思维框架 1.1 设计思维过程 设计思维?是…

【python】爬取豆瓣电影排行榜TOP250存储到CSV文件中

一、导入必要的模块&#xff1a; 代码首先导入了需要使用的模块&#xff1a;requests、lxml和csv。 import requests from lxml import etree import csv 如果出现模块报错 进入控制台输入&#xff1a;建议使用国内镜像源 pip install 模块名称 -i https://mirrors.aliyun.co…

Failed to launch task: 文件”Setup”不存在 Mac安装Adobe软件报错解决方案

在安装 Adobe 软件时&#xff0c;软件提示 Failed to launch task: 文件”Setup”不存在 &#xff0c;这个时候怎么处理呢&#xff1f; 解决方法如下&#xff1a; 1、安装 AnitCC 或 或 Creative Cloud 环境&#xff0c;保证软件所需要的环境 2、如果安装后也不起作用&#x…

[ThinkPHP]源码阅读:Model的获取器

目录 1、ThinkPHP组件版本 2、业务Model代码 3、阅读框架源码 4、跳过获取器获取原始数据写法 1、ThinkPHP组件版本 topthink/think-orm v2.0.58 topthink/think-helper v3.1.6 2、业务Model代码 原理&#xff1a;Model通过调用toArray方法使用自定义的获取器 3、阅读框架…

GZ035 5G组网与运维赛题第8套

2023年全国职业院校技能大赛 GZ035 5G组网与运维赛项&#xff08;高职组&#xff09; 赛题第8套 一、竞赛须知 1.竞赛内容分布 竞赛模块1--5G公共网络规划部署与开通&#xff08;35分&#xff09; 子任务1&#xff1a;5G公共网络部署与调试&#xff08;15分&#xff09; 子…

Web Woeker和Shared Worker的使用以及案例

文章目录 1、前言2、介绍 Web Worker3、使用须知及兼容性3.1、使用须知3.2、兼容性 4、使用 Web Worker4.1、创建 Web Worker4.2、与主线程通信4.3、终止 Web Worker4.4、监听错误信息 5、使用 Shared Worker4.5、调试 Shared Worker 6、使用中的一些坑6.1、Web Woeker 中引入了…

第4章_运算符

文章目录 1. 算术运算符1.1 加法与减法运算符1.2 乘法与除法运算符1.3 求模运算符 2. 比较运算符2.1 等号运算符2.2 安全等于运算符2.3 不等于运算符2.4 空运算符2.5 非空运算符2.6 最小值运算符2.7 最大值运算符2.8 BETWEEN AND运算符2.9 IN运算符2.10 NOT IN运算符2.11 LIKE运…

k8s中kubectl命令式对象、命令式对象配置、声明式对象配置管理资源介绍

目录 一.kubernetes资源管理简介 二.三种资源管理方式优缺点比较 三.命令式对象管理介绍 1.kubectl命令语法格式 2.资源类型 &#xff08;1&#xff09;通过“kubectl api-resources”来查看所有的资源 &#xff08;2&#xff09;每列含义 &#xff08;3&#xff09;常…

Java 设计模式——命令模式

目录 1.概述2.结构3.案例实现3.1.命令接口3.2.具体命令3.3.接受者3.4.调用者3.5.测试 4.优缺点5.使用场景6.JDK 源码解析——Runnable 1.概述 &#xff08;1&#xff09;日常生活中&#xff0c;我们出去吃饭都会遇到下面的场景&#xff1a; &#xff08;2&#xff09;命令模…

Go语言集成开发环境(IDE):GoLand 2023中文

GoLand 2023是一款由JetBrains开发的现代化、功能丰富的Go语言集成开发环境&#xff08;IDE&#xff09;。它提供了智能代码提示和自动完成、强大的内置调试器以及代码重构工具&#xff0c;帮助开发者提高编码效率并确保代码质量。GoLand 2023还支持多种版本控制系统&#xff0…

kubernetes-ingress-nginx

目录 一、部署 二、访问 1.基于路径访问 2.基于域名访问 三、加密与认证 1.TLS加密 2.auth认证 四、rewrite重定向 五、canary金丝雀发布 1.基于header灰度 2.基于权重灰度 3.业务域拆分 一、部署 ingress-nginx是一个开源的Kubernetes Ingress控制器&#xff0c;用…