15. C++泛型与符号重载

news2024/11/15 21:21:47


【泛型编程】

若多组类型不同的数据需要使用相同的代码处理,在C语言中需要编写多组代码分别处理,这样做显然太过繁琐,C++增加了虚拟类型,使用虚拟类型可以实现一组代码处理多种类型的数据。

虚拟类型是暂时不确定的数据类型,它在定义时不指定具体类型,而是在使用时指定类型,可以用于单个数据类型,也可以用于数组、结构体,使用虚拟类型编程也称为泛型编程,意为广泛类型。

使用虚拟类型的代码称为模板,但是全局数据不能使用虚拟类型,全局数据也无需定义为模板。

全局函数模板

函数模板的参数、返回值可以使用虚拟类型,参数与返回值的数量必须相同,只是类型不同。

#include <iostream>
template <typename T>   //使用template关键词定义虚拟类型,T为虚拟类型名称
T add(T t1, T t2)
{
	return t1+t2;
}
int main()
{
	printf("%d\n", add(1, 2));          //T指定为int类型
	printf("%f\n", add(0.1f, 0.2f));    //T指定为float类型
	
	return 0;
}

虚拟类型使用template关键词定义,也可以使用class定义,可以在<>符号内定义多个虚拟类型,不同虚拟类型使用,符号隔开,但是每个定义的虚拟类型都必须使用,否则编译报错。

函数模板内可以使用多个虚拟类型,执行函数模板时需要为其内部虚拟类型指定具体类型,当多次执行函数模板并为虚拟类型设置不同的具体类型时,编译器会将函数模板编译为多个函数,分别使用不同的指令处理数据,上述代码中的add函数实际上会被编译器编译成两个函数,分别使用整数运算指令和浮点数运算指令处理数据,模板只是简化了程序员的工作量,并没有减少程序编译后的代码量。

成员函数模板

#include <iostream>
class math
{
public:
	template <typename T>    //定义虚拟类型
	T add(T t1, T t2) const
	{
		return t1+t2;
	}
};
int main()
{
	math math1;
	printf("%d\n", math1.add(1, 2));
	printf("%f\n", math1.add(0.1f, 0.2f));
	
	return 0;
}

类模板

成员数据使用虚拟类型的类称为类模板。

#include <iostream>
template <typename T>
class math
{
private:
	T a,b;
	
public:
	math(T t1, T t2)
	{
		a = t1;
		b = t2;
	}
	
	T add() const
	{
		return a+b;
	}
};
int main()
{
	math<int> math1(1, 2);         //创建对象时需要使用<>符号设置数据类型
	printf("%d\n", math1.add());
	
	math<float> math2(0.1, 0.2);
	printf("%f\n", math2.add());
	
	return 0;
}

成员数组模板

虚拟类型用于类成员数组时可以额外定义一个变量,此变量用于设置数组模板的长度,从而实现数组的类型、长度都在定义时临时确定。

#include <iostream>
template <typename T, int i>    //变量i设置数组长度
class array
{
private:
	T a[i];
	
public:
	//......
};
int main()
{
	array<int, 5> array1;      //成员数组类型为int,包含5个元素
	array<float, 6> array2;    //成员数组类型为float,包含6个元素
	
	return 0;
}


【符号重载】

在C++中可以借助operator关键词将语法中的某些符号、关键词当做函数名,从而重新定义此符号的功能,这种函数称为符号函数,调用符号函数执行时可以无需指定operator关键词,直接使用重载的符号即可,全局函数和成员函数都可以设置为符号函数。

使用符号函数会让代码更简洁,比如连接字符串函数使用+符号作为函数名,即可通过+符号连接两个字符串。


可重载的符号如下:

+  -  *  /  ++  --  %  <<  >>
&&  ||  !  &  |  ~  ^
<  >  ==  !=  >=  <=
=  +=  -=  *=  /=  %=  ^=  &=  |=  >>=  <<=
,  ()  []
->  ->*
new  delete  new[]  delete[]


符号重载注意事项:
1.只能使用C++语法中原有符号,不能使用C++语法没有的符号。
2.= () [] -> 这四种符号只能用于成员函数,不能用于全局函数。
3.重载不同符号时,函数可以设置的参数个数不同。
4.重载相同符号时,全局函数与成员函数可以设置的参数个数不同。
5.重载不同符号有不同的限制,比如:重载-符号不能计算两个double数据相加、重载%符号不能只有一个操作数、重载new的函数返回值只能是void类型指针。


