C++模板

模板初阶
如何实现一个通用的加法函数?我们可以类似这样使用函数重载的方法进行编写
int sum(int& a, int& b)
{
	return a + b;
}

double sum(double& a, double& b)
{
	return a + b;
}
使用函数重载虽然可以实现,但是有一下几个不好的地方:
1. 重载的函数仅仅是类型不同,代码复用率比较低,只要有新类型出现时,就需要用户自己增
加对应的函数
2. 代码的可维护性比较低,一个出错可能所有的重载均出错
那能否 告诉编译器一个模子,让编译器根据不同的类型利用该模子来生成代码 呢?答案是肯定的。
函数模板
    函数模板概念
函数模板代表了一个函数家族,该函数模板与类型无关,在使用时被参数化,根据实参类型产生
函数的特定类型版本。
    函数模板格式
template<typename T1, typename T2,......,typename Tn>
返回值类型 函数名 ( 参数列表 ){}
#include<iostream>
using namespace std;

//int sum(int& a, int& b)
//{
//	return a + b;
//}
//
//double sum(double& a, double& b)
//{
//	return a + b;
//}

template<typename T>
T sum(T& a, T& b)
{
	return a + b;
}

int main()
{
	int a = 1;
	int b = 2;
	cout << "a+b="<<sum(a, b) << endl;

	double c = 1.0;
	double d = 2.1;
	cout << "d+c=" << sum(d, c) << endl;



	return 0;

}

运行结果很明显这个模板是能够完成这种泛型编程的操作

注意: typename 用来定义模板参数 关键字 也可以使用 class( 切记:不能使用 struct 代替
class)
函数模板的原理
函数模板是一个蓝图,它本身并不是函数,是编译器用使用方式产生特定具体类型函数的模具。
所以其实模板就是将本来应该我们做的重复的事情交给了编译器
函数模板的实例化
用不同类型的参数使用函数模板时 ,称为函数模板的 实例化 。模板参数实例化分为: 隐式实例化
和显式实例化
隐式实例化:让编译器根据实参推演模板参数的实际类型,就如同上述代码一样编译器会自动推导输入的参数是什么类型的进行匹配,但是如果这样就无法正确匹配会导致编译不通过

这是因为模板中只有一个T无法变成两种类型,此时有两种处理方式:1.用户自己来强制转化2.使用显式实例化

template<typename T>
T sum(const T& a,const T& b)
{
	return a + b;
}

int main()
{
	int a = 1;
	int b = 2;
	cout << "a+b"<<sum(a, b) << endl;

	double c = 1.0;
	double d = 2.1;
	cout << "d+c" << sum(d, c) << endl;

	sum(a, int(c));//将c转换类型以后是常量,需要用const缩小权限
	cout << "a+c" << sum(a, int(c)) << endl;
	return 0;

}

运行结果

还有另外一种方法就是显式实例化,显式实例化:在函数名后的<>中指定模板参数的实际类型

模板参数的匹配原则
  一个非模板函数可以和一个同名的函数模板同时存在,而且该函数模板还可以被实例化为这个非模板函数, 模板函数不允许自动类型转换,但普通函数可以进行自动类型转换
  类模板的定义格式
template < class T1 , class T2 , ..., class Tn >
class 类模板名
{
// 类内成员定义
};
/#include<iostream>
using namespace std;
// 类模版
template<typename T>
class Stack
{
public:
Stack(size_t capacity = 4)
{
_array = new T[capacity];
_capacity = capacity;
_size = 0;
}
void Push(const T& data);
private:
T* _array;
size_t _capacity;
size_t _size;
};
// 模版不建议声明和定义分离到两个文件.h 和.cpp会出现链接错误,具体原因后面会讲
template<class T>
void Stack<T>::Push(const T& data)
{
// 扩容
_array[_size] = data;
++_size;
}
int main()
{
Stack<int> st1; // int
Stack<double> st2; // double
return 0;
}
类模板的实例化
类模板实例化与函数模板实例化不同, 类模板实例化需要在类模板名字后跟 <> ,然后将实例化的
类型放在 <> 中即可,类模板名字不是真正的类,而实例化的结果才是真正的类
// Stack是类名,Stack<int>才是类型
Stack<int> st1; // int
Stack<double> st2; // double

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值