c++(六)

c++(六)

  • 多态
    • 概念
    • 在c++中是如何实现多态
      • 静态多态(绑定)
      • 动态多态(绑定)
    • 动态多态的实现原理
    • 动态内存分配中遇到的问题
  • 重载、重定义、重写的区别
  • 抽象类
  • 接口类---抽象类
  • 空类对象的内存大小
  • explicit
  • final
    • 修饰类
    • 修饰成员函数

在这里插入图片描述

多态

概念

多种状态(一个事物的多种状态或形态)

<1>水在不同的温度下呈现的不同状态
<2>买票
学生票;
成人票;
老年票;
军人;

在c++中是如何实现多态

绑定:就是把函数调用语句与对应的代码块进行了绑定!。

静态多态(绑定)

编译的时候,就知道执行的是哪一个函数体
调用函数时,函数名是一样的,当我们传入不同参数的时候,执行的是不同的函数体(函数重载、运算符重载)

动态多态(绑定)

在运行的时候,才知道执行的是哪一个函数体

案例:如果要求两个子类的周长和面积之和,就得写两个函数来实现,传入不同的对象
在这里插入图片描述

在这里插入图片描述

#include <iostream>
using namespace std;
class Shape
{
public:
	Shape(int s = 0, int c = 0) :s(s), c(c)
	{
		cout << "Shape构造" << endl;
	}
	~Shape()
	{
		cout << "Shape析构" << endl;
	}
	int getC()
	{
		cout << "周长:" << this->c << endl;
		return this->c;
	}
	int getS()
	{
		cout << "面积:" << this->s << endl;
		return this->s;
	}
private:
protected:
	int s;
	int c;
};
class Rect:public Shape
{
public:
	Rect(int a = 0, int b = 0) :a(a), b(b)
	{
		cout << "Rect构造" << endl;
	}
	~Rect()
	{
		cout << "Rect析构" << endl;
	}
	int getC()
	{
		this->c = (this->a + this->b) * 2;
		return this->c;
	}
	int getS()
	{
		this->s = this->a * this->b;
		return this->s;
	}
	void show()
	{
		cout << "周长:" << this->c << ",面积:" << this->s << endl;
	}
private:
protected:
	int a;
	int b;
};
class Circle:public Shape
{
public:
	Circle(int r = 0) :r(r)
	{
		cout << "Circle构造" << endl;
	}
	~Circle()
	{
		cout << "Circle析构" << endl;
	}
	int getC()
	{
		this->c = 2 * 3.14 * this->r;
		return this->c;
	}
	int getS()
	{
		this->s = 3.14 * this->r * this->r;
		return this->s;
	}
	void show()
	{
		cout << "周长:" << this->c << ",面积:" << this->s << endl;
	}
private:
protected:
	int r;
};
void Rcs(Rect & demo)
{
	cout << demo.getC()+ demo.getS()<< endl;
}
void Ccs(Circle& demo)
{
	cout << demo.getC() + demo.getS() << endl;
}
int main()
{
	//矩形对象
	Rect rect(2,3);
	Rcs(rect);
	
	//圆形对象
	Circle circle(3);
	Ccs(circle);


}

解决:用父类统一管理子类
在这里插入图片描述
问题:通过父类的引用操作子类的对象时,并没有执行子类的函数,执行的是子类从父类继承过来的函数
在这里插入图片描述
解决:目的:执行子类重定义的函数,将父类对应的函数写成虚函数
虚函数的格式:

virtual 返回值类型 函数名(参数列表){}

未加victual之前,不能访问子类重定义函数的原因:
将子类对象强制赋值给父类的引用,父类的引用所访问的范围小,访问不到子类的函数
在这里插入图片描述

