C++之多态(下)

news2024/11/27 16:44:25

目录

多态的实现原理

多态的拓展 

单继承中的多态 

多继承中的多态


上期,我们学习了多态的基本概念,本期我们来学习多态的实现原理。

多态的实现原理

class Base
{
public:
	virtual void func1()
	{
		cout << "Base::func1()" << endl;
	}
private:
	int _a;
	char _ch;
};

对于上述Base这个类而言,sizeof(Base)有多大呢?

大多数人可能认为是8个字节,按照以往的知识,考虑了内存对齐的大小之后,看似是8个字节貌似也没有什么问题,我们不妨通过实践,来看一下这个Base有多大。

通过运行结果不难发现,Base类的大小竟然是12字节,这是为什么呢?我们通过创建了一个Base类对象通过监视窗口进一步查看。

 通过监视窗口,我们不难看出,虽然我们只定义了两个成员,但是实际上Base类中有三个成员,那么这个_vfptr成员变量是什么呢?

_vfptr我们称它为虚函数表指针,它指向了一个虚函数表,虚函数表就是一个虚函数指针数组,里面存储虚函数的地址,在子类虚函数表中,会先去存放从子类中继承下来的虚函数地址,然后再去存放自己类中生成的虚函数的地址。

那么有了这个虚函数表指针之后,我们是如何在底层实现多态的呢? 

代码如下。

class Base
{
public:
	virtual void func1()
	{
		cout << "Base::func1()" << endl;
	}
private:
	int _a;
	char _ch;
};

class Child:public Base
{
public:
	virtual void func1()
	{
		cout << "Child::func1()" << endl;
	}
};

int main()
{
	Base b;
	Child c;
	Base& b2 = b;
	b2.func1();
	Base& b3 = c;
	b3.func1();
	return 0;
}

运行结果如下。 

我们发现,上述代码实现了多态。通过图示为大家讲解原理。

    当我我们把b对象传给它的引用b2时,b2调用func1函数时,先会去找b的虚函数指针,然后通过虚函数指针找到b的虚函数表,然后在虚函数表中找到func1函数的地址然后去调用,这样就完成了调用父类Base类中的虚函数func1。

    当我们把c对象床位它的引用b3时,b3调用func1函数时,先会去找c的虚函数指针,然后通过虚函数指针找到c的虚函数表,然后在虚函数表中找到func1函数的地址然后去调用,这样就完成了调用子类Child类中的虚函数func1。

    简单来说,就是父类类的指针或者引用会根据传来的是子类还是父类对象,去对应的子类或者父类对象的虚函数表中去调用对应的虚函数,这便是多态的实现原理。

多态的拓展 

示例代码如下。

我们发现,同样的两个父类对象,他们的虚函数指针也是相同的。这其实也是多态的一个特点,就是同类的对象共用一张虚函数表,子类会继承父类的虚函数表,但是会对继承下来的虚函数表进行改写,所以虽然子类会继承父类的虚函数表,但是因为进行了改写,所以本质上子类的虚函数表和父类的虚函数表是两张不同的表。

这不由得产生了一个问题,虚函数表存放在哪里?栈里面吗?

当然不是,如果是栈里面,那么虚函数表的生命周期就随对象,太过麻烦,我们直接给出结论,虚函数表是与虚函数一眼个都是存放在代码段的。

单继承中的多态 

代码如下。

#include<iostream>
using namespace std;


class Base
{
public:
	virtual void func1()
	{
		cout << "Base::func1()" << endl;
	}
	virtual void func2()
	{
		cout << "Base::func2()" << endl;
	}

private:
	int _a;
	char _ch;
};

class Child:public Base
{
public:
	virtual void func1()
	{
		cout << "Child::func1" << endl;
	}
	
	virtual void func3()
	{
		cout << "Child::func3" << endl;
	}
};

int main()
{
	Base b;
	Child c;

	return 0;
}

 调试窗口如下。

我们发现子类的虚表中,存储从父类中继承下来的func2以及重写之后的func1,自己的func3函数其实也在虚表中,但是通过调试窗口看不见,只能通过内存观察。

 

多继承中的多态

代码如下。

#include<iostream>
using namespace std;


class Base1
{
public:
	virtual void func1()
	{
		cout << "Base1::func1()" << endl;
	}
	virtual void func2()
	{
		cout << "Base1::func2()" << endl;
	}

private:
	int _a;
	char _ch;
};
class Base2
{
public:
	virtual void func3()
	{
		cout << "Base2::func3()" << endl;
	}
	virtual void func4()
	{
		cout << "Base2::func4()" << endl;
	}

private:
	int _a;
	char _ch;
};

class Child:public Base1,public Base2
{
public:
	virtual void func1()
	{
		cout << "Child::func1" << endl;
	}
	
