C++面向对象之多态性

news2024/12/28 20:04:24

文章目录

      • C++面向对象之多态性
        • 1.静态多态
        • 2.动态多态
        • 3.多态的好处
        • 3.1使用方法
      • 4.纯虚函数
      • 5.虚析构与纯虚析构
        • 5.1问题
        • 5.2解决
      • 6.其他知识点
      • 7.代码
      • 8.测试结果
        • 8.1父类中无虚函数,父类的指针指向子类对象,将调用父类中的函数,无法调用子类中的重写函数,即无法实现多态
        • 8.2父类中的函数由虚函数实现
        • 8.3父类指针对象,无法释放子类中开辟的堆空间数据
        • 8.4将父类的析构函数定义为虚析构函数
        • 8.5将父类中的析构函数定义为纯虚析构函数

C++面向对象之多态性

1.静态多态

通过函数重载和运算符重载实现,在编译时确定函数早绑定

2.动态多态

派生类和虚函数实现运行时多态,运行阶段实现函数晚绑定。

当子类重写了父类的虚函数时,子类中的虚函数表将替换父类中的虚函数,

所以当父类的引用或者指针指向子类对象时,将发生多态

3.多态的好处

结构清晰

可读性很强

利于后期的拓展和维护

3.1使用方法

父类的引用或者指针指向子类的对象

4.纯虚函数

定义格式:virtual 返回值类型 函数名称(参数列表) = 0;

类中有了纯虚函数,称为抽象类,抽象类无法实例化对象

子类必须重写父类中的所有纯虚函数,才能实例化对象,否则也是抽象类

5.虚析构与纯虚析构

5.1问题

多态使用时,如果子类中有属性开辟到了堆区,则父类指针释放时无法调用子类的析构函数

5.2解决

将父类中的析构函数改为虚析构函数或者纯虚析构函数

纯虚析构函数需要先声明,后实现,但是纯虚函数可以只声明

如果子类没有堆区数据,可以不将父类的析构函数写成虚析构或者纯虚析构

拥有纯虚析构函数的类也属于抽象类

6.其他知识点

空类(即里面什么代码都没有)的大小通过sizeof测定的结果是1

vfptr(虚函数表指针) ——> vftable(虚函数表,用于记录虚函数的地址)

7.代码

#include<iostream>

using namespace std;

class Animal {
public:
	Animal() {
		cout << "基类中的构造函数被调用!" << endl;
	}

	// 虚函数,虚函数将实现晚绑定
    virtual void speack() {
		cout << "动物在说话!" << endl;
	}
	virtual ~Animal() = 0;			// 纯虚析构函数,纯虚析构声明后,必须定义
};


// Animal中的纯虚析构实现部分,可以在这里释放父类开辟的堆空间
Animal::~Animal() {}

class Cat :public Animal {

public:
	Cat() {
		cout << "cat中的构造函数被调用" << endl;

	}
	void speack() {
	
		cout << "小猫在说话!" << endl;
	}
	~Cat() {

		cout << "cat中的析构函数被调用" << endl;
	}
};

class Dog : public Animal {
public:
	void speack() {
		cout << "小狗在说话" << endl;
	}
	~Dog() {
		cout << "dog中的析构函数被调用" << endl;
	}
};

// 地址早绑定,在编译阶段函数地址已经早绑定Animal
void doSpeack(Animal& animal) {
	animal.speack();
}

// 派生类重写基类中的虚函数,当基类的引用或者指针指向派生类时,实现多态
void test01() {
	Cat cat;
	Dog dog;

	doSpeack(cat);
	doSpeack(dog);

}

// 基类和派生类的构造函数和析构函数的调用
// 
void test02() {

	Animal* p_cat = new Cat();			// 开辟内存到堆区,需要手动释放
	if (p_cat != NULL) {
		delete p_cat;						// 释放指针
		p_cat = NULL;

	}
	
}
	
// --------------------------------------------------------------------------
class CPU {
public:
	virtual void caculate() = 0;
};

class VideoCard {
public:
	virtual void display() = 0;
};

class Memory {
public:
	virtual void storage() = 0;
};

class Computer {
public:
	Computer(CPU *cpu, VideoCard *videoCard,Memory * memory) {
		this -> m_cpu = cpu;
		this -> m_vc = videoCard;
		this -> m_mem = memory;
	}

	// 电脑的工作
	void work() {
		m_cpu->caculate();
		m_vc->display();
		m_mem->storage();

	}
	~Computer() {
		if (m_cpu != NULL) {
			delete m_cpu;
		}
		if (m_vc != NULL) {
			delete m_vc;
		}if (m_mem != NULL) {
			delete m_mem;
		}
	}

private:
	CPU* m_cpu;
	VideoCard* m_vc;
	Memory* m_mem;
};
// inter厂商
class InterCPU :public CPU {

public:
	 void caculate() {
		cout << "inter的CPU开始计算了" << endl;
	
	}
};

class InterVideoCard :public VideoCard {

public:
	 void display() {
		cout << "inter的显卡开始计算了" << endl;

	}
};
class InterMemory :public Memory {

public:
	 void storage() {
		cout << "inter的内存条开始存储了" << endl;

	}
};
// lenovo

