C++模板初阶

泛型编程

通过前面的学习,我们知道要实现多种类型的两个数的加法必然要用到函数的重载

int add(int x, int y)
{
	return x + y;
}

double add(double x, double y)
{
	return x + y;
}

char add(char x, char y)
{
	return x + y;
}

但是这样对于我们来说是否太过于麻烦,既然他们的实现方式都是一样的,那么我们是否能够定义一个模具,使用的时候只需要将不同的类型放在里面让他生成不同的函数,能够实现不同类型的加法嘞?答案是肯定的

首先,需要了解到范式编程:

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

函数模板

概念

函数模板代表了一个函数家族,该函数模板与类型无关,在使用时被参数化,根据实参类型产生函数的特定类型版本。

函数模板格式

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

比如我们下面的程序

 问题来了,main函数里面的函数调用是调用的同一个函数吗?

答案是否定的,虽然经过调试,函数调用的时候会走同一块地方,但是并不是意味着这两个函数调用调用的是同一个函数,调用的是由一个模板生出来的两个不同函数

我们通过反汇编也能看出这个问题

很明显,调用的是两个不同的函数

函数模板的原理

函数模板是一个蓝图,它本身并不是函数,是编译器用使用方式产生特定具体类型函数的模具。所以其实模板就是将本来应该我们做的重复的事情交给了编译器

在编译器编译阶段,对于模板函数的使用,编译器需要根据传入的实参类型来推演生成对应类型的函数以供调用。比如:当用double类型使用函数模板时,编译器通过对实参类型的推演,将T确定为double类型,然后产生一份专门处理double类型的代码,对于字符类型也是如此。

函数模板的实例化

隐式实例化

:根据实参的类型自动确定T的类型

但是下面的代码是有问题的

这段代码编译器会报错,因为x1是int 类型的,y1是double类型的,编译器无法确定根据两个实参类型无法确定T是什么类型的

针对上面的问题,有以下两种解决方案

第一种

强制类型转化

第二种:显示类型转换

显式类型转换

:在函数名后的<>中指定模板参数的实际类型

比如下面的

参数不一致的话会被强制类型转换的

模板参数的匹配原则

1. 一个非模板函数可以和一个同名的函数模板同时存在,而且该函数模板还可以被实例化为这个非模板函数

这种情况下,add(x1,x1)会去匹配普通的函数,而不会去匹配模板里面生成的函数,就像吃饭一样,我们一般都会去选择一个成品,而不是一个半成品

2.2对于非模板函数和同名函数模板,如果其他条件都相同,在调动时会优先调用非模板函数而不会从该模板产生出一个实例。如果模板可以产生一个具有更好匹配的函数, 那么将选择模板

3. 模板函数不允许自动类型转换,但普通函数可以进行自动类型转换

类模板

template<class T>
class Queue
{
public:
	Queue(size_t capacity = 10)
		: _pData(new T[capacity])
		, _size(0)
		, _capacity(capacity)
	{}
	// 使用析构函数演示:在类中声明,在类外定义。
	~Queue();
	T& operator[](size_t pos)
	{
		assert(pos < _size);
		return _pData[pos];
	}
private:
	T* _pData;
	size_t _size;
	size_t _capacity;
};

// 注意:类模板中函数放在类外进行定义时,需要加模板参数列表
//这里不建议模板声明和定义分离到.h和.cpp文件里面,会出现链接错误
template <class T>
Queue<T>::~Queue()
{
	if (_pData)
		delete[] _pData;
	_size = _capacity = 0;
}


int main()
{
	//实例化
	Queue<int> q1;
	Queue<char> q2;
	return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值