C++模板初阶,只需稍微学习;直接起飞;泛型编程

news2025/1/16 12:50:38

🤓泛型编程

  1. 假设像以前交换两个函数需要,函数写很多个或者要重载很多个;那么有什么办法实现一个通用的函数呢?
void Swap(int& x, int& y)
{
	int tmp = x;
	x = y;
	y = tmp;
}
void Swap(double& x, double& y)
{
	double tmp = x;
	x = y;
	y = tmp;
}
void Swap(char& x, char& y)
{
	char tmp = x;
	x = y;
	y = tmp;
}
  1. 虽然函数重载可以实现,但是总归不太好
    1. 可以发现函数重载虽然可以使用同一个函数名,避免不了复用率比较低,假如有新的类型 还是需要再写对应类型函数
    2. 函数多了可维护性就会变差,一个出错可能其他的重载都会有问题
  2. 所以下面就用到了一个函数模板的,解决这个问题

泛型编程:编写与类型无关通用的代码,是代码复用的一种手段,模板是泛型编程的基础

🤓函数模板

概念:函数模板代表一个函数家族,该函数与类型无关,在使用时被参数化,根据实参类型产生函数的特定版本类型

☝️ 函数模板格式

template<typename T1,typename T2,...,typename Tn>

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

注意:typename是用来定义模板参数的关键字还可以写成class(但是不可以写成struct,不能使用struct来代替)

☝️ 函数模板的原理

  1. 函数模板是一个蓝图,本身就不是一个函数,编译器使用了某种方式产生特定具体类型函数的模具,所以本来需要写很多次函数重载的活或者其他重复的事情都交给了编译器
  2. 在编译器编译阶段,对于模板的使用,编译器需要根据传过来的实参类型来推导生成对应函数类型,提供调用;如int类型的实参使用函数模板时,编译器通过对应类型推演,推导出T类型是int类型,从而产生一份专门处理int类型的函数,对于double类型也是这样的;

虽然编译器麻烦一点,但是我们就可以少写一些了,岂不美哉

☝️ 函数模板的实例化

  1. 不同的类型使用函数模板时,这个过程称之为函数模板的实例化,函数模板的实例化分为两种:隐式实例化显式实例化
  2. 隐式模板实例化:通过传递的实参类型推导出对应函数的实际类型
template <class T>
void Swap(T& x, T& y)
{
	T tmp = x;
	x = y;
	y = tmp;
}

template <typename Type1,typename Type2>
void fun(Type1& x,Type2& y)
{

}
int main()
{
	int x1 = 10,x2 = 20;
	double y1 = 10.1,y2 = 20.1;
	Swap(x1, x2);
	Swap(y1, y2);
	//Swap(x1, y1); 这样就不行了,函数模板只写了一个T的关键字,必须是同一个类型
	cout << y1 << " " << y2 << endl;

	//C++自带的swap函数
	swap(x1, x2);
	swap(y1, y2);

	//如果两个参数不同,就需要有两个关键字
	fun(x1, y1);
	return 0;
}
  1. 显示实例化:
#include <iostream>
using namespace std;
template<class T>
T Add(const T& x, const T& y)//这里需要写const 不然不能使用强制转换
{
	return x + y;
}

//可以写多个函数模板;如果不想强制转换和显示实例化可以写两个关键字的 
template<class T1,class T2>
T1 Add(T1& num1, T2& num2)
{
	return num1 + num2;
}

template<class N>
N* apply(int x)//没有传入的实参类型,意思是的位置没有用到 N 推导不了
{
	N* tmp = new N[x];//N 用做了类型参数
	return tmp;
}


int main()
{
	int su1 = 10, su2 = 20;
	double xu1 = 10.2, xu2 = 20.2;

	Add(su1, su2);
	Add(xu1, xu2);

	//隐式实例化; 强制类型转换
	cout << Add(su1,(int)xu1) << endl;
	cout << Add((double)su1,xu1) << endl;

	//显示实例化,直接告诉 T 的类型,编译器不需要推导了
	cout << Add<double>(su1,xu1)<< endl;//这里的su1 会有隐式类型转换
	cout << Add<int>(su1,xu1) << endl;

	cout << Add(su2, xu2) << endl;

	//这里必须显示写实例化
	double* space = apply<double>(20);


	//隐式类型转换不是想转就能转的,比如:指针,一般都是和int相关的类型
	char a = 'b';
	int ia = 2100;
	cout << (int)a << endl;
	cout << (char)ia << endl;
	return 0;
}
  1. 编译器一般不会自己进行隐式类型转换,怕出事
  2. 函数模板实例化,如果其他条件相同的情况下,会优先调用非模板函数;如果模板函数实例化出更好的,那么会选择模板;所以说什么好选择什么
  3. 函数模板对自定义类型不能隐式类型转换,对于普通的类型会自动隐式类型转换
#include <iostream>
using namespace std;
int Add(const int& x,const int& y) //这里优先调用
{
	return 20 * (x + y);
}