	virtual void func3()
	{
		cout << "Child::func3" << endl;
	}

	virtual void func5()
	{
		cout << "Child::Func5" << endl;
	}
};

int main()
{

	Child c;

	return 0;
}

监视窗口如下。

多继承中,子类会继承父类中的两个虚表并进行改写。继承下来的父类1的虚表存放从父类1中继承下来的fun1和func2函数,同样的,继承下来的父类2的虚表中存放从父类2中继承下来的func3和func4函数。

那么问题来了,子类中的虚函数func5到底存储在那个虚表里呢,是父类1还是父类2,父类1为Base1,父类2为Base2,调试通过内存进行观察。

Base1虚表中的内容如下。

 

Base2虚表中的内容如下。 

 

子类首先继承了父类Base1,然后继承了父类Base2,所以我们得出了结论,多继承中,子类的虚函数存放在首先继承的父类的虚表里面。 

以上便是多态的所有内容。

本期内容到此结束^_^ 

 

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

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

相关文章

CUTLASS 中的 47_ampere_gemm_universal_streamk 示例

前一篇文章介绍了 Stream-K: Work-centric Parallel Decomposition for Dense Matrix-Matrix Multiplication on the GPU 论文&#xff0c;下面对其代码实现进行分析。 cutlass 的 examples/47_ampere_gemm_universal_streamk 展示了 GEMM Stream-K 算法在 Ampere 架构上的使用…

健身房管理系统--论文pf

TOC springboot542健身房管理系统--论文pf 第1章 绪论 1.1选题动因 当前的网络技术&#xff0c;软件技术等都具备成熟的理论基础&#xff0c;市场上也出现各种技术开发的软件&#xff0c;这些软件都被用于各个领域&#xff0c;包括生活和工作的领域。随着电脑和笔记本的广泛…

思特科技:国家宝藏数字体验馆展现东方美学 让“文物活起来”

01      思特科技为“国家宝藏数字体验展”提供“数字技术”支持&#xff0c;带来国宝的数字化演绎。以《国家宝藏》顶级IP为基础&#xff0c;打造的全新沉浸文化项目“国宝数字体验展“&#xff0c;借由文物的视角、站在历史的星河中&#xff0c;探寻时间长河中不变的智慧…

设计模式笔记02(java版)

文章目录 创建者模式单例设计模式 ★单例模式的结构单例模式的实现饿汉式-方式1&#xff08;静态变量方式&#xff09;饿汉式-方式2&#xff08;静态代码块方式&#xff09;懒汉式-方式1&#xff08;线程不安全&#xff09;懒汉式-方式2&#xff08;线程安全&#xff09;懒汉式…

Linux环境安装 JDK

目录 JDK准备 1&#xff09;卸载现有JDK&#xff08;3台节点&#xff09; 2&#xff09;用Xftp工具将JDK导入到hadoop12的/opt/software文件夹下面 3&#xff09;在Linux系统下的opt目录中查看软件包是否导入成功 4&#xff09;解压JDK到/opt/module目录下 5&#xff09;配…

数据恢复新宠儿:2024年新兴软件趋势与亮点解析

你的手机、优盘、电脑里是不是都存储这你生活的点点滴滴&#xff1f;不知道你有没有遇到过数据误删或者消失的情况。如果有数据恢复精灵能帮你找回数据是不是为你的数据找回点亮了方向。这次我就介绍几款数据恢复工具带你走出数据丢失的困境。 1.福昕数据恢复 链接直达&#…

告别 Coding 噩梦-掌握这10个习惯,成为大数据开发高手

你是否曾在半夜被一个顽固的bug折磨得睡不着觉?是否因为理解不了复杂算法而感到沮丧?别担心,你并不孤单。作为一名经验丰富的大数据开发者,我深知编程之路上的挫折感。但今天,我要和你分享我是如何在这条充满荆棘的道路上找到突破,最终成长为一名得心应手的编程高手的。 前…

达梦数据库的系统视图v$tablespace

达梦数据库的系统视图v$tablespace 在达梦数据库&#xff08;DM Database&#xff09;中&#xff0c;V$TABLESPACE 提供了有关数据库中的表空间&#xff08;Tablespace&#xff09;信息。这些信息对于管理数据库存储和优化性能非常关键。表空间是数据库逻辑存储结构的一个层次…

基于Java的小区物业管理系统设计与实现

TOC springboot596基于Java的小区物业管理系统设计与实现--论文 研究背景 小区物业管理系统主要通过计算机网络&#xff0c;对小区物业管理系统所需的信息进行统一管理&#xff0c;方便用户随时随地进行增添、修改、查询、删除各类信息。本系统极大的促进了系统与数据库管理…