重载 + 符号

重载+符号连接固定长度字符串对象,并返回连接结果。

#include <iostream>
class string
{
public:
	char strvar[100] = {0};
	
	/* operator+符号函数连接string对象 */
	string operator+(const string & conobj) const
	{
		string result;              //存储连接结果
		unsigned int strlen = 0;    //存储本类strvar空字符下标
		unsigned int conlen = 0;    //存储conobj.strvar空字符下标
		
		result.strvar[0] = 0;       //初始空字符
		
		/* 查询本类strvar空字符下标,若没有空字符则当做不合规string对象处理,strlen = 0 */
		for(int i = 0; i < 100; i++)
		{
			if(strvar[i] == 0)
			{
				strlen = i;
				break;
			}
		}
		
		/* 查询conobj.strvar空字符下标 */
		for(int i = 0; i < 100; i++)
		{
			if(conobj.strvar[i] == 0)
			{
				conlen = i;
				break;
			}
		}
		
		/* result连接本类strvar */
		if(strlen != 0)
		{
			result = *this;
		}
		
		/* result连接conobj.strvar */
		if(conlen != 0)
		{
			if(strlen == 0)
			{
				result = conobj;
			}
			else
			{
				for(int i = 0; strlen<99 && i<=conlen; i++)
				{
					result.strvar[strlen] = conobj.strvar[i];
					strlen++;
				}
				
				result.strvar[99] = 0;    //确保末尾元素是空字符
			}
		}
		
		return result;
	}
	
	/* 重载operator+符号函数,连接字符串 */
	string operator+(const char * conobj) const
	{
		string result;
		unsigned int strlen = 0;
		unsigned int conlen = 98;    //若字符串长度超标,则最多使用99个字符
		
		result.strvar[0] = 0;
		
		/* 查询本类strvar末尾下标 */
		for(int i = 0; i < 100; i++)
		{
			if(strvar[i] == 0)
			{
				strlen = i;
				break;
			}
		}
		
		/* 查询conobj末尾下标,只需查询99个字节 */
		for(int i = 0; i < 99; i++)
		{
			if(conobj[i] == 0)
			{
				conlen = i;
				break;
			}
		}
		
		/* 连接本类strvar */
		if(strlen != 0)
		{
			result = *this;
		}
		
		/* 连接conobj */
		if(conlen != 0)
		{
			for(int i = 0; strlen<99 && i<=conlen; i++)
			{
				result.strvar[strlen] = conobj[i];
				strlen++;
			}
			
			result.strvar[99] = 0;
		}
		
		return result;
	}
};
int main()
{
	string ali = {"阿狸"};
	string taozi = {"桃子"};
	string zoo = ali + taozi;      //调用ali.operator+函数,连接string对象
	printf("%s\n", zoo.strvar);
	
	zoo = zoo + "喜羊羊美羊羊";      //调用zoo.operator+函数,连接字符串
	printf("%s\n", zoo.strvar);
	
	return 0;
}


重载 = 符号

重载=符号修改动态长度字符串对象,字符串成员定义为私有,只能通过operator=符号函数修改。

#include <iostream>
#include <string.h>
class string
{
private:
	char * strvar;
	
public:
	string()
	{
		strvar = new char;
		*strvar = 0;
	}
	
	string(const char * assobj)
	{
		size_t asslen = strlen(assobj); 
		
		strvar = new char[asslen+1];
		strcpy(strvar, assobj);
		strvar[asslen+1] = 0;     //末尾空字符
	}
	
	~string()
	{
		delete [] strvar;
	}
	
	/* 返回字符串地址 */
	const char * get() const
	{
		return strvar;
	}
	
	void operator=(const char *assobj)
	{
		size_t asslen = strlen(assobj);
		
		/* 释放旧内存 */
		delete [] strvar;
		
		/* 申请新内存 */
		strvar = new char[asslen+1];
		
		/* 内存赋值 */
		strcpy(strvar, assobj);
		strvar[asslen+1] = 0;
	}
};