#include <iostream>
using namespace std;
class Shape
{
public:
	Shape(int s = 0, int c = 0) :s(s), c(c)
	{
		cout << "Shape构造" << endl;
	}
	~Shape()
	{
		cout << "Shape析构" << endl;
	}
	virtual int getC()
	{
		cout << "周长:" << this->c << endl;
		return this->c;
	}
	virtual int getS()
	{
		cout << "面积:" << this->s << endl;
		return this->s;
	}
private:
protected:
	int s;
	int c;
};
class Rect:public Shape
{
public:
	Rect(int a = 0, int b = 0) :a(a), b(b)
	{
		cout << "Rect构造" << endl;
	}
	~Rect()
	{
		cout << "Rect析构" << endl;
	}
	int getC()
	{
		this->c = (this->a + this->b) * 2;
		return this->c;
	}
	int getS()
	{
		this->s = this->a * this->b;
		return this->s;
	}
	void show()
	{
		cout << "周长:" << this->c << ",面积:" << this->s << endl;
	}
private:
protected:
	int a;
	int b;
};
class Circle:public Shape
{
public:
	Circle(int r = 0) :r(r)
	{
		cout << "Circle构造" << endl;
	}
	~Circle()
	{
		cout << "Circle析构" << endl;
	}
	int getC()
	{
		this->c = 2 * 3.14 * this->r;
		return this->c;
	}
	int getS()
	{
		this->s = 3.14 * this->r * this->r;
		return this->s;
	}
	void show()
	{
		cout << "周长:" << this->c << ",面积:" << this->s << endl;
	}
private:
protected:
	int r;
};
void Scs(Shape & demo)
{
	cout << demo.getC()+ demo.getS()<< endl;
}
int main()
{
	//矩形对象
	Rect rect(2,3);
	Scs(rect);
	
	//圆形对象
	Circle circle(3);
	Scs(circle);


}

在这里插入图片描述

动态多态的实现原理

有虚函数一定能实现动态多态吗?不一定

多态的实现:
<1>一个父类,有多个子类
<2>父类中有虚函数,子类重写父类的虚函数
<3>用父类对象的指针或者引用去操作子类的对象并调用虚函数的受,才会触发动态多态(决定性因素)

将父类的对应的函数写成虚函数,在子类中进行重写,通过父类对象的指针/引用去操作子类对象就可以调用到子类的函数了

指针所能访问的空间的大小:由指针指向的数据类型大小决定

int *p; //4字节
shape *p;// 8个字节

在这里插入图片描述
为什么添加virtual就可以访问子类的函数?

虚函数表:保存虚函数的地址(函数指针数组)

什么时候有虚函数表?

一个类中一旦有了虚函数,那么这个类中就有了一个虚函数表,保存这个类中所有虚函数的地址,如果这个类被子类继承了,子类中也会有一张虚函数表

父类的虚函数表和子类的虚函数表一样吗?

<1>如果子类不重写父类的虚函数,那么父类和子类的虚函数表是一样的
<2>如果子类重写了父类的虚函数,那么子类虚函数表中对应的就是子类重写之后的虚函数地址

在这里插入图片描述

  1. 父类有虚函数,那么被子类继承之后,子类中对应的函数也是虚函数!子类中对应函数的virtual关键字可加可不加!
  2. 父类中有函数是虚函数,如果子类有重定义的话,此时被称为重写(覆盖–就是子类中的函数把从父类中继承来的给覆盖了。子类中有且只有一个这样子的函数!!!)!!!!
  3. 重写就必须保证 子类中的函数首部与父类中函数的首部是一模一样的,首部指的是:函数类型 函数名(参数列表)。

动态内存分配中遇到的问题

问题:把new出来的子类对象,赋值给了父对象类型的指针,在整个操作过程中,都是通过父类的指针来操作,使用delete去释放空间的时候,只执行了父类的析构函数,并没有子类的析构函数,可能会造成内存泄漏的问题(在子类的构造函数去new空间了)
在这里插入图片描述

在这里插入图片描述

解决:目标:执行子类的析构函数
将父类的析构函数写成虚函数,子类的析构自然也是虚函数!

在这里插入图片描述

#include <iostream>
using namespace std;
class Shape
{
public:
	Shape(int s = 0, int c = 0) :s(s), c(c)
	{
		cout << "Shape构造" << endl;
	}
	virtual ~Shape()
	{
		cout << "Shape析构" << endl;
	}
	virtual int getC()
	{
		cout << "周长:" << this->c << endl;
		return this->c;
	}
	virtual int getS()
	{
		cout << "面积:" << this->s << endl;
		return this->s;
	}
private:
protected:
	int s;
	int c;
};
class Rect :public Shape
{
public:
	Rect(int a = 0, int b = 0) :a(a), b(b)
	{
		cout << "Rect构造" << endl;
	}
	~Rect()
	{
		cout << "Rect析构" << endl;
	}
	int getC()
	{
		this->c = (this->a + this->b) * 2;
		return this->c;
	}
	int getS()
	{
		this->s = this->a * this->b;
		return this->s;
	}
	void show()
	{
		cout << "周长:" << this->c << ",面积:" << this->s << endl;
	}
private:
protected:
	int a;
	int b;
};
class Circle :public Shape
{
public:
	Circle(int r = 0) :r(r)
	{
		cout << "Circle构造" << endl;
	}
	~Circle()
	{
		cout << "Circle析构" << endl;
	}
	int getC()
	{
		this->c = 2 * 3.14 * this->r;
		return this->c;
	}
	int getS()
	{
		this->s = 3.14 * this->r * this->r;
		return this->s;
	}
	void show()
	{
		cout << "周长:" << this->c << ",面积:" << this->s << endl;
	}
private:
protected:
	int r;
};
void Scs(Shape* demo)
{
	cout << demo->getC() + demo->getS() << endl;
}
int main()
{

	Shape* p = new Circle(4);
	Scs(p);
	delete p;


}