template<class T>
T Add(const T& x, const T& y)//这里需要写const 不然不能使用强制转换
{
	return x + y;
}
int main()
{
	int su1 = 10, su2 = 20;
	Add(su1, su2);    
}

🤓类模板

☝️ 类模板的定义格式

template<class T1, class T2, ..., class Tn> 
class 类模板名
{
 // 类内成员定义
}; 
#include <iostream>
using namespace std;

template<typename T>
class Stack
{
public:
	Stack(int n = 4)
		:_array(new T[n])// T 就是代表的是模板实例化的类型
		, _size(0)
		, _capacity(n)
	{

	}
	void Push(const T& p);
	~Stack()
	{
		delete[] _array;
		_array = nullptr;
		_size = _capacity = 0;
	}
private:
	T* _array;
	size_t _size;
	size_t _capacity;
};

template<typename T> //如果是声明和定义分离 就需要再写一个类模板
void Stack<T>::Push(const T& p)//告诉类中模板类型是什么
{
	if (_size == _capacity)
	{
		T* tmp = new Stack[_capacity * 2];
		memcpy(tmp, _array, sizeof(T) * _size);//拷贝内容
		delete[] _array;//释放旧空间
		_array = tmp;
		_capacity = _capacity * 2;
	}
	_array[_size++] = p;
}

int main()
{
	Stack<int> a1;
	return 0;
}
  1. 模板的定义和声明不建议放到两个不同的文件 .h 和 .cpp;会出现链接错误

☝️ 类模板的实例化

  1. 模板类是需要显示实例化的
  2. 和函数模板实例化不同,类模板的名字不是真正的类,而实例化的结果才是真正的类
int main()
{
	// Stack 是类名,Stack<int> 是类型
	Stack<int> a1;
	Stack<double> a2;
	return 0;
}

頑張ろ

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

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

相关文章

胤娲科技:AI短视频——创意无界,即梦启航

在这个快节奏的时代&#xff0c;你是否曾梦想过用几秒钟的短视频&#xff0c;捕捉生活中的每一个精彩瞬间&#xff1f;是否曾幻想过&#xff0c;即使没有专业的摄影和剪辑技能&#xff0c;也能创作出令人惊艳的作品&#xff1f; 现在&#xff0c;这一切都不再是遥不可及的梦想。…

微前端学习以及分享

微前端学习以及分享 注&#xff1a;本次分享demo的源码github地址&#xff1a;https://github.com/rondout/micro-frontend 什么是微前端 微前端的概念是由ThoughtWorks在2016年提出的&#xff0c;它借鉴了微服务的架构理念&#xff0c;核心在于将一个庞大的前端应用拆分成多…

从MySQL到OceanBase离线数据迁移的实践

本文作者&#xff1a;玉璁&#xff0c;OceanBase 生态产品技术专家。工作十余年&#xff0c;一直在基础架构与中间件领域从事研发工作。现负责OceanBase离线导数产品工具的研发工作&#xff0c;致力于为 OceanBase 建设一套完善的生态工具体系。 背景介绍 在互联网与云数据库技…

LEAP 瞬移工具场景试点游戏关卡

你是否厌倦了在Unity编辑器中浪费时间浏览大型游戏关卡&#xff1f;不要看得比Leap更远&#xff01;这个功能强大的编辑器脚本允许您只需单击一下即可即时传输到场景中的任何位置。告别繁琐的手动导航&#xff0c;迎接闪电般快速的关卡设计。有了Leap&#xff0c;你就可以专注于…

Gin框架官方文档详解04:HTTP/2 推送,JSON相关

官方文档&#xff1a;https://gin-gonic.com/zh-cn/docs/ 注&#xff1a;强烈建议没用过Gin的读者先阅读第一节&#xff1a;第一个Gin应用。 目录 一、HTTP/2 推送二、JSONP三、PureJSON四、SecureJSON五、总结 一、HTTP/2 推送 首先&#xff0c;以“04HTTP2server推送”为根目…

linux 时区问题

一、修改系统时间和时区 查看当前下系统时间和时区 timedatectl设置系统时区 ​sudo timedatectl set-timezone <时区>​&#xff0c;例如&#xff1a; sudo timedatectl set-timezone Asia/Shanghai执行成功则没有输出。 更推荐使用 tzselect​ ​命令&#xff0c;…

通信工程学习:什么是VHDL超高速集成电路硬件描述语言

VHDL&#xff1a;超高速集成电路硬件描述语言 VHDL&#xff0c;全称为Very-High-Speed Integrated Circuit Hardware Description Language&#xff0c;即超高速集成电路硬件描述语言&#xff0c;是一种用于电路设计的高级语言。以下是关于VHDL的详细介绍&#xff1a; 一、起源…

ThingsBoard规则链节点:Split Array Msg节点详解