int main()
{
	string zoo("阿狸");
	printf("%s\n", zoo.get());
	
	zoo = "喜羊羊";
	printf("%s\n", zoo.get());
	
	return 0;
}


 

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

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

相关文章

免费的文案二次创作软件,打造高质量原创文案

在当今数字化时代&#xff0c;内容创作已经成为企业和个人推广自身品牌、产品和服务的重要手段。然而&#xff0c;对于许多人来说&#xff0c;撰写高质量的原创文案并非易事。幸运的是&#xff0c;随着技术的发展&#xff0c;出现了许多文案二次创作免费软件&#xff0c;为那些…

怎么做不限扫码次数的文件活码?文件可长期扫描展现下载

如何制作不限扫码次数的文件二维码呢&#xff1f;将文件转二维码后分享给其他人&#xff0c;是现在非常方便的一种文件传输方式。很多小伙伴在制作文件二维码的时候&#xff0c;比较担心的一个问题&#xff0c;就是二维码可以扫码的次数&#xff0c;担心达不到自己预期的效果&a…

保姆级讲解 Stable Diffusion

目录 本文讲解思路介绍 一、引入 二、Diffusion Model 三、原文的摘要和简介 四、Stable Diffusion 4.1、组成模块 4.2、感知压缩 4.3、条件控制 五、图解 Stable Diffusion 5.1、潜在空间的扩散 5.2、条件控制 5.3、采样 5.4、Diffusion Model 与 Stable Diffusion …

win11+wsl+ubuntu20.04+ros+x11+mobaxterm实现win11中ROS使用(含可视化)

前言 为实现在win11中使用ros… 一、win11中wsl(ubuntu20.04)安装 参考&#xff1a;Windows 11 安装 WSL2 主要步骤&#xff1a;开启虚拟化–>安装ubuntu20.04 安装后可能还是WSL1&#xff0c;可参考WSL1升级为WSL2进行升级。 二、使用鱼香ROS换源并更新 wget http://fishro…

【刷题记录】详谈设计循环队列

下题目为个人的刷题记录&#xff0c;在本节博客中我将详细谈论设计循环队列的思路&#xff0c;并给出代码&#xff0c;有需要借鉴即可。 题目&#xff1a;LINK 循环队列是线性表吗&#xff1f;或者说循环队列是线性结构吗&#xff1f; 对于这个问题&#xff0c;我们来看一下线…

Awesome-Backbones-main——alexnet模型分析

AlexNet作为骨干网络相对较老&#xff0c;可能在复杂数据集上的表现不如一些最新的深度网络结构&#xff0c;如ResNet、EfficientNet等&#xff0c;学习率调整策略中采用了阶梯式学习率更新器&#xff0c;可能并不总是适合所有数据集和模型&#xff0c;需要根据具体情况调整学习…

有名信号量、网络协议模型、UDP编程发送端

我要成为嵌入式高手之3月5日Linux高编第十五天&#xff01;&#xff01; ______________________________________________________ 学习笔记 有名信号量 1、创建semget #include <sys/types.h> #include <sys/ipc.h> #include <sys/sem.h> int semget(…

JVM 的垃圾回收机制以及垃圾回收算法的详解

目录 1、JVM 的垃圾回收机制 2、识别垃圾 2.1、引用计数 2.2、可达性分析 3、垃圾回收算法 3.1、标记-清除 3.2、复制算法 3.3、标记-整理 4、分代回收 1、JVM 的垃圾回收机制 对于&#xfeff;程序计数器&#xfeff;、&#xfeff;虚拟机栈&#xfeff;、&#xfe…

C if...else 语句

一个 if 语句 后可跟一个可选的 else 语句&#xff0c;else 语句在布尔表达式为 false 时执行。 语法 C 语言中 if…else 语句的语法&#xff1a; if(boolean_expression) {/* 如果布尔表达式为真将执行的语句 */ } else {/* 如果布尔表达式为假将执行的语句 */ }如果布尔表…

VMware Workstation17虚拟机安装

文章目录 一.下载安装软件二.安装过程选项三.序列化四.检查是否安装成功 一.下载安装软件 方式一&#xff1a;官网下载 方式二: 网盘下载(从官网里面下载的正版) 二.安装过程选项 双击下载的安装包&#xff0c;按以下图片选项进行安装 如果没有以下图片的"升级"选…