<1>在设计类的时候,为什么建议把析构函数写成虚函数
防止内存泄漏
<2>为什么不执行子类的析构函数就可能会存在内存泄漏的问题
在子类的构造函数去new空间了

重载、重定义、重写的区别

重载:同一个作用域内,函数功能相似,函数名相同、参数不同,与返回值无关的一组函数
重定义:在继承关系中,子类重定义父类的函数,函数名相同即可
重写(覆盖):在继承关系中,子类重写父类的虚函数
备注:函数首部必须一样
首部:返回值类型 函数名(形式参数列表)

抽象类

在设计类的时候,发现这个类确实需要这样子的一个操作函数,但是在父类中不知道该怎么实现,它的所有的子类都要实现这个函数,并且所有的子类实现这个函数的效果是不一样的,这种情况下,就可以把这个函数写成纯虚函数

virtual 返回值类型 函数名(形参列表) = 0;

在这里插入图片描述
注意:抽象类是不能创建对象的
在这里插入图片描述

作用:就是用来被继承的,在子类中去实现这个纯虚函数(每一个子类都要去实现这个纯虚函数)
如果子类没有实现这个纯虚函数,子类也变成了抽象类

#include <iostream>
using namespace std;
class Shape //抽象类
{
public:
	Shape(int s = 0, int c = 0) :s(s), c(c)
	{
		cout << "Shape构造" << endl;
	}
	virtual ~Shape()
	{
		cout << "Shape析构" << endl;
	}
	virtual int getC() = 0;//纯虚函数
	
	virtual int getS() = 0;
	
private:
protected:
	int s;
	int c;
};
class Rect :public Shape
{
public:
	Rect(int a = 0, int b = 0) :a(a), b(b)
	{
		cout << "Rect构造" << endl;
	}
	~Rect()
	{
		cout << "Rect析构" << endl;
	}
	int getC()
	{
		this->c = (this->a + this->b) * 2;
		return this->c;
	}
	int getS()
	{
		this->s = this->a * this->b;
		return this->s;
	}
	void show()
	{
		cout << "周长:" << this->c << ",面积:" << this->s << endl;
	}
private:
protected:
	int a;
	int b;
};
class Circle :public Shape
{
public:
	Circle(int r = 0) :r(r)
	{
		cout << "Circle构造" << endl;
	}
	~Circle()
	{
		cout << "Circle析构" << endl;
	}
	int getC()
	{
		this->c = 2 * 3.14 * this->r;
		return this->c;
	}
	int getS()
	{
		this->s = 3.14 * this->r * this->r;
		return this->s;
	}
	void show()
	{
		cout << "周长:" << this->c << ",面积:" << this->s << endl;
	}
private:
protected:
	int r;
};
void Scs(Shape* demo)
{
	cout << demo->getC() + demo->getS() << endl;
}
int main()
{

	Shape* p = new Circle(4);
	Scs(p);
	delete p;


}

在这里插入图片描述

接口类—抽象类

接口类其实就是抽象类的应用
当抽象类不能实例化对象时,抽象类中的成员变量也就不能初始化,其构造函数也就不能被执行

接口类:类中只有成员函数,没有数据成员,并且成员函数必须是纯虚函数
作用:就是用来被继承的,描述一些能力、协议

#include <iostream>
using namespace std;
//接口类
class fly_land
{
public:
	virtual void fly() = 0;//纯虚函数
	virtual void land() = 0;
};
class Bird :public fly_land
{
public:
	void fly()
	{
		cout << "bird  fly ....." << endl;
	}
	void land()
	{
		cout << "bird land....." << endl;
	}
};
class Plane :public fly_land
{
public:
	void fly()
	{
		cout << "plane fly....." << endl;
	}
	void land()
	{
		cout << "plane land....." << endl;
	}
};
void dosomething(fly_land& demo)
{
	demo.fly();
}
int main()
{
	Bird bird;
	dosomething(bird);

	Plane plane;
	dosomething(plane);
}

