C++入 门——“多态”

news2024/9/19 22:03:02

一、多态

        多态是面向对象的一个重要特性,它允许程序在运行时通过传入不同对象而呈现出不同的运行结果,比如同样的采访,询问老师的年龄和学生的年龄最后得到的结果是不一样的,这就呈现出一种多态。

        多态分为两种:静态多态(编译时期就确定)和运行时多态(运行时期就确定)。编译时的多态比如有:重载,模版等,本文介绍运行时多态。

二、多态的实现条件

多态的实现有两个基本条件

        a.必须是基类的引用或者指针来调用相应的函数。

        b.被调用的函数是虚函数

        1.重写(覆盖)

        派生类中有和基类一样的虚函数,那么这两个函数构成重写。重写的实现条件是函数名、函数参数、返回值(协变除外)相同。        

        2.虚函数 

        被关键字“virtual”修饰的函数叫做虚函数,例如 virtual void f(int a)。使用virtual的前提是类的成员函数。值得注意的是,派生类的虚函数的virtual可以不用显式的写出来,但是基类必须写。

以下是一个多态的例程:

#include <iostream>

using namespace std;


class kids
{
public:

	virtual void getage()
	{
		cout << "kids is " << 16 << endl;
	}


};


class student : public kids
{
public:

	virtual void getage()
	{
		cout << "student is " << 20 << endl;
	}



};


int main()
{
	kids* kid = new kids;

	kids* stu = new student;

	kid->getage();
	stu->getage();


	delete kid;
	delete stu;
	return 0;
}

   它的运行结果是:

        在main函数中,先定义了一个基类的指针让它指向派生类的对象,这样构成了第一个条件,调用的函数是一个虚函数,然后满足了第二个条件,这样就形成了多态。

        为什么是基类的指针或者引用呢?

        只有基类的指针或者引用才能既指向基类对象,又指向派生类的对象。

虚函数有个很重要的内容,就是当子类和派生类的析构函数被定义的时候,需要将析构函数写成虚函数以构成重写,倘若不这样写,则会发生内存泄漏的问题:

#include <iostream>

using namespace std;



class kids
{
public:

	~kids()
	{
		cout << " ~kids() " << endl;
	}

};


class student : public kids
{
public:

	~student()
	{
		cout << " ~student() " << endl;
	}
};


int main()
{
	kids* kid = new kids;

	kids* stu = new student;



	delete kid;
	delete stu;
	return 0;
}

运行结果:

        可以看到,“stu”对象的析构函数没有被调用,原因是kids* stu = new student;代码发生了切片,导致只释放了“stu”的基类的资源。那么我们需要把析构函数写成虚函数并构成重写。为什么能构成重写呢?编译器会在编译时将析构函数的名字做了一个特殊处理成“destructor”的名称,于是乎加上virtual自然也能构成重写。最后在delete的时候就会发生多态行为,从而正确释放资源。

三、多态中需要注意的问题

        当基类和派生类的虚函数构成重写时,如果函数有缺省值,无论调用的是哪一个虚函数,都会使用基类的缺省值:

#include <iostream>

using namespace std;


class kids
{
public:

	virtual void getage(int age = 16)
	{
		cout << "kids is " << age << endl;
	}


};


class student : public kids
{
public:

	virtual void getage(int age = 20)
	{
		cout << "student is " << age << endl;
	}



};


int main()
{
	kids* kid = new kids;

	kids* stu = new student;

	kid->getage();
	stu->getage();


	delete kid;
	delete stu;
	return 0;
}

        理解上可以认为重写的是实现函数的方式。即基类的函数名和参数加上派生类的实现方法。

四、抽象类

        在虚函数的后边加上 “=0”,那么这个函数被称为纯虚函数,纯虚函数所在的那个类被称作抽象类,然而抽象类是不被允许创建对象的,当某一个类继承了这个抽象类,那么这个派生类也是抽象类,只有当我们在派生类中重写了这个纯虚函数,才能够正常的创建对象。但是可以用抽象类定义指针或者引用。

