C++之多态(上篇)(最全总结)

news2024/11/25 20:25:19

本篇目录

  • 前言
  • 1.多态的概念
    • 1.1概念
  • 2.多态的定义及实现
    • 2.1 虚函数
    • 2.2 虚函数的重写
    • 2.3 多态的构成条件
  • 3.一道经典题目
  • 4.多态的原理
    • 4.1虚函数表

前言

需要声明的,这两篇文章(C++之多态(上下篇))的运行环境都是在vs2013下的x86程序中,涉及的指针都是4bytes。如果要在其他平台下,部分代码需要改动。比如:如果是x64程序,则需要考虑指针是8bytes问题等等。

1.多态的概念

1.1概念

多态的概念:通俗来说,就是多种形态,具体点就是去完成某个行为,当不同的对象去完成时会产生出不同的状态。

举个例子:比如买票这个行为,当普通人买票时,是全价买票;学生买票时,是半价买票;军人买票时,是优先买票。

2.多态的定义及实现

2.1 虚函数

虚函数:即被virtual修饰的类成员函数称为虚函数。
ps: 普通函数不能用virtual修饰,会报错。

class Person
{
public:
	virtual void BuyTicket()
	{
		cout << "买票-全价" << endl;
	}
};

2.2 虚函数的重写

虚函数的重写(覆盖):派生类中有一个跟基类完全相同的虚函数。(需要满足三同:即派生类虚函数与基类虚函数的返回值类型,函数名字,参数列表完全相同不符合重写就是隐藏关系),称派生类的虚函数重写了基类的虚函数。

class Person
{
public:
	virtual void BuyTicket()
	{
		cout << "买票-全价" << endl;
	}
};

class Student :public Person
{
public:
	//虚函数重写/覆盖条件:虚函数+三同(函数名、参数、返回值)
	//不符合重写,就是隐藏关系
	virtual void BuyTicket()
	{
		cout << "买票-半价" << endl;
	}
};

虚函数重写的两个例外:

2.3 多态的构成条件

多态是在不同继承关系的类对象,去调用同一个函数,产生了不同的行为。比如Student继承了Person。Person对象买票全价,Student对象买票半价。
在继承中构成多态还要满足两个条件:
1.必须通过基类的指针或者引用去调用虚函数
2.被调用的函数必须是虚函数,且派生类必须对基类的虚函数进行重写

class Person
{
public:
	virtual void BuyTicket()
	{
		cout << "买票-全价" << endl;
	}
};

class Student :public Person
{
public:
	//虚函数重写/覆盖条件:虚函数+三同(函数名、参数、返回值)
	//不符合重写,就是隐藏关系
	//**特例1:子类虚函数不加virtual,依旧构成重写(实际最好加上)**
	//void BuyTicket()
	virtual void BuyTicket()
	{
		cout << "买票-半价" << endl;
	}
};

class Soldier :public Person
{
public:
	virtual void BuyTicket()
	{
		cout << "优先买票" << endl;
	}
};

//多态的两个条件
//1、虚函数重写
//2、父类指针或者引用去调用虚函数

void Func(Person& p)
{
	p.BuyTicket();
}

int main()
{
	Person ps;
	Student st;
	Soldier sd;
	Func(ps);
	Func(st);
	Func(sd);
	return 0;
}

特例1:子类虚函数不加virtual,依旧构成重写(实际最好加上)
特例2:重写的协变,返回值可以不同,要求必须是父子关系的指针或者引用,这里的父子关系不一定是此父类和子类,其他的父子关系都可以

class Person
{
public:
	virtual Person* BuyTicket()
	{
		cout << "买票-全价" << endl;
		return this;
	}
};

class Student :public Person
{
public:
	//虚函数重写/覆盖条件:虚函数+三同(函数名、参数、返回值)
	//不符合重写,就是隐藏关系
	virtual Student* BuyTicket()
	{
		cout << "买票-半价" << endl;
		return this;
	}
};
class A
{};
class B :public A
{};

class Person
{
public:
	virtual A* BuyTicket()
	{
		cout << "买票-全价" << endl;
		return nullptr;
	}
};

class Student :public Person
{
public:
	//虚函数重写/覆盖条件:虚函数+三同(函数名、参数、返回值)
	//不符合重写,就是隐藏关系
	virtual B* BuyTicket()
	{
		cout << "买票-半价" << endl;
		return nullptr;
	}
};

3.一道经典题目

问:以下程序的输出结果是什么?

class A
{
public:
	virtual void func(int val = 1)
	{
		std::cout << "A->" << val << std::endl;
	}

	virtual void test()
	{
		func();
	}
};

class B :public A
{
public:
	void func(int val = 0)
	{
		std::cout << "B->" << val << std::endl;
	}
};

int main(int argc,char* argv[])
{
	B* p = new B;
	p->test();
	return 0;
}

在这里插入图片描述

