C++之多态使用小结

news2025/1/9 16:54:17

1、多态定义

1.1 多态概念     

        C++多态性(Polymorphism)是面向对象编程(OOP)的一个重要特性之一,它允许我们使用统一的接口来处理不同类型的对象。多态性使得程序更加灵活、可扩展并且易于维护。

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

1.2 多态的构成条件

       多态是在不同继承关系的类对象,去调用同一函数,产生了不同的行为。对于同一行为买票(BuyTicket)比如,由于Student继承了Person。Person对象买票全价,Student对象买票半价。
  在继承中要构成多态还有两个条件:

  • 必须通过基类的指针或者引用调用虚函数。
  • 被调用的函数必须是虚函数,且派生类必须对基类的虚函数进行重写

2、多态的使用

2.1 虚函数

      构成多态的条件中提到了虚函数,所谓的虚函数,就是被virtual修饰的类成员函数。具体如下,函数BuyTicket()即为虚函数。其中只要在申明时添加virtual关键字,在具体实现虚函数方法时不需要添加。

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

2.2 虚函数的重写

      虚函数的重写(覆盖):派生类中有一个跟基类完全相同的虚函数(即派生类虚函数与基类虚函数的返回值类型、函数名字、参数列表完全相同),称子类的虚函数重写了基类的虚函数。我们看如下例子派生类Student对虚函数BuyTicket() 进行了重写。

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

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

3、多态练习

3.1 派生构造函数使用

      派生函数在使用基类中成员变量的同时,再添加成员变量,这种情况用法可参考如下案例。基类Person中包括成员变量:name、age、gender。派生类Student又添加成员变量:id、score。那么,在构造函数中,使用如下命令,其中name、age、gender为继承People,id、score为赋值。

Student::Student(string name, int age, string gender, string id, int score) : People(name, age, gender), id(id), score(score)
{}
#include <iostream>
#include<string>
using namespace std;
class People
{
public:
	People();
	People(string name, int age, string gender);
	~People();
	void PrintInfo();

public:
	string name;//姓名
	int age;//年龄
	string gender;//性别

};

People::People(string name, int age, string gender)
{
	this->name = name;
	this->age = age;
	this->gender = gender;
}
void People::PrintInfo()
{
	cout << "name :" << this->name << endl; 
	cout << "age :" << this->age << endl;
	cout << "gender :" << this->gender << endl;
}

People::People()
{
}

People::~People()
{
}

class Student :public People
{
public:
	Student();
	Student(string name, int age, string gender, string id, int score);
	~Student();
	void PrintInfo();

public:
	string id;
	int score;

};
Student::Student(string name, int age, string gender, string id, int score) : People(name, age, gender), id(id), score(score)
{}

void Student::PrintInfo()
{
	cout << "name :" << this->name << endl;
	cout << "age :" << this->age << endl;
	cout << "gender :" << this->gender << endl;
	cout << "id :" << this->id << endl;
	cout << "score :" << this->score << endl;
}

Student::Student()
{
}

Student::~Student()
{
}

3.2 案例一:

      下面介绍对这句话的理解:基类的指针引用或者调用调用虚函数

其可以这样理解:

(1)如果指针指向基类地址,那么只能访问基类的虚函数

(2)如果指针指向派生类地址,那么只能访问派生类中与基类对应的函数

#include <iostream>
#include<string>
using namespace std;
class Person
{
public:
	virtual void BuyTicket()
	{
		cout << "买票-全价" << endl;
	}
};
class Student : public Person
{
public:
	virtual void BuyTicket()
	{
		cout << "买票-半价" << endl;
	}
};
void Func(Person& p)
{
	p.BuyTicket();
}
int main()
{
	Person ps;
	Student st;
	Func(ps);
	Func(st);
	system("pause");
	return 0;
}

       上述代码构成了多态吗?首先是虚函数BuyTicket(),其次完成了重写。结果如下,原因是ps对应的是基类指针,因此只能访问基类的BuyTicket()函数;而st对应的是派生类指针,因此访问派生类的BuyTicket()函数。

3.3 案例二:

#include <iostream>
#include<string>
using namespace std;
class A
{
public:
	virtual void func(int val)
	{
		cout << "A->" << val << std::endl;
	}
};

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

int main()
{
	A* p = new B;
	p->func(1);
	system("pause");
	return 0;
}

       上述的代码调用构成多态吗?首先是虚函数func(),其次完成了重写上述代码中,p指针是指向派生类B地址,因此,只能访问B对应的func()函数,是B->1