class lenovoCPU :public CPU {

public:
	virtual void caculate() {
		cout << "lenovo的CPU开始计算了" << endl;

	}
};

class lenovoVideoCard :public VideoCard {

public:
	virtual void display() {
		cout << "lenovo的显卡开始计算了" << endl;

	}
};
class lenovoMemory :public Memory {

public:
	virtual void storage() {
		cout << "lenovo的内存条开始存储了" << endl;

	}
};

void test03() {

	// 创建电脑
	CPU* interCPU = new InterCPU;
	VideoCard* interCard = new InterVideoCard;
	Memory* interMemory = new InterMemory;

	Computer* computer1 = new Computer(interCPU, interCard, interMemory);
	computer1->work();
	delete computer1;

	cout << "---------------------------" << endl;
	Computer* computer2 = new Computer(new lenovoCPU, new lenovoVideoCard,new lenovoMemory);
	computer2->work();
	delete computer2;

	cout << "---------------------------" << endl;
	Computer* computer3 = new Computer(new InterCPU, new lenovoVideoCard, new lenovoMemory);
	computer3->work();
	delete computer3;
}
int main() {   

	//test01();
	//test02();
	test03();
	system("pause");
	return 0;
}

8.测试结果

8.1父类中无虚函数,父类的指针指向子类对象,将调用父类中的函数,无法调用子类中的重写函数,即无法实现多态

在这里插入图片描述

8.2父类中的函数由虚函数实现

在这里插入图片描述

父类的指针指向小猫子类,将调用小猫类中的重写函数,实现多态

8.3父类指针对象,无法释放子类中开辟的堆空间数据

在这里插入图片描述

cat类中的析构函数没有被调用,无法释放开辟的堆空间数据

8.4将父类的析构函数定义为虚析构函数

子类中的析构函数被调用
在这里插入图片描述

8.5将父类中的析构函数定义为纯虚析构函数

子类中的析构函数被调用,将父类中的析构函数声明为纯虚析构函数后,必须要实现声明的函数。
在这里插入图片描述

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

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

相关文章

Qt入门基础

目录 一 学习Qt的动机 二 创建第一个Qt程序 关于main.cpp QApplication Widget 关于对象树 关于Widget常用的API return a.exec() 一 学习Qt的动机 我在学习了C之后&#xff0c;想做图形化界面。实现前后端的交互。这时候就可以利用Qt进行编程。 二 创建第一个Qt程序 Qt…

【RocketMQ】消息的存储

Broker对消息的处理 BrokerController初始化的过程中&#xff0c;调用registerProcessor方法注册了处理器&#xff0c;在注册处理器的代码中可以看到创建了处理消息发送的处理器对象SendMessageProcessor&#xff0c;然后将其注册到远程服务中&#xff1a; public class Brok…

哨声吹响,与世界杯相关的欺诈也在激增

2022 年世界杯已经开始&#xff0c;通过虚假流媒体网站与彩票针对足球迷的诈骗激增。近日&#xff0c;Zscaler 发现与世界杯相关的新注册域名有所增加&#xff0c;尽管并非都是恶意的&#xff0c;也是值得警惕的。 流量趋势 随着世界杯的开赛&#xff0c;从 11 月 21 日流媒体…

Python set集合全部操作方法

文章目录一. 介绍1. 创建set集合2. 判断元素是否在集合内3. 集合推导式(Set comprehension)二. 集合基本操作1. add&#xff08;&#xff09;添加单个元素2. update&#xff08;&#xff09;添加列表&#xff0c;元组&#xff0c;字典等整体数据3. remove ( ) 移除元素&#xf…

PACS三维影像后处理系统源码 PACS源码

PACS源码 PACS3D影像后处理系统源码 一、系统概述&#xff1a; ​基于VC MSSQL开发的一套三甲医院医学影像PACS系统源码&#xff0c;集成3D影像后处理功能&#xff0c;包括三维多平面重建、三维容积重建、三维表面重建、三维虚拟内窥镜、最大/小密度投影、心脏动脉钙化分析等…

mysql数据库之视图

视图&#xff08;view&#xff09;是一种虚拟的存在&#xff0c;视图中的数据并不在数据库中实际存在&#xff0c;行和列数据来自定义视图的查询中使用的表&#xff0c;并且是在使用视图时动态生成的。 通俗的讲&#xff0c;视图之保存了查询的sql逻辑&#xff0c;不保存查询结…

【C语言】函数指针和指针函数

文章目录[TOC](文章目录)前言概述函数指针定义&#xff1a;使用&#xff1a;回调函数指针函数前言 今天学一下函数指针 提示&#xff1a;以下是本篇文章正文内容&#xff0c;下面案例可供参考 概述 函数指针&#xff1a;是一个指向函数的指针&#xff0c;在内存空间中存放的…

关于小程序内存在违规内容的处理警告