解析:p是一个指向B对象的指针,p通过指针的方式去访问B继承A的成员函数test,成员函数放在公共代码区,
所以p是一个B的指针,当它调用对象A中的成员函数test时,test的this指针是指向A对象的,所以这里将B
传给A*会发生切片或者切割,test函数里面的func()函数,this->func();这里的this是p的同级拷贝,这里的
this指向的是B,通过切片后看到的是A,这里满足多态的两个条件,所以这里是多态,指向谁就调用谁,这里指向的
是B,则调用B对象的func()函数,我们知道子类的虚函数是可以不加virtual的,虚函数重写是接口继承,即前面那部分与父类
保持一致,所以这里的val是父类的缺省值1而不是子类的缺省值0,重写实现,实现部分是调用子类自己的,所以答案是B->1。

4.多态的原理

4.1虚函数表

这里有一道笔试题,计算sizeof(Base)是多少?

class Base
{
public:
	virtual void Func1()
	{
		cout << "Func1()" << endl;
	}
private:
	int _b = 1;
};

int main()
{
	cout << sizeof(Base) << endl;
	return 0;
}

通过观察测试我们发现答案是8bytes,除了_b成员,还多了一个_vfptr指针放在对象的前面,(注意平台可能放在对象的最后面,跟平台有关),对象的这个指针我们叫做虚函数表指针,v表示virtual,f表示function;一个含有虚函数成员的类都至少有一个虚函数表指针,因为虚函数的地址要被放到虚函数表中,虚函数表简称虚表,那么派生类中这个表放了些什么呢,我们接着往下分析。

在这里插入图片描述
在这里插入图片描述

在这里插入图片描述

总结:
多态的本质原理,符合多态的两个条件,那么调用时,会到指向对象的虚表中找到对应的虚函数地址,进行调用。

在这里插入图片描述
下篇接这里继续,大家可以休息一下哦。

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

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

相关文章

Python数据可视化操作原理

后端是处理数据提取用户想要的数据。简单常用的是Python&#xff0c;相对于java&#xff0c;c, c&#xff0c;Python简直对初学者太友好&#xff0c;提供丰富多彩的API接口&#xff0c;比如常见的降维聚类算法&#xff1a;PCA, t-SNE, MDS, k-means等。如果用c实现过PCA算法有几…

MinGW下载和安装详细步骤 及 环境配置

一、下载 点击 这里 进入官网下载最新版本的MinGW。&#xff08;这里下载的是Windows32位&#xff0c;但MinGW的所有软件都将在64位Windows平台上执行&#xff0c;所以32位和64位都是一样的。&#xff09; 二、安装 1. 下载完成后&#xff0c;双击程序进行安装&#xff1b; …

[附源码]计算机毕业设计Python的连锁药店销售管理系统(程序+源码+LW文档)

该项目含有源码、文档、程序、数据库、配套开发软件、软件安装教程 项目运行 环境配置&#xff1a; Pychram社区版 python3.7.7 Mysql5.7 HBuilderXlist pipNavicat11Djangonodejs。 项目技术&#xff1a; django python Vue 等等组成&#xff0c;B/S模式 pychram管理等…

【数据结构】基础: 常见排序算法

【数据结构】基础&#xff1a;常见排序算法 摘要&#xff1a;本文将从排序的概念及其附属概念出发&#xff0c;再对排序算法进行分类&#xff0c;并对其思想与实现进行说明&#xff0c;最后对各个算法进行总结。 文章目录【数据结构】基础&#xff1a;常见排序算法一. 排序的概…

Debian11.5和Ubuntu22.04安装fcitx5中文输入法(五笔拼音)

1 说明 Debian和Ubuntu的DE(桌面环境)均为GNOME。 2 安装fcitx5和fcitx5-chinese-addons&#xff08;Debian和Ubuntu通用&#xff09; sudo apt install fcitx5 fcitx5-chinese-addons 3 Debian11.5设置fcitx5 Debian安装完fcitx5后&#xff0c;最好先重启&#xff01;&am…

第十四届蓝桥杯集训——for——判断质数/素数

第十四届蓝桥杯集训——for——判断质数/素数 目录 第十四届蓝桥杯集训——for——判断质数/素数 1、什么是质数/素数&#xff1f; 2、整除代码的表达方式&#xff1f; 3、判断素数代码 4、素数的价值 5、素数分布规律 6、素数密度公式 判断素数是我们在做算法题目中出现…

零基础学习编程,哪一门语言比较适合入门

初学编程的人&#xff0c;几乎都会问这个问题吧&#xff0c;编程语言近年来备受关注的Java和Python&#xff0c;到底选择什么作为入门好呢&#xff1f;下面乐字节来为大家讲述下&#xff1a; 首先得明白你学习编程的目的是什么&#xff0c;如果是是为了学会编程后跳入互联网企…

[附源码]计算机毕业设计Node.js宠物店网站(程序+LW)

项目运行 环境配置&#xff1a; Node.js最新版 Vscode Mysql5.7 HBuilderXNavicat11Vue。 项目技术&#xff1a; Express框架 Node.js Vue 等等组成&#xff0c;B/S模式 Vscode管理前后端分离等等。 环境需要 1.运行环境&#xff1a;最好是Nodejs最新版&#xff0c;我…

可视化报表软件-FineReport绝对层次坐标

