[C++](8)模板的初步了解

泛型编程

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

为了支持各种类型的两个数据的交换,我们不得不写出多个函数。比如之前写的swap函数:

void Swap(int& a, int& b)
{
	int tmp = a;
	a = b;
	b = tmp;
}
void Swap(double& a, double& b)
{
	double tmp = a;
	a = b;
	b = tmp;
}
void Swap(char& a, char& b)
{
	char tmp = a;
	a = b;
	b = tmp;
}

它们构成函数重载,但是代码复用率低,一旦出现新的类型,就需要用户自己添加相应的函数。代码维护性低,一但发现错误,所有函数都要一起改。

我们能否只写一个函数模板,需要什么类型的函数直接让编译器自己往里面填好了生成出来呢?

答案是可以的,我们称这种方法叫泛型编程

函数模板

模板是泛型编程的基础,要用到的关键字:template

函数模板的定义

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

👆:typename也可以写成class,当前的角度,用这两个关键字没有区别,T模板参数,是我们定义函数模板要用的类型名,可以自己随别取

例1:

template<typename T>
void Swap(T& a, T& b)
{
	T tmp = a;
	a = b;
	b = tmp;
}

模板的声明必须带上模板参数:

//例1的声明:
template<typename T>
void Swap(T& a, T& b)

模板不支持声明和定义分离到两个文件。一般是要放到一个文件中,有些地方会把文件命名成xxx.hpp,寓意头文件和定义实现内容合并在一起。

函数模板的实例化

调用Swap函数:

img

👆:传入不同类型的参数,编译器会按照模板生成不同的函数来调用。

另外,C++库里面有swap函数,我们以后也不用自己实现了


函数模板显式实例化

如果你写得函数模板无法通过传参来推导类型,就必须手动指定:

调用时在函数模板名后面跟<><>内是我们自己指定的类型。

template<typename T>
T* func(int c) //无法通过传参推导T的类型
{
	return newT[n];
}
int main()
{
	int* p1 = func<int>(10);
	double* p2 = func<double>(10);
	return 0;
}

再看下面的例子:

template<class T>
T Add(const T& a, const T& b)
{
	return a + b;
}
int main()
{
	int a = 10;
	double d = 9.8;
	Add(a, d);//此处报错:没有与参数列表匹配的 函数模板 "Add" 实例
	return 0;
}

👆:传入的两个参数的类型不同,T的类型无法确认,此时也可以手动指定成Add<int>(a, d);Add<double>(a, d);,这样程序就能运行了,传参的时候会进行强制类型转换。

模板参数的匹配原则

int Add(int a, int b) //专门处理int类型的函数
{
	return a + b;
}

template<class T> //通用的函数模板
T Add(const T& a, const T& b)
{
	return a + b;
}

int main()
{
	int a = 1, b = 2;
	Add(a, b);
	return 0;
}

传入int类型的数据,会优先调用哪个函数呢?

通过调试发现,编译器调用的是专门处理int类型的函数,而没有去用模板实例化生成的。

如果手动指定类型Add<int>(a, b);那么一定是调用函数模板实例化生成的。

类模板

类模板的定义

template<class T1, class T2, ..., class Tn>
class 类模板名
{

};

例:

template<class T>
class Stack
{
public:
	Stack(int capacity = 0)
	{
		_a = new T[capacity];
		_capacity = capacity;
		_top = 0;
	}
	~Stack()
	{
		delete[] _a;
		_capacity = 0;
		_top = 0;
	}
	//...
private:
	T* _a;
	int _top;
	int _capacity;
};

类模板是实例化

类不像函数,函数模板可以根据传参去推导要替换的类型,而类模板没有。

类模板的实例化需要在类模板名后面跟<><>内的是我们自己指定的类型。

int main()
{
	Stack<int> st1;
	Stack<double> st2;
	return 0;
}

模板参数也支持给缺省参数,比如template<class T = char>,这样如果不指定类型就默认是char类型

  • 4
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 5
    评论
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

世真

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值