【C++】——模板

news2024/12/25 0:13:48

目录

    • 泛型编程
    • 函数模板
      • 函数模板的概念
      • 函数模板格式:
      • 函数模板的原理
      • 函数模板的实例化
      • 模板参数的匹配原则
    • 类模板
      • 类模板定义格式
      • 类模板的实例化

泛型编程

泛型编程:编写与类型无关的通用代码,是代码复用的一种手段。模板是泛型编程的基础
引例:实现交换函数

void Swap(int& left, int& right)
{
	int temp = left;
	left = right;
	right = temp;
}
void Swap(double& left, double& right)
{
	double temp = left;
	left = right;
	right = temp;
}
void Swap(char& left, char& right)
{
	char temp = left;
	left = right;
	right = temp;
}

函数重载的缺点:
1、代码复用率低,只要有新的类型出现,就要增加相应的函数
2、代码的可维护性比较低,一个出错可能所有的重载均出错

函数模板

函数模板的概念

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

函数模板格式:

template <class T>
//template<typename T>
//template<typename T1,typename T2>
//返回值类型 函数名(参数列表){}

例:

template <class T>
//template<typename T>
//template<typename T1,typename T2>
void Swap(T& left, T& right)
{
	char temp = left;
	left = right;
	right = temp;
}
int main()
{
	int i = 10;
	int j = 2;
	double a = 2;
	double b = 3;
	cout << i <<" "<< j << endl;
	cout << a <<" "<< b << endl;
	Swap(i, j);
	Swap(b, a);
	cout << "------------------" << endl;;
	cout << i << " " << j << endl;
	cout << a << " " << b << endl;
	return 0;
}

注意:typename是用来定义模板参数关键字,也可以使用class,但是不能使用struct代替class

函数模板的原理

函数模板是一个蓝图,它本身并不是函数,是编译器用使用方式产生特定具体类型函数的模具。所以其实模板就是将本来应该我们做的重复的事情交给了编译器。

在这里插入图片描述

在编译器编译阶段,对于模板函数的使用,编译器需要根据传入的实参类型来推演生成对应类型的函数以供
调用。比如:当用double类型使用函数模板时,编译器通过对实参类型的推演,将T确定为double类型,然
后产生一份专门处理double类型的代码

函数模板的实例化

用不同类型的参数使用函数模板时,称为函数模板的实例化。模板参数实例化分为:隐式实例化和显式实例化。

隐式实例化:让编译器根据实参推演模板参数的实际类型

template<class T>
T Add(const T& left, const T& right)
{
	return left + right;
}
int main()
{
	int a1 = 10, a2 = 20;
	double d1 = 10.0, d2 = 20.0;
	Add(a1, a2);
	Add(d1, d2);
	Add(a2, (int)d2);//隐式转换(强转)
	return 0;
}

显式实例化:在函数名后的<>中指定模板参数的实际类型

template<class T>
T Add(const T& left, const T& right)
{
	return left + right;
}
int main(void)
{
	int a = 10;
	double b = 20.0;
	// 显式实例化
	Add<int>(a, b);
	return 0;
}

模板参数的匹配原则

一个非模板函数可以和一个同名的函数模板同时存在,而且该函数模板还可以被实例化为这个非模板函数

// 专门处理int的加法函数
int Add(int left, int right)
{
	return left + right;
}
// 通用加法函数模板
template<class T>
T Add(T left, T right)
{
	return left + right;
}
void Test()
{
	Add(1, 2); // 与非模板函数匹配,编译器不需要特化
	Add<int>(1, 2); // 调用编译器特化的Add版本
}

int main()
{
	Test();
	return 0;
}

在这里插入图片描述

对于非模板函数和同名函数模板,如果其他条件都相同,在调动时会优先调用非模板函数而不会从该模板产生出一个实例。如果模板可以产生一个具有更好匹配的函数, 那么将选择模板

// 专门处理int的加法函数
int Add(int left, int right)
{
	return left + right;
}
// 通用加法函数
template<class T1, class T2>
T1 Add(T1 left, T2 right)
{
	return left + right;
}
void Test()
{
	Add(1, 2); // 与非函数模板类型完全匹配,不需要函数模板实例化
	Add(1, 2.0); // 模板函数可以生成更加匹配的版本,编译器根据实参生成更加匹配的Add函数
}
int main()
{
	Test();
	return 0;
}

类模板

类模板定义格式

template<class T1, class T2, ..., class Tn>
class 类模板名
{
// 类内成员定义
};

用类模板实现栈:

template<class T>
class Stack
{
public:
	Stack(size_t capacity = 4)
	{
		_array = new T[capacity];
		_capacity = capacity;
		_size = 0;
	}
	void Push(T x)
	{
		_array[_size++] = x;
	}
	~Stack()
	{
		delete[] _array;
		_size = _capacity = 0;
	}
private:
	T* _array;
	size_t _size;
	size_t _capacity;
};
int main()
{
	Stack<int> st1;//类模板的实例化  类1存int
	Stack<double> st2;//类2存double
	return 0;
}

C++库中自动提供的模板swap

#include <iostream>
using namespace std;
int main()
{
	int x = 0;
	int y = 1;
	swap(x, y);
	double a = 1.1;
	double b = 2.2;
	swap(a, b);
}

在这里插入图片描述

类模板的实例化

类模板实例化与函数模板实例化不同,类模板实例化需要在类模板名字后跟<>,然后将实例化的类型放在<>中即可,类模板名字不是真正的类,而实例化的结果才是真正的类。

// Vector类名,Vector<int>才是类型
Vector<int> s1;
Vector<double> s2;

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

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

相关文章

并发——线程池实践

文章目录 1. 使用 ThreadPoolExecutor 的构造函数声明线程池2.监测线程池运行状态3.建议不同类别的业务用不同的线程池4.别忘记给线程池命名5.正确配置线程池参数常规操作美团的骚操作 简单总结一下我了解的使用线程池的时候应该注意的东西&#xff0c;网上似乎还没有专门写这…

带你了解科研院所

一、什么是科研院所 研究院是独立于教育部和高校系统之外的&#xff0c;以科研工作为业务核心的各级、各类研究机构。独立研究院有很多种&#xff0c;其中实力最强、名气最大、分布最广、数量最集中的是直属国务院的中科院、社科院两大科研系统中的各类研究所和研究中心。 两大…

大数据课程I1——Kafka的概述

文章作者邮箱&#xff1a;yugongshiyesina.cn 地址&#xff1a;广东惠州 ▲ 本章节目的 ⚪ 了解Kafka的概念&#xff1b; ⚪ 掌握Kafka的配置与启动&#xff1b; 一、简介 1. 基本概念 Apache kafka 是一个分布式数据流平台。可以从如下几个层面来理解&#x…

第十六章、【Linux】程序管理与SELinux初探

16.1 什么是程序 &#xff08;process&#xff09; 在Linux 系统当中&#xff1a;“触发任何一个事件时&#xff0c;系统都会将他定义成为一个程序&#xff0c;并且给予这个程序一个 ID &#xff0c;称为 PID&#xff0c;同时依据启发这个程序的使用者与相关属性关系&#xff…

Ubuntu18.04使用carla0.9.5联合仿真搭环境报错

Ubuntu18.04使用工程与carla0.9.5联合仿真报错 1 File "/home/cg/Auto_driving/src/ros-bridge/carla_ros_bridge/src/carla_ros_bridge/client.py", line 18, in <module>from carla_ros_bridge.bridge_with_rosbag import CarlaRosBridgeWithBagFile "…

04.利用Redis国逻辑过期实现缓存功能---解决缓存击穿

学习目标&#xff1a; 提示&#xff1a;学习如何利用Redis逻辑过期实现添加缓存功能解决缓存击穿 学习产出&#xff1a; 缓存击穿讲解图&#xff1a; 解决方案&#xff1a; 采用互斥锁采用逻辑过期 1. 准备pom环境 <dependency><groupId>org.springframework…

webpack 创建VUE项目

1、安装 node.js 下载地址&#xff1a;https://nodejs.org/en/ 下载完成以后点击安装&#xff0c;全部下一步即可 安装完成&#xff0c;输入命令验证 node -vnpm -v2.搭建VUE环境 输入命令&#xff0c;全局安装 npm install vue-cli -g安装完成后输入命令 查看 vue --ver…

算法篇之(Map Set)

前言&#xff1a;前面学习了List线性表的数组、链表数据结构&#xff0c;本篇博客主要学习和List相似的数据结构&#xff1a;Map和Set。 目录 思维导图 有效字母异位词 两数之和 思维导图 有效字母异位词 可以用哈希表实现 先创建哈希表&#xff0c; dic1{}对每个字符串进…

【C语言学习】条件运算符、逻辑运算、运算符优先级

一、条件运算符 条件&#xff1f;条件满足时的值&#xff1a;条件不满足时的值 count (count>20)?count-10:count10;等同于 if( count>20 )count count-10; elsecount count10; 优先级 条件运算符的优先级高于赋值运算符&#xff0c;但低于其他运算符。 尽量不要…

k8s 自身原理 2