在这里插入图片描述

空类对象的内存大小

默认构造函数、析构函数、默认拷贝构造函数、赋值运算符函数、取值运算符函数 const 修饰的取值运算符
空类占内存大小:1字节
在这里插入图片描述
在这里插入图片描述

explicit

作用:修饰构造函数的,对应的构造函数被称为 转换构造函数!!!!
意义:防止构造函数单参数的时候进行自动类型的转换

在这里插入图片描述

final

作用:修饰类和类中的成员函数

修饰类

作用:不能被继承
在这里插入图片描述

修饰成员函数

作用:无法重写
在这里插入图片描述

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

稳定性大升级!EMCS全球服务网络携手NineData实现数据实时同步

易客满&#xff08;ECMS Express&#xff09;专注于提供全球化的国际物流解决方案和经济快递服务&#xff0c;服务网络覆盖全球主要贸易市场的国际物流公司。ECMS拥有国际快递、国际货代、仓储供应链全球覆盖服务能力。 1. 易客满&#xff08;ECMS&#xff09;数据复制的技术挑…

SOLIDWORKS 2024:零件亮点的升级与突破

随着科技的不断发展&#xff0c;工程设计软件也在持续进步&#xff0c;以更好地满足工程师和设计师的需求。SOLIDWORKS&#xff0c;作为一款广泛使用的三维CAD软件&#xff0c;一直在不断地推出新版本&#xff0c;以提供更强大、更便捷的功能。今天&#xff0c;我们将深入探讨S…

高边坡监测常用的主要仪器设备

随着人类的发展&#xff0c;近几年由于人类生活生产的破坏&#xff0c;地球环境不断恶化。鉴于这一现象&#xff0c;监测行业也随之应运而生。常见的监测类型有&#xff1a;边坡监测&#xff0c;地灾监测&#xff0c;水库监测&#xff0c;大坝监测&#xff0c;矿山监测&#xf…

geotrust通配符证书600元且赠送一个月

GeoTrust作为国际知名的数字证书颁发机构&#xff0c;旗下有RapidSSL、QuickSSL等子品牌经营着各种类型的SSL数字证书&#xff0c;其中RapidSSL旗下的SSL数字证书都是入门级的&#xff0c;性价比高。审核速度也比较快&#xff0c;证书的适用范围也比较广泛。今天就随SSL盾小编了…

HarmonyOS-9(stage模式)