3.4 案例三:

#include <iostream>
#include<string>
using namespace std;
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)
	{
		cout << "B->" << val << std::endl;
	}
};

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

在 B 类的 func 函数中,有一个默认参数值为 0,这意味着当 test 函数被调用时,它会使用这个默认值。然而,test 函数中有一个显式的调用 func(),这意味着它会调用 B 类中的 func 实现,并传递参数 1

参考博客:

【1】【C++】多态(举例+详解,超级详细)_c++多态-CSDN博客

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

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

相关文章

期末成绩发布智能助手

期末考试的结束标志着教师们迎来了成绩处理的忙碌时期。传统的成绩单分发方式不仅耗时耗力&#xff0c;而且容易出错。幸运的是&#xff0c;易查分小程序的出现&#xff0c;为这一过程提供了一个简便而高效的解决方案。 易查分小程序是专为教师和家长设计的智能工具&#xff0…

安卓笔记1-Retrofit2请求自定义接口

1、整体功能概述 安卓项目中使用Retrofit2实现和自定义接口的网络交互&#xff0c;通过Postman模拟服务端&#xff0c;创建自定义接口。 作用 前后端开发进度对不齐时&#xff0c;客户端可利用本功能模拟测试数据。备忘。 缺点 retrofit模拟接口需要配置响应数据类&#xff…

美无定论,娜扎亦菲各自绽放你更爱哪一款?

娜扎亦菲各自绽放你更爱哪一款&#xff1f; 哎呀&#xff0c;这个问题可真是让我头疼呢&#xff0c; 就像让我在两个糖果店里选择最甜的那一颗一样难&#xff01; 古力娜扎和刘亦菲&#xff0c;两位都是娱乐圈里璀璨的明珠&#xff0c; 美得各有千秋&#xff0c;让人怎么舍得…

2024年上半年信息系统项目管理师——综合知识真题题目及答案(第1批次)(3)

2024年上半年信息系统项目管理师 ——综合知识真题题目及答案&#xff08;第1批次&#xff09;&#xff08;3&#xff09; 第41题&#xff1a;在应用集成中&#xff0c;有多个组件帮助协调连接各种应用。其中&#xff08;&#xff09;利用特定的数据结构&#xff0c;帮助开发人…

企业网络实验dhcp-snooping、ip source check,防非法dhcp服务器、自动获取ip(虚拟机充当DHCP服务器)、禁手动修改IP

文章目录 需求相关配置互通性配置配置vmware虚拟机&#xff08;dhcp&#xff09;分配IP服务配置dhcp relay&#xff08;dhcp中继&#xff09;配置dhcp-snooping&#xff08;防非法dhcp服务器&#xff09;配置ip source check&#xff08;禁手动修改IP&#xff09; DHCP中继&…

四. TensorRT模型部署优化-pruning(sparse-tensor-core)

目录 前言0. 简述1. 自动驾驶中需要关注的电力消耗2. Ampere架构中的3rd Generation Tensor core3. Sparse tensor core做矩阵乘法总结参考 前言 自动驾驶之心推出的 《CUDA与TensorRT部署实战课程》&#xff0c;链接。记录下个人学习笔记&#xff0c;仅供自己参考 本次课程我们…

【刷题汇总 -- 删除公共字符、两个链表的第一个公共结点、mari和shiny】

C日常刷题积累 今日刷题汇总 - day0121、删除公共字符1.1、题目1.2、思路1.3、程序实现 -- 蛮力法1.4、程序实现 -- 哈希 2、两个链表的第一个公共结点2.1、题目2.2、思路2.3、程序实现 -- 对齐比对法2.4、程序实现 -- 公共端点路程法 3、mari和shiny3.1、题目3.2、思路3.3、程…

Unity如何查找两个transform最近的公共parent

查找两个子对象最近的父对象 一、问题背景二、解决方案思路核心算法代码 三、总结 一、问题背景 最近看到个关于Unity的问题&#xff1a;在Hierarchy面板中的游戏对象&#xff0c;给定两个子物体transform对象&#xff0c;如何查找这两个transform最近的公共父级parent。感觉挺…

Java中常用线程安全的集合

文章目录 常用线程安全的集合CopyWriteArrayListCopyOnWriteArraySetHashTableConcurrentHashMapJDK1.7JDK1.8 常用线程安全的集合 在多线程环境中&#xff0c;数据的一致性和线程的安全性是至关重要的。传统的集合类&#xff0c;如ArrayList、HashMap和HashSet&#xff0c;在…

