【C++】——初识模版

文章目录

前言

当我们使用一个通用的函数:

cpp 复制代码
//为每一个类型都编写一个重载版本
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;
}

这种方法的缺点是显而易见的:随着需要交换的类型的增加,你需要不断地编写新的重载函数。这不仅繁琐,而且不灵活,因为它不能自动适应未来可能出现的新类型。

函数模板提供了一种更加灵活和通用的解决方案。你可以定义一个模板函数,该函数可以接受任意类型的参数,并在编译时根据传入的参数类型生成相应的函数版本。

函数模版

函数模版的格式:

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

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

cpp 复制代码
//函数模版
template<class T>
void Swap(T& m, T& n)
{
	T tmp = m;
	m = n;
	n = tmp;
}

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

cpp 复制代码
template<typename T>
void Swap(T& m, T& n)
{
	T temp = m;
	m = n;
	n = temp;
}
cpp 复制代码
template<class T>
void Swap(T& m, T& n)
{
	T tmp = m;
	m = n;
	n = tmp;
}
int main()
{
	int i = 1, j = 2;
	double x = 1.1, y = 2.2;
	Swap(i, j);
	Swap(x, y);
	//Swap(i, x); 函数模版不能传不同类型的参数
	return 0;
}

函数模版的原理

函数模版本身并不是函数,模版只是将我们做的事重复的事交给了编译器

函数模版的实例化

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

这里就是要解决这个问题

有两种处理方式

  1. 强制类型转换
  2. 使用显式实例化
cpp 复制代码
template<class T>
void Swap(const T& m, const T& n)
{
	T tmp = m;
	m = n;
	n = tmp;
}
int main()
{
	int i = 1, j = 2;
	double x = 1.1, y = 2.2;
	//推导实例化(自己动手强转)
	Swap(i, (int)x);
	Swap((double)i, x);
	//显示实例化
	Swap<int>(i, x);
	return 0;
}

如果我就要用 Swap(i,x) 来实现呢?

cpp 复制代码
template<class T1,class T2>
T1 Swap(const T1& m, const T2& n)
{
	T1 tmp = m;
	m = n;
	n = tmp;
}

有种场景我们必须用显示实例化:

cpp 复制代码
template<class T>
T* func1(int n)
{
	return new T[n];
}
int main()
{
	//func1(10); 编译器无法推导出类型
	int* p = func1<int>(10);
	return 0;
}

如果函数和模板同时存在,会先调用函数

cpp 复制代码
template<class T>
T ADD(const T& left, const T& right)
{
	return left + right;
}
int ADD(const int& x, const int& y)
{
	return (x + y) * 10;
}
int main()
{
	int a = 5;
	int b = 10;
	cout<<ADD(a, b)<<endl;

	return 0;
}

类模版

类模版的格式:

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

类模版实现栈

cpp 复制代码
template<class T>
class Stack
{
public:
	Stack(int n = 4)
		:_arr(new T[n])
		,_size(0)
		,_capacity(n)
	{}
	~Stack()
	{
		delete[] _arr;
		_arr = nullptr;
		_size = _capacity = 0;
	}
	void Push(const T& x)
	{
		if (_size == _capacity)
		{
			T* tmp = new T[_capacity * 2];
			memcpy(tmp, _arr, sizeof(T) * _size);
			delete[] _arr;
			_arr = tmp;
			_capacity *= 2;
		}
		_arr[_size++] = x;
	}
	//...
private:
	T* _arr;
	int _size;
	int _capacity;
};

将栈的所有数据和方法封装在类内部,所以只有类成员函数才可以访问(最好不要类里声明,类外定义,除非在类外使用template<>语法来指明你正在定义的是哪个模板参数的成员函数),而且,通过类模版,不同的类型都可以实现栈,安全性也得到了提升。

cpp 复制代码
template<class T>
void Stack<T>::Push(const T& x)
{
	if (_size == _capacity)
	{
		T* tmp = new T[_capacity * 2];
		memcpy(tmp, _arr, sizeof(T) * _size);
		delete[] _arr;
		_arr = tmp;
		_capacity *= 2;
	}
	_arr[_size++] = x;
}

类模版的实例化

类模版只能使用显示实例化

cpp 复制代码
int main()
{
	Stack<int>str1;
	str1.Push(1);
	str1.Push(2);
	str1.Push(3);

	Stack<double>str2;
	str2.Push(1.1);
	str2.Push(2.2);
	str2.Push(3.3);
	return 0;
}

希望这篇博客对你有所帮助!!!

相关推荐
地平线开发者18 分钟前
SparseDrive 模型导出与性能优化实战
算法·自动驾驶
董董灿是个攻城狮43 分钟前
大模型连载2:初步认识 tokenizer 的过程
算法
地平线开发者1 小时前
地平线 VP 接口工程实践(一):hbVPRoiResize 接口功能、使用约束与典型问题总结
算法·自动驾驶
罗西的思考1 小时前
AI Agent框架探秘:拆解 OpenHands(10)--- Runtime
人工智能·算法·机器学习
HXhlx5 小时前
CART决策树基本原理
算法·机器学习
Wect5 小时前
LeetCode 210. 课程表 II 题解:Kahn算法+DFS 双解法精讲
前端·算法·typescript
颜酱6 小时前
单调队列:滑动窗口极值问题的最优解(通用模板版)
javascript·后端·算法
肆忆_8 小时前
# 用 5 个问题学懂 C++ 虚函数(入门级)
c++
不想写代码的星星12 小时前
虚函数表:C++ 多态背后的那个男人
c++
Gorway12 小时前
解析残差网络 (ResNet)
算法