1.概念说明 在进行报表设计时&#xff0c;单元格尚未扩展&#xff0c;但是其它单元格的计算表达式可能需要此单元格扩展后某个数据的精确位置&#xff0c;这时就需要使用绝对层次坐标精确表达该数据的位置。 层次坐标概念图如下图所示&#xff1a; 注&#xff1a;反向获取第 …

热门技术中的应用:云计算中的网络-第25讲-软件定义网络:共享基础设施的小区物业管理办法

上一节我们说到,使用原生的VLAN和Linux网桥的方式来进行云平台的管理,但是这样在灵活性、隔离性方面都显得不足,而且整个网络缺少统一的视图、统一的管理。 可以这样比喻,云计算就像大家一起住公寓,要共享小区里面的基础设施,其中网络就相当于小区里面的电梯、楼道、路、…

圣诞节送给女友的圣诞树----专属于我们的浪漫

前言&#xff1a; 美酒一杯让人醉&#xff0c;温馨陪伴浪漫随;雪花片片惹人爱&#xff0c;烦恼忧伤全不见;字里行间藏真情&#xff0c;文短情深送心愿:圣诞佳节快来到&#xff0c;祝大家永远开心幸福! Hello大家好&#xff0c;我是Dream。 圣诞节马上到了&#xff0c;一些朋友问…

[附源码]计算机毕业设计Python的实验填报管理系统(程序+源码+LW文档)

该项目含有源码、文档、程序、数据库、配套开发软件、软件安装教程 项目运行 环境配置&#xff1a; Pychram社区版 python3.7.7 Mysql5.7 HBuilderXlist pipNavicat11Djangonodejs。 项目技术&#xff1a; django python Vue 等等组成&#xff0c;B/S模式 pychram管理等…

【Mysql】Sharding-JDBC实现读写分离、分库分表的原理分析

【Mysql】SpringBoot整合Sharding-JDBC实现读写分离、分库分表&#xff08;一&#xff09;介绍Sharding-JDBC&#xff08;1&#xff09;什么是Sharding-JDBC&#xff08;2&#xff09;Sharding-JDBC的源码是如何实现对JDBC增强的&#xff08;3&#xff09;Sharding-JDBC的分片原…

力扣804.唯一摩尔斯密码词(java语言 散列表法)

题目描述&#xff1a; 国际摩尔斯密码定义一种标准编码方式&#xff0c;将每个字母对应于一个由一系列点和短线组成的字符串&#xff0c; 比如: ‘a’ 对应 “.-” &#xff0c; ‘b’ 对应 “-…” &#xff0c; ‘c’ 对应 “-.-.” &#xff0c;以此类推。 为了方便&#…

全球石油行业资源储量丰富 但分布不均 供需量逐渐恢复增长

1、全球石油资源储量情况 &#xff08;1&#xff09;全球石油资源丰富&#xff0c;但分布不均匀 根据观研报告网发布的《2022年中国石油行业分析报告-行业全景评估与投资规划分析》显示&#xff0c;全球石油资源总量丰富&#xff0c;勘探开发潜力较大。根据数据显示&#xff0…

旺季大促白热化,如何做好谷歌广告投放

眼下已经到了旺季大促的白热化阶段了&#xff0c;那么在这个关键的时期&#xff0c;跨境卖家应该如何利用好广告投放呢&#xff1f; 想必大家都知道&#xff0c;谷歌是跨境卖家们最最常用的广告投放渠道&#xff0c;今天&#xff0c;华sir重点向大家介绍一下谷歌的智能购物广告…

[附源码]Python计算机毕业设计Django校园二手交易平台

项目运行 环境配置&#xff1a; Pychram社区版 python3.7.7 Mysql5.7 HBuilderXlist pipNavicat11Djangonodejs。 项目技术&#xff1a; django python Vue 等等组成&#xff0c;B/S模式 pychram管理等等。 环境需要 1.运行环境&#xff1a;最好是python3.7.7&#xff0c;…

B5G毫米波通信无线接入网络的架构设计

【摘 要】在B5G和6G时代,基于高频毫米波通信的各类先进技术将成为极大提升网络容量和促进新业务部署的关键使能因素。结合过去蜂窝无线接入网络架构的演进特点,设计出一种新型的无线接入网络架构,使得它能充分地适配高频毫米波通信的各种特点,并能实现对网络各层资源的更高…

(附源码)springboot厨到家服务平台 毕业设计 063133

springboot厨到家服务系统 摘 要 在社会快速发展的影响下&#xff0c;餐饮迅速发展&#xff0c;大大增加了餐饮服务信息管理的数量、多样性、质量等等的要求&#xff0c;使餐饮的管理和运营比过去十年更加困难。依照这一现实为基础&#xff0c;设计一个快捷而又方便的厨到家服…

Java项目:SSM问卷调查系统

作者主页&#xff1a;源码空间站2022 简介&#xff1a;Java领域优质创作者、Java项目、学习资料、技术互助 文末获取源码 项目介绍 这是一个基于SpringMVCSpringMyBatis的SSM问卷调查系统。 管理端权限 管理员信息CURD 制作调查问卷 发布调查问卷 统计调查结果 统计报表展示 用…