引言 拆分数组消息节点简介 用法 含义 应用场景 实际项目运用示例 智能仓储管理系统 智能电网监控系统 车联网平台 结论 引言 ThingsBoard是一个功能强大的物联网平台&#xff0c;它提供了设备管理、数据收集与处理以及实时监控等核心功能。其规则引擎允许用户定义复杂…

时序图分析(IIC通信为例)

一、时序图分析&#xff08;IIC通信为例&#xff09; 时序图-->编程 解析&#xff1a;时序概念&#xff1a;一般指可编程器件的编程方法&#xff0c;在单片机编程时&#xff0c;需要根据被控芯片的时序去写程序&#xff0c;把芯片上的时序用代码来实现&#xff0c;方可实…

数据结构4——栈

1. 栈的概念及结构 栈的概念&#xff1a; 栈是一种特殊的线性表&#xff0c;其只允许在固定的一端进行插入和删除元素操作。进行数据插入和删除操作的一端称为栈顶&#xff0c;另一端称为栈底。栈中的数据元素遵守后进先出LIFO&#xff08;Last In First Out&#xff09;的原则…

<Linux> 线程池

一、线程池 1. 池化技术 池化技术是一种在计算机科学中广泛应用的优化技术&#xff0c;它的核心思想是&#xff1a;预先创建并维护一组资源&#xff08;例如线程、连接、对象&#xff09;&#xff0c;供多个任务共享使用&#xff0c;以减少创建和销毁资源的开销&#xff0c;提…

贪吃蛇游戏(代码篇)

我们并不是为了满足别人的期待而活着。 前言 这是我自己做的第五个小项目---贪吃蛇游戏&#xff08;代码篇&#xff09;。后期我会继续制作其他小项目并开源至博客上。 上一小项目是贪吃蛇游戏&#xff08;必备知识篇&#xff09;&#xff0c;没看过的同学可以去看看&#xf…

使用Java API访问Apache Kafka

简介 Kafka是由Apache软件基金会开发的一个开源流处理平台,Kafka是一个功能强大且灵活的平台。 基本情况 软件名称:Apache Kafka 软件平台:跨平台 软件语言:Scala、Java 开发商:Apache软件基金会 软件授权:Apache License 2.0 最近更新时间:2024年7月23日 核心概念 -…

Ubuntu:用户不在sudoers文件中

1、问题 执行sudo xxx命令时&#xff0c;显示&#xff1a; user 不在sudoers文件中 需要查看系统版本进入恢复模式修复。 2、重启进入恢复模式 查看系统命令&#xff1a;uname -r 可能显示为&#xff1a;6.8.0-45-generic 重启Ubuntu系统&#xff0c;在开机时按ESC进入模…

oracle归档日志爆满问题处理

最近客户单位的oracle数据库出了问题&#xff0c;经常出现无法连接,报错提示 ORA-00257: archiver error, Connect internal only, until freed.&#xff0c;手动清除归档日志后可以恢复访问&#xff0c;但是过不了几天依旧会爆满&#xff0c;每日生成的归档日志很大。经过详细…

内部排序算法小结

练习目标&#xff1a; 1、实现 直接插入排序、冒泡排序、SHELL排序和快速排序&#xff1b; 2、随机生成100组数据&#xff0c;每组数据1000个元素。 注意&#xff1a;计时的单位是CPU的clock而非时间&#xff01;&#xff01;&#xff01; 【后续】 1、加入选择排序&#xff1b…

读书笔记《PPT演讲力》大树模型

作者把PPT演讲比作一棵大树&#xff0c;树的每一部分对应着PPT演讲的一个技巧。 根据这个大树模型&#xff0c;是否有联想到自己过往的演讲经历&#xff1f;演讲是否都达到了大树模型中说的效果&#xff1f;根据这个思维导图&#xff0c;结合自己的经历&#xff0c;试着总结3句…

云计算第四阶段-----CLOUND二周目 04-06

cloud 04 今日目标&#xff1a; 一、Pod 生命周期 图解&#xff1a; [rootmaster ~]# vim web1.yaml --- kind: Pod apiVersion: v1 metadata:name: web1 spec:initContainers: # 定义初始化任务- name: task1 # 如果初始化任务失败&#…

数字化与数智化,你知道它们的区别吗?

​其实老早就想说这个。中间一直在忙忙忙&#xff0c;还有处理自己的事情&#xff0c;导致拖更了。 最近听说一个物流大佬现在也转行做数字化厂家负责人&#xff0c;顺便给我讲解了这二者的区别&#xff0c;这里我就重新梳理了一下&#xff0c;加上了我自己的一些观点&#xf…

qt creator 开发环境的安装

1.找官网 官网地址&#xff1a;Installation | Qt Creator Documentation 点 Parent Directory 继续点 Parent Directory 点 archive/ 2.下载在线安装器 点 online_ainstallers 选择在线安装器版本 选择对应版本后进入下载列表&#xff0c;根据自己的系统选择下载。 下载后…