c++ - 多态

news2024/9/21 4:28:14

文章目录

    • 一、多态的概念
    • 二、多态使用
    • 三、多态的原理


一、多态的概念

1、概念:
多态就是具有多种形态,可以理解为同一个行为不同对象去完成表现出不同的状态,如:
在这里插入图片描述

二、多态使用

1、构成多态的条件
(1)派生类要对基类虚函数进行重写。
(2)通过基类指针或引用调用虚函数。

2、虚函数
关键字:virtual,加在函数声明前面,并且该函数是非静态成员函数。
如:
在这里插入图片描述
3、函数重写
(1)条件:
派生类重写的函数返回值、函数名称、函数参数与基类相同。

(2)使用

class Person {
public:
//虚函数
	virtual void test01()
	{
		//...
	}
};
class Student : public Person {
public:
	//重写 virtual关键字在派生类中写不写都可
	virtual void test01()
	{
		//...
	}
};

(3)例外
协变:
派生类重写基类虚函数时,与基类虚函数返回值类型不同。即基类虚函数返回基类对象的指
针或者引用,派生类虚函数返回派生类对象的指针或者引用时,称为协变。

class Person {
public:
	virtual  Person& test01()
	{
		//...
	}
};
class Student : public Person {
public:
	//重写 返回值是继承关系
	virtual  Student& test01()
	{
		//...
	}
};

析构函数:
如果基类的析构函数为虚函数,此时派生类析构函数只要定义,无论是否加virtual关键字,
都与基类的析构函数构成重写,虽然基类与派生类析构函数名字不同。虽然函数名不相同,
看起来违背了重写的规则,其实不然,这里可以理解为编译器对析构函数的名称做了特殊处
理,编译后析构函数的名称统一处理成destructor。

如果出现以下情况就会出现子类没有析构

class Person {
public:
	 ~Person() { cout << "~Person()" << endl; }
};
class Student : public Person {
public:
	~Student() { cout << "~Student()" << endl; }
};

void test()
{
	//情况
	//不重写析构函数时
	Person* p = new Student;
	delete p;
}

在这里插入图片描述
如果重写之后调用调用子类的析构,子类的析构再去调用父类析构就不会出现以上情况了。

class Person {
public:
	virtual ~Person() { cout << "~Person()" << endl; }
};
class Student : public Person {
public:
	~Student() { cout << "~Student()" << endl; }
};

void test()
{
	Person* p = new Student;
	delete p;
}

在这里插入图片描述

(3)重载、重定义(隐藏)、重写的区别
重载:同一作用域下,函数名相同,参数(类型、个数、顺序)不同。
重定义:作用域不同(派生类域、基类域),函数名相同。
重写:作用域不同(派生类域、基类域),必需是虚函数,函数名相同、返回类型相同、参数相同。
(4)使用多态

class Person {
public:
	//虚函数
	virtual void test01() {
		cout << "Person" << endl;
	}
protected:
	int _a;
};

class Student : public Person {
public:
	virtual void test01() {
		cout << "Student" << endl;
	}
protected:
	int _b;
};

void Print(Person* pp)
{
	pp->test01();
}

void test()
{
	Person p;
	Student s;
	//基类对象,传给基类指针pp,pp还是基类 ->不构成多态,依然使用基类的函数
	Print(&p);

	//派生类对象,传给基类指针pp,pp指向的是派生类-> 构成多态,使用的是派生类重写的函数
	Print(&s);
}

4、抽象类
(1)纯虚函数
在虚函数声明后面加上 =0 就是纯虚函数了。

virtual void test01() = 0;

(2)
拥有纯虚函数的类叫做抽象类,抽象类不能被实例化,当派生类继承抽象类后,必须重写抽象类中的纯虚函数,不然该派生类依旧还是抽象类,不能被实例化。

//抽像类
class Person {
public:
	//纯虚函数
	virtual void test01() = 0;
};
class Student : public Person {
public:
	//重写纯虚函数
	virtual void test01()
	{
		cout << "virtual void test01()" << endl;
	}
};

三、多态的原理

1、虚函数表
一个类中存在虚函数是会生成一个指针,该指针指向的内容就是虚函数表。
在x86环境下:

//抽像类
class Person {
public:
	//虚函数
	virtual void test01() {};
protected:
	int _a;
};

void test()
{
	Person p;
	cout << sizeof(Person) << endl;
}

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
当派生类继承基类时也会产生一个虚函数指针,该指针指向的内容一部分是从父类继承下来的,一部分是重写的。
在这里插入图片描述
test01()使用了派生类的,test02()没有重写,还是使用基类的。

