初识C++中的模板

当我们写交换两个变量内容的函数时,虽然有函数重载,但函数内容基本上都一样,这样显得有些麻烦了。C++ 中就提供了解决该问题的方法------模板。

泛型编程

泛型编程指的是编写与类型无关的通用代码,不指定具体数据类型,等到使用时再确定其类型。

泛型编程出现的意义就在于,使一段代码可以适配多种不同类型的数据,让我们不用重复写多个同样的代码。比如说对于不同类型数据的 Swap 交换函数,C++ 中就是靠模板来实现的。## 函数模板

函数模板定义的是一类函数,这类函数与参数类型无关,只有在特定情况下才会产生对应的函数。

一个函数模板定义的方式如下:template <typename 类型名(自定)>,其中类型的名称我们可以自己命名,通常是 T。

比如说我们定义函数 Swap 的函数模板:

cpp 复制代码
//函数模板
template <typename T>
void Swap(T& left, T& right)
{
	T tmp = left;
	left = right;
	right = tmp;
}

这就是一个函数模板了,当我们显式调用它或者传参调用该函数时,编译器才会根据该函数模板生成对应的函数。该过程就称为函数模板的实例化。

cpp 复制代码
int main()
{
  int x1 = 1,x2 = 2;
	//显式实例化
	//函数名后跟<>,内写类型
	//显式实例化的时候就调用该函数
	Swap<int>(x1, x2);

	double d1 = 3.14, d2 = 5.12;
	//隐式实例化
	Swap(d1, d2);

	return 0;
}

这是正常情况下,如果我们传过去的一个是 int 型,一个是 double 型,那么在类型匹配上都会产生冲突,第一个 T 匹配的是 int,第二个 T 变成了 double,产生了冲突,这时分两种情况:

  • 如果是隐式实例化,此时编译器就会报错,不会进入实例化阶段。
  • 如果我们已经显式实例化出了一个函数(如上),然后在显式实例化时就调用该函数(反之报错),编译器在传参时就会帮我们进行类型转换(double 转为 int),再调用这个函数。

函数调用优先级

如果我们已经定义了一个 Swap 函数,假设就是 int 类型,然后我们显式实例化出了一个 int 型的 Swap 函数,那么编译器会先调用哪个函数呢?

cpp 复制代码
void Swap(int& left, int& right)
{
	int tmp = left + 3;//做点区别
	left = right;
	right = tmp;
}

//函数模板
template <typename T>
void Swap(T& left, T& right)
{
	T tmp = left;
	left = right;
	right = tmp;
}

int main()
{

	int x1 = 1, x2 = 2;
	Swap<int>;
	Swap(x1, x2);
	cout<< x1 << ' ' << x2 << endl;
	return 0;
}

可以看到调用的是我们自己定义的函数,如果模板函数更匹配,编译器则会去调用模板函数。## 类模板

类模板的定义格式如下:template <class T>

比如说我们想定义不同的 Stack 类来存储不同类型的数据:

cpp 复制代码
//类模板
template <class T>
class Stack
{
public:
	Stack(int n = 4)
		:_array(new T[n])
		, _top(0)
		, _capacity(n)
	{

	}
	void Push(T& x)
	{
		_array[_top++] = x;
	}
	~Stack()
	{
	delete[] _array;
	}
private:
	T* _array;
	int _top;
	int _capacity;
};

然后我们就可以生成不同的 Stack 类,存储不同类型的数据了。

cpp 复制代码
int main()
{
	Stack<int> s1;
	Stack<char> s2;
	Stack<double> s3;
//这三个对象是不同的类型
	return 0;
}
相关推荐
天天被压力19 分钟前
【A股分钟级高频数据完全手册 #04】指数分钟级行情数据接口:沪深指数Pro版最新分时取数
java·人工智能·python
敲代码的小小酥22 分钟前
谈SpringMVC与Spring WebFlux的区别与适用场景
java·后端·spring
天天被压力28 分钟前
【A股分钟级高频数据完全手册 #03】股票历史1分钟K线数据接口怎么用:Pro版批量拉取与本地缓存
java·人工智能·python
zhanghaha131430 分钟前
C# 系列教程_7 判断语句(分支)保姆级精讲
开发语言·c#
apcipot_rain35 分钟前
C++转Java日记(02)
java·开发语言·c++
nice_lcj52043 分钟前
【从零理解 Spring AI · 03】Spring AI 在 Spring 生态里的位置
java·spring boot·大模型·spring ai·ai应用开发
杜 硕1 小时前
从零开始的C++生活——第七讲——02
开发语言·c++·生活
zhanghaha13141 小时前
C# 系列教程_8 循环语句 保姆级精讲(面向新手)
开发语言·c#
Rabitebla9 小时前
【Linux 底层原理】进程(十):进程等待详解---从僵尸进程到 wait、waitpid 与 status
linux·c++·笔记·学习·visual studio
麦麦麦当劳大王9 小时前
【油猴脚本】Boss直聘 岗位职责复制
开发语言·前端·javascript