红队专题-开源漏扫-巡风xunfeng源码剖析与应用

开源漏扫-巡风xunfeng 介绍主体两部分:网络资产识别引擎,漏洞检测引擎。代码赏析插件编写JSON标示符Python脚本此外系统内嵌了辅助验证功能文件结构功能 模块添加IP三. 进行扫描在这里插入图片描述 ![在这里插入图片描述](https://img-blog.csdnimg.cn/direct/de587a6f6f694…

SpringCloudGateway工作原理与链路图

SpringCloudGateway基本介绍 Spring Cloud Gateway 构建于Spring Boot 2.x、 Spring WebFlux和Project Reactor之上。因此,在使用 Spring Cloud Gateway 时,您可能不会应用许多熟悉的同步库(例如 Spring Data 和 Spring Security)和模式。 Spring Cloud Gateway 需要 Sprin…

超好用的一键生成原创文案方法

在现代社会中&#xff0c;原创文案不管是在营销中&#xff0c;还是在品牌推广中都起着至关重要的作用。然而&#xff0c;对于许多人来说&#xff0c;创作出令人印象深刻且引人注目的原创文案并不容易。但随着技术的发展&#xff0c;我们现在可以利用一键生成原创文案的方法来帮…

(3)应用与信息

文章目录 前言 3.1 FlightDeck FrSky发射器应用程序 3.2 MAVLink2数据包签名(安全) 3.3 MAVLink高延迟协议 3.4 无线地面站连接中继器 1 概述 2 组件 3 设置 3.5 遥测无线电区域条例 3.6 用于OpenTX的Yaapu遥测脚本 前言 FlightDeck FrSky Transmitter AppMAVLink2 …

GitHub会员充值

GitHub是一个基于Web的代码托管平台&#xff0c;为开发者提供了协作、版本控制和代码管理的工具。它允许个人和团队共同协作开发软件项目&#xff0c;并提供了许多功能&#xff0c;使得代码的管理和维护更加容易 版本控制系统&#xff1a; GitHub使用Git作为其版本控制系统。Gi…

使用MATLAB快速对波形进行傅里叶分解到有限次谐波

使用MATLAB快速对波形进行傅里叶分解到有限次谐波 目录 使用MATLAB快速对波形进行傅里叶分解到有限次谐波1、解析表达式分解到有限次谐波1.1、理论分析1.2、全部代码 2、数值波形分解到有限次谐波2.1、基础理论2.2、对应代码 很多时候对功率放大器设计阻抗空间的分析都是从波形…

初阶数据结构之---二叉树的顺序结构-堆

引言 今天要讲的堆&#xff0c;不是操作系统虚拟进程地址空间中&#xff08;malloc&#xff0c;realloc等开空间的位置&#xff09;的那个堆&#xff0c;而是数据结构中的堆&#xff0c;它们虽然名字相同&#xff0c;却是截然不同的两个概念。堆的底层其实是完全二叉树&#x…

数据结构之队列详解(C语言手撕)

&#x1f389;个人名片&#xff1a; &#x1f43c;作者简介&#xff1a;一名乐于分享在学习道路上收获的大二在校生 &#x1f648;个人主页&#x1f389;&#xff1a;GOTXX &#x1f43c;个人WeChat&#xff1a;ILXOXVJE &#x1f43c;本文由GOTXX原创&#xff0c;首发CSDN&…

CorelDRAW Essentials2024使用简单易学的图形软件,让设计充满乐趣

CorelDRAW Essentials 2024使用简单易学的图形软件&#xff0c;让设计充满乐趣 创作引人注目的海报、卡片、社交媒体图片等。 增强功能&#xff01;支持文件导入/导出新增功能&#xff01;支持 WebP 文件&#xff0c;提高网页兼容性并优化图像交付增强功能&#xff01;显著的…

设计模式-行为型模式-中介者模式

中介者模式&#xff08;Mediator&#xff09;&#xff0c;用一个中介对象来封装一系列的对象交互。中介者使各对象不需要显式地相互引用&#xff0c;从而使其耦合松散&#xff0c;而且可以独立地改变它们之间的交互。[DP] 首先&#xff0c;我们定义一个Colleague接口&#xff0…