2、多态原理
在这里插入图片描述

满足多态以后的函数调用,不是在编译时确定的,是运行起来以后到对象的中取找的。不满足多态的函数调用时编译时确认好的(运行时确定)。

3、动态绑定和静态绑定

  1. 静态绑定又称为前期绑定(早绑定),在程序编译期间确定了程序的行为,也称为静态多态,
    比如:函数重载
  2. 动态绑定又称后期绑定(晚绑定),是在程序运行期间,根据具体拿到的类型确定程序的具体
    行为,调用具体的函数,也称为动态多态。

4、多继承与多态

class Person1{
public:
	//虚函数
	virtual void test01() {};

protected:
	int _a;
};

class Person2 {
public:
	//虚函数
	virtual void test02() {};

protected:
	int _b;
};

class Student : public Person1, public Person2 {
public:
	//重写Person1
	void test01()
	{}
	//重写Person2
	void test02() 
	{}
	void test03()
	{}
protected:
	int _b;
};

void test()
{
	Student s;
}

多继承时每个基类会生成相应的虚函数指针。
在这里插入图片描述

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

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

相关文章

从线性变换的视角理解矩阵范数与行列式

在线性代数这一数学分支中&#xff0c;矩阵作为描述线性变换的工具&#xff0c;扮演着至关重要的角色。矩阵的范数和行列式是两个核心概念&#xff0c;它们分别从不同的角度揭示了矩阵及其所代表的线性变换的性质。本文旨在从线性变换的视角出发&#xff0c;探讨矩阵范数与行列…

C#小结:未能找到类型或命名空间名“xxx”(是否缺少 using 指令或程序集引用?)

方案一&#xff1a;移除这些失效的引用&#xff0c;下载对应版本的dll&#xff0c;重新添加引用 方案二&#xff1a;项目右键属性-调整目标框架版本&#xff08;一般是降低版本&#xff09; 方案三&#xff1a;调整编译顺序&#xff1a; 项目A&#xff1a;引用1、引用2 &…

底软驱动 | Linux用户空间与内核空间通信(Netlink通信机制)

1&#xff0c;什么是Netlink通信机制 Netlink是linux提供的用于内核和用户态进程之间的通信方式。但是注意虽然Netlink主要用于用户空间和内核空间的通信&#xff0c;但是也能用于用户空间的两个进程通信。只是进程间通信有其他很多方式&#xff0c;一般不用Netlink。除非需要用…

【pytorch】手写数字识别

https://blog.csdn.net/qq_45588019/article/details/120935828 基本均参考该博客 《深度学习原理Pytorch实战》 初步处理 导包 import torch import numpy as np from matplotlib import pyplot as plt from torch.utils.data import DataLoader from torchvision import tr…

esp32 usb cdc串口读写