Python编码系列—前端后浪:Python前后端分离开发实战指南

&#x1f31f;&#x1f31f; 欢迎来到我的技术小筑&#xff0c;一个专为技术探索者打造的交流空间。在这里&#xff0c;我们不仅分享代码的智慧&#xff0c;还探讨技术的深度与广度。无论您是资深开发者还是技术新手&#xff0c;这里都有一片属于您的天空。让我们在知识的海洋中…

我“开发“了一款大模型应用,AI门槛这么低了吗?

现在国产大模型多如牛毛。虽然可选的大模型产品很多&#xff0c;但普遍存在同质化、高分低能、实用性差、专业性不足的问题&#xff0c;哪怕是诸如ChatGPT、Gemini这样全球顶尖的大模型也会存在这种情况。 还有一点比较重要的是&#xff0c;由于大模型需要算力、算法、数据的基…

干货:2024年四大翻译工具新体验!

在全球化的今天&#xff0c;语言的障碍似乎越来越小&#xff0c;这得益于各种翻译工具的飞速发展。从简单的在线翻译到复杂的AI翻译技术&#xff0c;我们有了更多的选择来跨越语言的鸿沟。以下是几款备受推崇的翻译工具&#xff0c;推荐给大家 福昕在线翻译 链接&#xff1a;…

onlyoffice连接器(connector)开发使用精讲 二次开发 深入开发【一】

连接器是onlyoffice调用web api的一个基础工具&#xff0c;可以方便开发者或者用户与业务系统结合使用web功能。 关于connector官方说明文档在这里&#xff1a;Automation API - ONLYOFFICE Api Documentation 注意&#xff1a;该功能针对开发者版、企业版&#xff0c;社区版常…

高考杂志社《高考》杂志社高考杂志社编辑部2024年第22期目录

高考论坛 高考内容改革背景下的高中数学教学策略探究 高琳琳; 3-5 新高考背景下高中数学教学中核心素养的培养路径 王芳芳; 6-8 教改研究 任务型教学在高中语文大单元教学中的应用 蔡莎; 9-11 大单元教学在高中思想政治教学中的应用探究 陈玲; 12-14 高中语文班…

局部整体(三)利用python绘制饼图

局部整体&#xff08;三&#xff09;利用python绘制饼图 饼图&#xff08; Pie Plot&#xff09;简介 饼图是一个将整体划分为几个扇形的圆形统计图表&#xff0c;用于描述数量、频率或百分比之间的相对关系。饼形图适合用来快速展示数据比例分布&#xff0c;但不利于展示较多…

华为手机相册的照片丢失或误删怎么恢复?

手机已经成为了生活中极其重要的一部分&#xff0c;尤其是华为手机用户&#xff0c;一定深知其出色的拍照功能和丰富的相册管理功能。然而&#xff0c;常有意外出现&#xff0c;如误删除、格式化、备份覆盖等情况导致手机相册的照片丢失&#xff0c;那么华为手机相册的照片怎么…

企业级WEB应用服务器——TOMCAT

一、WEB技术 1.1、HTTP协议和B/S 结构 最早出现了CGI&#xff08;Common Gateway Interface&#xff09;通用网关接口&#xff0c;通过浏览器中输入URL直接映射到一个 服务器端的脚本程序执行&#xff0c;这个脚本可以查询数据库并返回结果给浏览器端。这种将用户请求使用程…

今年暑期渗透测试面试经验分享

吉祥知识星球http://mp.weixin.qq.com/s?__bizMzkwNjY1Mzc0Nw&mid2247485367&idx1&sn837891059c360ad60db7e9ac980a3321&chksmc0e47eebf793f7fdb8fcd7eed8ce29160cf79ba303b59858ba3a6660c6dac536774afb2a6330#rd 《网安面试指南》http://mp.weixin.qq.com/s?…

arthas源码刨析:启动 (1)

文章目录 arthas-bootBootstrap Created with Raphal 2.3.0 开始 检查监听端口 jps 列表java应用 下载 lib 依赖 功能移交给 arthas-core 结束 arthas-boot 该module 的代码只有3个类&#xff1a; Bootstrap 启动类 Bootstrap &#xff0c;开头的注解就是 alibaba 的 cli 中…

蛇优化算法(Snake Optimization, SO)优化RBF神经网络的扩散速度实现多数入多输出数据预测,可以更改数据集(MATLAB代码)

一、蛇优化算法优化RBF神经网络的扩散速度原理介绍 RBF神经网络的扩散速度通常与它的径向基函数的宽度参数&#xff08;σ&#xff09;有关&#xff0c;这个参数控制了函数的径向作用范围。在高斯核函数中&#xff0c;当σ值较大时&#xff0c;函数的扩散速度较快&#xff0c;…