前面我们说到 K8S 的基本原理和涉及的四大组件&#xff0c;分享了前两个组件 etcd 和 ApiServer 这一次我们接着分享一波&#xff1a; 调度器 scheduler控制器管理器 controller manager 调度器 scheduler 调度器&#xff0c;见名知意&#xff0c;用于调度 k8s 资源的&…

复现Cell图表:pyscenic分析之转录因子二项值热图

接上一节视频教程的分析结果(pyscenic分析&#xff1a;视频教程)。今天我们复现一篇cell子刊的图表&#xff0c;这篇文章有一副关于转录因子的图表&#xff0c;观察这个图有什么特点呢&#xff1f;第一是热图是二项值热图&#xff0c;只有0&#xff0c;1两个值&#xff0c;我们…

Rikka with Square Numbers 2023“钉耙编程”中国大学生算法设计超级联赛(8)hdu7370

Problem - 7370 题目大意&#xff1a;给出两个数a&#xff0c;b&#xff0c;每次操作可以使其中一个数加上或减去一个任意的完全平方数&#xff0c;问要使a&#xff0c;b相等需要的最少操作次数是多少 1<a,b<1e9,a!b 思路&#xff1a;我们可以将问题转化为将a和b的差w…

Qt 多线程、信号和槽连接方式推荐connect(Sender,Singnal,Receiver,Slot,ConnectMode);如下图所示

connect&#xff08;主线程A&#xff0c;信号A,子线程B,槽函数B,DirectConnection /AutoConnection ); connect&#xff08;子线B,信号B,主线程A,槽函数A,QueueConnection );

电脑连接安卓设备显示offline

The Android is offline. This can be resolved by physically disconnecting and...用USB线连接手机和电脑&#xff0c;打开cmd&#xff0c;输入adb devices -l, adb devices -l结果显示可以识别手机&#xff0c;但是状态为offline 打开另外一个终端&#xff0c;输入 adb k…

Java面向对象学习第三部分

一、Static修饰符 static是静态的意思&#xff0c;基本概念如下&#xff1a; Static分类&#xff1a; 一般我们分类都是按照是否使用static修饰进行分类。分为静态变量&#xff08;类变量&#xff09;、实例变量。 静态变量和实例变量的比较&#xff1a; 比较&#xff0c;…

(贪心) 剑指 Offer 14- I. 剪绳子 ——【Leetcode每日一题】

❓剑指 Offer 14- I. 剪绳子 难度&#xff1a;中等 给你一根长度为 n 的绳子&#xff0c;请把绳子剪成整数长度的 m 段&#xff08;m、n都是整数&#xff0c;n > 1 并且 m > 1&#xff09;&#xff0c;每段绳子的长度记为 k[0],k[1]...k[m-1] 。请问 k[0]*k[1]*...*k[m…

Python机器学习实战-建立AdaBoost模型预测肾脏疾病(附源码和实现效果)

实现功能 建立AdaBoost模型&#xff08;集成学习&#xff09;预测肾脏疾病 实现代码 import pandas as pd import warnings warnings.filterwarnings("ignore") pd.set_option(display.max_columns, 26)#读取数据 df pd.read_csv("E:\数据杂坛\datasets\kidn…

江南大学轴承数据故障诊断(利用一维CNN进行故障诊断,代码和数据放在压缩包,无需修改任何东西,解压缩后直接运行,有详细注释)

1.江南大学轴承数据集介绍 采样频率&#xff1a;50khz&#xff0c;采样时间&#xff1a;10s 转速&#xff1a;600 800 1000/rpm 内圈&#xff1a;ib 外圈&#xff1a;ob 滚动体&#xff1a;tb 正常&#xff1a;N 以600转速下的内圈故障数据为例展示&#xff1a; 开始数据…

内网穿透实战应用-配置固定的远程桌面地址【内网穿透、无需公网IP】

配置固定的远程桌面地址【内网穿透、无需公网IP】 文章目录 配置固定的远程桌面地址【内网穿透、无需公网IP】第一步&#xff1a;保留TCP地址第二步&#xff1a;为远程桌面隧道配置固定的TCP地址第三步&#xff1a;使用固定TCP地址远程桌面 使用免费的cpolar生成的远程桌面公网…

STM32 定时器自动重装载寄存器ARR带来的影响,ARPE0和1区别

ARR是啥 自动重载寄存器是预装载的。对自动重载寄存器执行写入或读取操作时会访问预装载寄存器。预装载寄存器的内容既可以直接传送到影子寄存器&#xff0c;也可以在每次发生更新事件 (UEV) 时传送到影子寄存器&#xff0c;这取决于 TIMx_CR1 寄存器中的自动重载预装载使能位 …