【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;
}

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

相关推荐
神仙别闹1 小时前
基于C语言实现的(控制台)校园导航系统
java·服务器·c语言
scoone1 小时前
C++中的原子操作:原子性、内存顺序、性能优化与原子变量赋值
开发语言·c++
轩情吖1 小时前
模拟实现Bash
linux·c语言·开发语言·c++·后端·bash·环境变量
vampire-wpre1 小时前
我要成为算法高手-递归篇
算法·深度优先
微尘81 小时前
C++条件编译指令:#if、#elif、#ifdef、#ifndef、#elifdef、#elifndef、#else、#endif
开发语言·c++
醒了就刷牙2 小时前
Leetcode 面试150题 88.合并两个有序数组 简单
算法·leetcode·面试
丶Darling.3 小时前
Day47 | 动态规划 :线性DP 最长公共子序列&&最长公共子数组
算法·动态规划
丶Darling.3 小时前
Day48 | 动态规划 :线性DP 编辑距离
算法·动态规划
In 20294 小时前
矩阵【Lecode_HOT100】
java·算法·矩阵
qystca4 小时前
洛谷 P1722 矩阵 II C语言 记忆化搜索
算法