手撕Vue中的RouterLink和RouterView,深入理解其底层原理(一)

RouterLink和RouterView的作用 我们可以通过RouterLink绑定好指向的路径 点击就能够实现在RouterView中将页面显示出来 我们首先使用官方的vue-router展示一下效果 App.vue <template><div><router-link to"/">Home</router-link><ro…

Real User ID 和 Effective User ID 的区别

在 Unix 和 Linux 系统中&#xff0c;每个进程都有多个用户标识符&#xff08;UID&#xff09;&#xff0c;其中最重要的是“真实用户 ID”&#xff08;real UID&#xff09;和“有效用户 ID”&#xff08;effective UID&#xff09;。 它们的区别和用途如下&#xff1a; 真实…

STM32入门开发操作记录(一)——新建工程

目录 一、课程准备1. 课程资料2. 配件清单3. 根目录 二、环境搭建三、新建工程1. 载入器件支持包2. 添加模块3. ST配置4. 外观设置5. 主函数文件 一、课程准备 1. 课程资料 本记录操作流程参考自b站视频BV1th411z7snSTM32入门教程-2023版 细致讲解 中文字幕&#xff0c;课程资…

五. TensorRT API的基本使用-MNIST-model-build-infer

目录 前言0. 简述1. 案例运行2. 代码分析2.1 main函数2.2 build接口2.3 infer接口2.4 其他 总结参考 前言 自动驾驶之心推出的 《CUDA与TensorRT部署实战课程》&#xff0c;链接。记录下个人学习笔记&#xff0c;仅供自己参考 本次课程我们来学习课程第五章—TensorRT API 的基…

7.13实训日志

上午 学习网络安全的过程中&#xff0c;我们深入了解了网络的不同层面和技术&#xff0c;从表层网络到深网再到暗网&#xff0c;以及涉及的产业分类和技术工具。这些知识不仅帮助我们理解网络的复杂性&#xff0c;还揭示了如何应对和防范各种网络威胁。 首先&#xff0c;我们…

滞后序列分析案例详解

一个半小时 超出30分钟 日期&#xff1a;2024-07-13 19:14:33 回放 摘要 Python在行为分析中的应用 主要讲述了如何使用Python处理序列数据&#xff0c;以及如何结合定性分析和定量分析来全面分析课程内容。讲者提到了一种叫做分层法的分类方法&#xff0c;该方法使用了布鲁…

记录vite项目中Cornerstone的兼容问题(持续更新)

&#x1f50e; 在vite项目中打包提示错误 ESM integration proposal for Wasm" is not supported currently. ⛳️ 问题描述 Error: Could not load /home/xxx/xxx/node_modules/icr/polyseg-wasm/dist/ICRPolySeg.wasm (imported by node_modules/icr/polyseg-wasm/di…

【软件建模与设计】-02-UML图

目录 摘要 1、用例图&#xff08;use case diagram&#xff09; 2、类与对象 3、类图 3.1、四种关系 3.2、可见性 4、交互图 4.1、通信图 4.2、顺序图 5、状态机图 6、包图 7、并发通信图 8、部署图 9、UML扩展机制 9.1、构造型 9.2、标记值 9.3、约束 摘要 用…

log4j2的日志框架(详细,springboot和异步日志的实现)

目录 log4j2的介绍 Log4j2的性能 SpringBoot中的使用Log4j2 log4j2的进阶--异步日志 AsyncAppender方式 AsyncLogger方式 log4j2的介绍 Apache Log4j 2是对Log4j的升级版&#xff0c;参考了logback的一些优秀的设计&#xff0c;并且修复了一些问题&#xff0c;因此带 来…

韦东山嵌入式linux系列-驱动进化之路:总线设备驱动模型

1 驱动编写的 3 种方法 以 LED 驱动为例 1.1 传统写法 使用哪个引脚&#xff0c;怎么操作引脚&#xff0c;都写死在代码中。 最简单&#xff0c;不考虑扩展性&#xff0c;可以快速实现功能。 修改引脚时&#xff0c;需要重新编译。 应用程序调用open等函数最简单的方法是驱动…

ISO 45001:提升职业健康与安全管理水平的关键

在现代企业管理中&#xff0c;员工的职业健康与安全&#xff08;OH&S&#xff09;已经成为不可忽视的重要议题。ISO 45001作为国际标准化组织&#xff08;ISO&#xff09;制定的职业健康与安全管理体系标准&#xff0c;为企业提供了科学有效的管理规范和指南。实施这一标准…