遇到了问题&#xff0c;就记录一下解决过程吧 小程序涉及提供在线观看视频服务&#xff0c;请补充文娱-视频广场类目&#xff1b; 我们的小程序做了一个类似抖音上下滑动观看视频的页面&#xff0c;被警告了&#xff0c;查看了文档&#xff0c; https://developers.weixin.qq.…

C语言程序-计算闰年平年

#include <stdio.h> int main() { int year ,month,day,i1; printf("欢迎使用本程序&#xff0c;使用愉快\n") ; while(i<10){ printf("请输入您需要计算的年\n"); scanf("%d",&year); printf("…

安全高效 | AIRIOT智慧工地管理解决方案

建筑工地施工材料、机械设备、工程车、人员各个环节管理相对复杂、建筑业也是安全事故频发的高危行业&#xff0c;安全管控尤为重要。建筑施工单位想要保障安全生产&#xff0c;做好能源消耗管控降低生产成本&#xff0c;需要解决掉很多现状问题&#xff1a;1、工地施工作业人员…

【Leetcode 剑指Offer】第 11 天 双指针(简单)

双指针剑指 Offer 18. 删除链表的节点剑指 Offer 18. 删除链表的节点 给定单向链表的头指针和一个要删除的节点的值&#xff0c;定义一个函数删除该节点。 返回删除后的链表的头节点。 示例 1: 输入: head [4,5,1,9], val 5 输出: [4,1,9] 解释: 给定你链表中值为 5 的第二…

服务器(centos7.6)已经安装了宝塔面板,想在里面安装一个SVN工具(subversion),应该如何操作呢?

首先&#xff0c;在登录进入宝塔面板&#xff0c;然后点击左侧终端&#xff0c;进入终端界面&#xff0c;如下图&#xff1a;------------------------------------------如果是第一次使用会弹出输入服务器用户名和密码&#xff0c;此时输入root账号和密码&#xff0c;即可进入…

2.基于Label studio的训练数据标注指南:(智能文档)文档抽取任务、PDF、表格、图片抽取标注等

文档抽取任务Label Studio使用指南 1.基于Label studio的训练数据标注指南&#xff1a;信息抽取&#xff08;实体关系抽取&#xff09;、文本分类等 2.基于Label studio的训练数据标注指南&#xff1a;&#xff08;智能文档&#xff09;文档抽取任务、PDF、表格、图片抽取标注等…

Python3-集合

Python3 集合 集合&#xff08;set&#xff09;是一个无序的不重复元素序列。 可以使用大括号 { } 或者 set() 函数创建集合&#xff0c;注意&#xff1a;创建一个空集合必须用 set() 而不是 { }&#xff0c;因为 { } 是用来创建一个空字典。 创建格式&#xff1a; parame …

奇淫技巧:熟练使用Fetch一个干翻PostMan的顶级技巧

一&#xff1a;如何使用fetch重新发送一个接口请求&#xff1f; 按照如下的请求进行复制 fetch("https://bip-test.yyuap.com/mdf-node/uniform/user/checkAuthByCode?terminalType1&serviceCodeorderList&codeuserdef_filterItem,userdef_schemaSetting"…

《C++ Primer》第十章 泛型算法

《C Primer》第十章 泛型算法 10.1 概述 大多数算法定义在头文件algorithm中&#xff0c;还有一些算法在numeric中。例如标准库算法find: int val 42;//即将查找的值 //如果在vec中找到想要的元素&#xff0c;则返回结果指向它&#xff0c;否则返回vec.cend() auto result …

小样本学习--学习记录

之前在做课题的时候&#xff0c;把数据不均衡和小样本的概念混淆了&#xff0c;昨天看了一篇论文&#xff1a;《 面向小样本数据的机器学习方法研究综述 &#xff08;陈良臣&#xff0c;傅德印&#xff09;》 &#xff0c;这篇论文写的非常清晰。推荐阅读。 网上的一些综述整理…

2月VR大数据:硬件份额变化不大,PS VR2首发游戏超50款

Hello大家好&#xff0c;每月一期的VR内容/硬件大数据统计又和大家见面了。 想了解VR软硬件行情么&#xff1f;关注这里就对了。我们会统计Steam平台的用户及内容等数据&#xff0c;每月初准时为你推送&#xff0c;不要错过喔&#xff01;本数据报告包含&#xff1a;Steam VR硬…

擅长捉弄的内存马同学:Valve内存马

前言 内存马的文章已经很久没有更新过了&#xff0c; 这篇文章不太适合想直接学习利用Valve内存马的师傅 &#xff0c;因为我这篇文章可能会有大篇笔墨去说Tomcat容器&#xff0c;至于原因就是我想更深入的了解一些Tomcat&#xff0c;而Valve内存马属于已经被师傅们玩烂了的一…

现场设备发生故障,如何第一时间通知相关人员?

一、前言 虹科物联网HMI作为一站式物联网解决方案&#xff0c;致力于解决用户在数据采集和可视化、远程监控、边缘计算、软PLC、数据存储&#xff08;SQL数据库和CSV文件&#xff09;、数据上云&#xff08;OPC UA、MQTT&#xff09;等方面的需求&#xff0c;帮助企业快速实现…