void setup() { Serial.begin(); // 在USB CDC On Boot使能&#xff08;Enabled&#xff09;情况下&#xff0c;这里是USBCDC Serial.setDebugOutput(true); } void loop() { if (Serial.available() > 0) { // 检查是否有可用的数据 String input Serial.readS…

大模型应用中什么是IFT(指令微调)?

大模型应用中什么是IFT&#xff08;指令微调&#xff09;&#xff1f; 背景 随着人工智能技术的发展&#xff0c;特别是自然语言处理&#xff08;NLP&#xff09;领域的进步&#xff0c;预训练语言模型&#xff08;如GPT-3、BERT&#xff09;已经展现出了强大的语言理解和生成…

少儿编程 2024年6月电子学会图形化编程等级考试Scratch二级真题解析(判断题)

2024年6月scratch编程等级考试二级真题 判断题&#xff08;共10题&#xff0c;每题2分&#xff0c;共20分&#xff09; 26、下列积木的运算结果为false 答案&#xff1a;错 考点分析&#xff1a;考查逻辑运算符的使用&#xff0c;60>50为true&#xff0c;取反为false&…

Java高频面试基础知识点整理3

干货分享&#xff0c;感谢您的阅读&#xff01;背景​​​​​​高频面试题基本总结回顾&#xff08;含笔试高频算法整理&#xff09; 最全文章见&#xff1a;Java高频面试基础知识点整理 &#xff08;一&#xff09;Java基础高频知识考点 针对人员&#xff1a; 1.全部人员都…

笔记 3 :linux 0.11 中的重要的全局变量 (b)

&#xff08;15&#xff09; 接着介绍缓冲区初始化&#xff0c;首先介绍一个全局量 end &#xff0c;表示 源代码编译的终点&#xff0c;随后就是缓冲区&#xff1a; 上图里也介绍了关于缓冲区的其它几个全局变量。全局数组 hash_table 的位置肯定是在 end 以前定义的。end 后为…

算法学习笔记(8.4)-完全背包问题

目录 Question&#xff1a; 图例&#xff1a; 动态规划思路 2 代码实现&#xff1a; 3 空间优化&#xff1a; 代码实现&#xff1a; 下面是0-1背包和完全背包具体的例题&#xff1a; 代码实现&#xff1a; 图例&#xff1a; 空间优化代码示例 Question&#xff1a; 给定n个物品…

Python数据分析案例51——基于K均值的客户聚类分析可视化

案例背景 本次案例带来的是最经典的K均值聚类&#xff0c;对客户进行划分类别的分析&#xff0c;其特点是丰富的可视化过程。这个经典的小案例用来学习或者课程作业在合适不过了。 数据介绍 数据集如下: 客户的编码&#xff0c;性别&#xff0c;年龄&#xff0c;年收入&#…

创建yum源、NFS共享存储

1. YUM源的提供方式 1.1 配置本地源仓库 cd /etc/yum.repos.d/ vim local.repo [local] // 仓库类别 namelocal // 仓库名称 baseurlfile:///mnt // 指定 URL 访问路径为光盘挂载目录 enabled1 …

UML建模案例分析-类图中的关系

概要 类图之间的关系比较多&#xff0c;绝大多数情况下重点关注的还是关联关系、组合、聚合这三种&#xff0c;最终是如何对应到代码上的。 例子 以订单为例&#xff1a;订单和订单项之间是组合关系&#xff0c;这和数据库实体之间不一样。数据库实体有主外键&#xff0c;开…

绘画平台小程序的设计

管理员账户功能包括&#xff1a;系统首页&#xff0c;个人中心&#xff0c;学生管理&#xff0c;讲师管理&#xff0c;课程类型管理&#xff0c;课程信息管理&#xff0c;课程购买管理&#xff0c;作业类型管理 开发系统&#xff1a;Windows 架构模式&#xff1a;SSM JDK版本&…

24/07/08数据结构(2.1203)顺序表实现

size属于结构体的作用域 如果要访问一个结构体的指针用-> 如果要访问一个结构体的变量用. 点操作 #include<stdio.h> #include<stdlib.h> #include<string.h> #include"seqlist.h" //typedef struct seqList{ // SLDataType* _data; //需…

SpringBoot3.3.0升级方案

本文介绍了由SpringBoot2升级到SpringBoot3.3.0升级方案&#xff0c;新版本的升级可以解决旧版本存在的部分漏洞问题。 一、jdk17下载安装 1、下载 官网下载地址 Java Archive Downloads - Java SE 17 Jdk17下载后&#xff0c;可不设置系统变量java_home&#xff0c;仅在id…

Leetcode 剑指 Offer II 086.分割回文串

题目难度: 中等 原题链接 今天继续更新 Leetcode 的剑指 Offer&#xff08;专项突击版&#xff09;系列, 大家在公众号 算法精选 里回复 剑指offer2 就能看到该系列当前连载的所有文章了, 记得关注哦~ 题目描述 给定一个字符串 s &#xff0c;请将 s 分割成一些子串&#xff0…

YOLOv10改进 | 特殊场景检测篇 | 单阶段盲真实图像去噪网络RIDNet辅助YOLOv10图像去噪(全网独家首发)

一、本文介绍 本文给大家带来的改进机制是单阶段盲真实图像去噪网络RIDNet&#xff0c;RIDNet&#xff08;Real Image Denoising with Feature Attention&#xff09;是一个用于真实图像去噪的卷积神经网络&#xff08;CNN&#xff09;&#xff0c;旨在解决现有去噪方法在处理…

零信任作为解决方案,Hvv还能打进去么?

零信任平台由“中心组件服务”三大部分构成&#xff0c;以平台形式充分融合软件定义边界&#xff08;SDP&#xff09;、身份与访问管理&#xff08;IAM&#xff09;、微隔离 &#xff08;MSG&#xff09;的技术方案优势&#xff0c;通过关键技术的创新&#xff0c;实现最佳可信…

PointCloudLib LocalMaximum_DeleteMaxPoint C++版本

测试效果 简介 在点云库&#xff08;Point Cloud Library&#xff0c;PCL&#xff09;中&#xff0c;处理点云数据时&#xff0c;经常需要去除局部最大点&#xff08;Local Maximum&#xff09;&#xff0c;这通常用于去除噪声、提取特定形状的特征或者简化点云数据。局部最大…