五、多态实现的大致原理

        在类中,如一个类有虚函数,那么它就会储存一张虚函数表,这张表储存了虚函数的地址,派生类会继承基类的虚函数表指针,但是和基类的不是同一个,当派生类重写了虚函数的时候,重写的虚函数就会覆盖掉派生类中基类继承下来虚函数的内容,这就是重写也叫覆盖的原因。

        在基类指针或者引用指向派生类时,调用派生类重写的虚函数的时候,程序就会去指针指向的对应类的虚函数表寻找对应的虚函数,然后去执行。指针指向基类,就去基类的虚函数表寻找,指针指向派生类,就去派生类的虚函数表寻找。

        不同的类的对象有不同的虚表,但是相同类的对象共享同一张虚表。

        派生类的虚表主要分为三部分内容:父类的虚函数地址加重写的虚函数地址加自己的虚函数地址。

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

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

相关文章

鸿蒙OpenHarmony【轻量系统芯片移植】内核移植

移植芯片架构 芯片架构的移植是内核移植的基础&#xff0c;在OpenHarmony中芯片架构移植是可选过程&#xff0c;如果当前OpenHarmony已经支持对应芯片架构则不需要移植操作&#xff0c;在“liteos_m/arch”目录下可看到当前已经支持的架构&#xff0c;如表1&#xff1a; 表1 …

2024年全国大学生软件测试大赛赛项安排(一)

✨博客主页&#xff1a; https://blog.csdn.net/m0_63815035?typeblog &#x1f497;《博客内容》&#xff1a;.NET、Java.测试开发、Python、Android、Go、Node、Android前端小程序等相关领域知识 &#x1f4e2;博客专栏&#xff1a; https://blog.csdn.net/m0_63815035/cat…

怎么选择靠谱AI论文生成工具?看完我的试用都会明白!

2024年上半年开始AI论文写作工具开始火了&#xff0c;层出不穷&#xff01;作为一个经常需要写论文的懒人&#xff0c;我非常好奇这些AI工具的实际效果到底怎么样&#xff1f;为了测试不同工具的实力&#xff0c;我对他们都进行了试用&#xff0c;发现了一些意想不到的结果....…

【楚怡杯】职业院校技能大赛 “云计算应用” 赛项样题一

某企业根据自身业务需求&#xff0c;实施数字化转型&#xff0c;规划和建设数字化平台&#xff0c;平台聚焦“DevOps开发运维一体化”和“数据驱动产品开发”&#xff0c;拟采用开源OpenStack搭建企业内部私有云平台&#xff0c;开源Kubernetes搭建云原生服务平台&#xff0c;选…

【F172】基于Springboot+vue实现的智能菜谱系统

作者主页&#xff1a;Java码库 主营内容&#xff1a;SpringBoot、Vue、SSM、HLMT、Jsp、PHP、Nodejs、Python、爬虫、数据可视化、小程序、安卓app等设计与开发。 收藏点赞不迷路 关注作者有好处 文末获取源码 项目描述 近些年&#xff0c;随着中国经济发展&#xff0c;人民的…

消防装备仓库管理系统|实现消防装备全流程跟踪

智慧消防装备仓库管理系统&#xff08;智物资DW-S302&#xff09;是一套成熟系统&#xff0c;依托互3D技术、云计算、大数据、RFID技术、数据库技术、AI、视频分析技术对RFID智能仓库进行统一管理、分析的信息化、智能化、规范化的系统。 1、支持实时物资仓库货位二维和三维孪生…

第七篇——数学应用:华罗庚化繁为简的神来之笔

目录 一、背景介绍二、思路&方案三、过程1.思维导图2.文章中经典的句子理解3.学习之后对于投资市场的理解4.通过这篇文章结合我知道的东西我能想到什么&#xff1f; 四、总结五、升华 一、背景介绍 数学的意义&#xff0c;以及它对于生活的指导边界&#xff0c;是那么的重…

Oracle CloudWorld 2024:多云时代的AI与数据库融合革命

在今年的 Oracle CloudWorld 大会上&#xff0c;甲骨文董事会主席兼首席技术官Larry Ellison 深入探讨了AI、云计算与数据库融合的未来。 在这一技术盛宴中&#xff0c;Ellison的演讲不仅展现了云计算的新趋势&#xff0c;还为企业数字化转型提供了前瞻性的技术路线。 我们来回…

kettle 数据库迁移 使用分页原理实现 数据库mysql

使用 kettle 9.0 先修改配置文件: C:\Users\xx\.kettle 新增如下配置,解决mysql 空字符串 自动转 null bug KETTLE_EMPTY_STRING_DIFFERS_FROM_NULLY git地址: GitHub - 2292011451/kettle_tool 第一步: 先把要迁移的表进行读取,循环查询每个表的最大数量以及页数,追加到…