配置文件 {"module": {"requestPermissions": [ //权限{"name": "ohos.permission.EXECUTE_INSIGHT_INTENT"}],"name": "entry", //模块的名称"type": "entry", //模块类型 :ability类型和…

【Python Cookbook】S01E02 从任意长度的可迭代对象中分解元素

目录 问题解决方案讨论 问题 从某个不确定长度的迭代对象中分解出 N N N 个元素。 解决方案 *分解操作和各种函数式语言中的列表处理功能有着一定的相似性。例如&#xff0c;如果有一个列表&#xff0c;可以像下面这样轻松将其分解为头部和尾部。 scores [99, 97, 91, 89…

CHIMA专访美创高级总监丁斐:为医疗数据安全构筑体系化防御新机制

5月17-19日&#xff0c;中国医院信息网络大会&#xff08;CHIMA 2024&#xff09;在南京隆重召开。作为结识多年的老友&#xff0c;美创科技再携以数据为中心的全系列安全业务、新一代数字化安全平台、医疗行业解决方案精彩亮相。 会议期间&#xff0c;CHIMA专访美创科技&…

金融反欺诈指南:车险欺诈为何如此猖獗?

目录 车险欺诈猖獗的原因 车险欺诈的识别难点 多重合作打击车险欺诈 保险企业需要提升反欺诈能力 监管部门需要加强协同合作 青岛市人民检察院在其官方微信公众号上发布的梁某保险诈骗案显示&#xff0c;2020 年以来&#xff0c;某汽修厂负责人梁某、某汽车服务公司负责人孙某&…

精通推荐算法7:多任务学习 -- 总体架构

1 多任务学习的总体架构 目前的互联网主流推荐场景在大多数情况下需要优化多个业务目标。例如在淘宝商品推荐中&#xff0c;需要兼顾点击率和转化率。在抖音短视频推荐中&#xff0c;需要考虑完播率、播放时长、点赞率、评论率、关注率等目标。为了提升各项业务目标&#xff0…

光栅幅值细分原理与实现

本文介绍光栅幅值细分原理与实现。 光栅是工业测量领域中常见的传感器&#xff0c;如下图。主要厂家有雷尼绍&#xff0c;海德汉&#xff0c;配套的光栅读数头有模拟信号的&#xff0c;也有直接细分输出数字脉冲的&#xff0c;本文的细分针对模拟信号&#xff0c;即有正弦信号…

数字化业务流程升级再造,解困基本半导体的CRM应用5年之痒

在新能源汽车、工业互联、5G通信、消费电子等需求的强力拉动下&#xff0c;以碳化硅为代表的第三代半导体产业迎来爆发式增长。 深圳基本半导体有限公司&#xff08;以下简称“基本半导体”&#xff09;是中国第三代半导体创新企业&#xff0c;专业从事碳化硅功率器件的研发与…

NineData 联合创始人周振兴将参加开源数据库技术沙龙,并和 PolarDB 开源社区一起去娃哈哈带来主题分享!

5月31日&#xff08;周五&#xff09;&#xff0c;PolarDB 开源社区将联合娃哈哈集团共同举办开源数据库技术沙龙&#xff01;NineData 联合创始人周振兴受邀参加&#xff0c;并将分享《NineData&#xff0c;Any to Any 数据复制之路》的技术分享。 本次活动汇聚了 PolarDB 产品…

用于水利工程系统方面的传感器M-A542VR10

近几年快速发展的IC技术和计算机技术&#xff0c;为传感器的发展提供了良好与可靠的科学技术基础。使传感器的发展日新月益&#xff0c;且数字化、多功能与智能化是现代传感器发展的重要特征爱普生也在不断发展自己的传感器型号。随着水利工程技术的不断进步&#xff0c;传感器…

面向对象编程:坦克飞机大战游戏的重构之旅

新书上架~&#x1f447;全国包邮奥~ python实用小工具开发教程http://pythontoolsteach.com/3 欢迎关注我&#x1f446;&#xff0c;收藏下次不迷路┗|&#xff40;O′|┛ 嗷~~ 目录 一、面向对象编程思想入门 坦克对象的定义 属性与行为方法的实现 二、面向过程与面向对象…

子网划分案例

4.2子网划分 “有类编址”的地址划分过于死板&#xff0c;划分的颗粒度太大&#xff0c;会有大量的主机号不能被充分利用&#xff0c;从而造成了大量的IP地址资源浪费。因此可以利用子网划分来减少地址浪费&#xff0c;即VLSM (Variable Length Subnet Mask)&#xff0c;可变长…

python清洗苹果产量数据:从字符串到整型的转化

新书上架~&#x1f447;全国包邮奥~ python实用小工具开发教程http://pythontoolsteach.com/3 欢迎关注我&#x1f446;&#xff0c;收藏下次不迷路┗|&#xff40;O′|┛ 嗷~~ 目录 一、引言 二、使用普通方法清洗数据 1. 创建字典并遍历 2. 示例代码 3. 结果展示 三、使…

WAMP无法启动mysql

一种原因是原来安装过mysql,mysql默认是自启动的&#xff0c;而WAMP内置mysql会发生冲突&#xff0c;所以 解决方法&#xff1a; winR 输入 services.msc 将mysql关闭&#xff0c;并设为手动模式

Java是长连接

Java是长连接&#xff0c;springboot进程被结束才断开 一个连接池有10个连接&#xff0c;2个并发会占用2个连接&#xff0c;用完之后归还给连接池 springboot服务用户的是线程池&#xff0c;返回结果之后&#xff0c;线程自动归还到线程池。跟php机制不一样 php是短链接&am…

【Leetcode 206】 反转链表——此递归相当妙啊

题目 给你单链表的头节点 head &#xff0c;请你反转链表&#xff0c;并返回反转后的链表。 示例 1&#xff1a; 输入&#xff1a;head [1,2,3,4,5] 输出&#xff1a;[5,4,3,2,1]示例 2&#xff1a; 输入&#xff1a;head [1,2] 输出&#xff1a;[2,1]示例 3&#xff1a; …

重学java 51.Collections集合工具类、泛型

"我已不在地坛&#xff0c;地坛在我" —— 《想念地坛》 24.5.28 一、Collections集合工具类 1.概述:集合工具类 2.特点: a.构造私有 b.方法都是静态的 3.使用:类名直接调用 4.方法: static <T> boolean addAll(collection<? super T>c,T... el…