(一)模式识别——基于SVM的道路分割实验(附资源)

写在前面&#xff1a;本报告所有代码公开在附带资源中&#xff0c;无法下载代码资源的伙伴私信留下邮箱&#xff0c;小编24小时内回复 一、实验目的 1、实验目标 学习掌握SVM&#xff08;Support Vector Machine&#xff09;算法思想&#xff0c;利用MATLAB的特定工具箱和库函…

MFC工控项目实例之十四模拟量信号名称从文件读写

承接专栏《MFC工控项目实例之十三从文件读写板卡信号名称》 在BoardTest.cpp文件中添加代码 int m_CountGetCurSel_AD[16];//索引号 UINT m_CountComboID_AD[16]//控件ID号{IDC_COMBO33,IDC_COMBO34,IDC_COMBO35,IDC_COMBO36,IDC_COMBO37,IDC_COMBO38,IDC_COMBO39,IDC_COMBO40…

语言模型微调:提升语言Agent性能的新方向

人工智能咨询培训老师叶梓 转载标明出处 大多数语言Agent依赖于少量样本提示技术&#xff08;few-shot prompting&#xff09;和现成的语言模型。这些模型在作为Agent使用时&#xff0c;如生成动作或自我评估&#xff0c;通常表现不佳&#xff0c;且鲁棒性差。 论文《FIREACT…

2024外滩大会:远的更近 旧的更新

文 | 大力财经 导语&#xff1a;2024 外滩大会圆满落幕&#xff01;未来更近了&#xff0c;旧的更创新了。全球 500 多位精英齐聚&#xff0c;50 余家企业 “招才”。在这里&#xff0c;我们不仅看到未来商业形态&#xff0c;更望见未来的影子。 为期三天的2024外滩大会圆满落幕…

flv复合流

一、什么是flv flv流媒体协议是Adobe公司推出的一种流媒体协议。其特点就是封装后的音视频数据量很小&#xff0c;并且协议规范相对简单&#xff0c;所以FLV流媒体协议适合网络传输&#xff0c;但是他是一个私有协议&#xff0c;所支持的网络传输比较有限&#xff1a;如RTMP、H…

Mysql异常断电InnoDB损坏处理

一、mysql启动报错信息收集 1、截图 [ERROR] InnoDB: Database page corruption on disk or a failed file read of page [page id: space0, page number203]. You may have to recover from a backup. Jun 27 13:30:06 localhost mysqld: 2024-06-27T13:30:06.14747208:00 0 …

意气实体过程函数论3

意气实体过程函数论3 和悦空间 y i y_i yi​才气的意气实体过程逻辑定义哥德尔数数理逻辑简称逻辑&#xff1b;明明德数符号琴语言数据结构王阳明群表示&#xff0c;被称为才气群表示论&#xff1b; 从劳动力关系向量到生产力配分函数算法为己之学模拟器接口函数声明内核与插件…

【JAVA入门】Day42 - 转换流

【JAVA入门】Day42 - 转换流 文章目录 【JAVA入门】Day42 - 转换流 转换流是字符流和字节流之间的桥梁。 转换流中的输入流叫做 InputStreamReader&#xff0c;它可以把字节流转换为字符流。 转换流的输出流叫做 OutputStreamWriter&#xff0c;它可以把字符流…

JAVA并发编程ReentrantLock核心原理剖析

JAVA并发编程系列以及陆续出了5篇&#xff0c;第六篇的主角ReentrantLock该出场了。之前《一文看懂全部锁机制》谈到可重入锁、《JAVA并发编程AQS原理剖析》谈到了JUC灵魂AQS&#xff0c;那么AQS的思想优秀实践者ReentrantLock是怎么实现AQS的呢&#xff1f; 1、ReentrantLock是…

Unity笔记:ScrollRect代码阅读

大体流程 Unity Docs - UGUI | Class ScrollRect 总的说 自身不负责Rebuild&#xff0c;设置脏之后交由LayoutRebuilder注册到CanvasUpdateRegistry里待rebuild的集合在固定时机统一Rebuild。自身只在Prelayout和Postlayout做一下数据准备和数据更新 自身的ICanvasElement.…