模板初阶

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

先来实现一个支持各种类型的交换函数 Swap

函数模板

函数模板并没有类型,在使用的时候被参数化,更据实参类型产生函数特定类型的版本;

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

template<typename T>
void Swap(T& left, T& right)
{
	T temp = left;
	left = right;
	right = temp;
}

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

template<class T>
//class / typename 没啥区别  
T Add(T left, T right)
{
	//查看 T 的类型
	cout << typeid(T).name() << endl;
	return left + right;
}

int main()
{
	Add(10, 20);
	Add(10.0,20.0);
	
	//该语句无法通过编译,由于编译器不确定推演出来的类型,
	//所以还必须在模板里加一个参数;
	Add(10,20.0);
	return 0;
}

函数模板的实例化

编译器在编译阶段,要根据实参的类型来确认具体生成什么类型的代码;用不同类型的参数使用函数模板时,称为函数模板的实例化
隐式实例化 VS 显式实例化

  1. 隐式实例化:没有明确给出模板参数的实际类型,编译器根据实参推演模板参数的实际类型,如果发现推演结果与类型参数不匹配,编译器报错;

     Add(10, 20);
     Add(10.0,20.0);
     Add(10,(int)20.0)
    
  2. 显式实例化:在函数名后的<>中指定模板参数的实际类型,明确指定模板参数列表中的实际类型,直接生成代码,在调用时如果发现类型不匹配会尝试进行类型转换。

     Add<int>(10.20.0);
    

类模板

类模板实例化与函数模板实例化不同,类模板实例化需要在类模板名字后跟<>,然后将实例化的类型放在 <> 中即可,类模板名字不是真正的类,而实例化的结果才是真正的类。

#include <iostream>
#include <stdlib.h>
#include <assert.h>
using namespace std;

//typedef int T;
template<class T>

class SeqList
{
public:
	SeqList(size_t capacity = 10)
		:_array (new T [capacity])
		,_capacity(capacity)
		,_size(0)
	{}

	void PushBack(const T& data);
	void PopBack()
	{
		--_size;
	}

	size_t Size()const
	{
		return _size;
	}

	size_t Capacity()const
	{
		return _capacity;
	}

	bool Empty()const
	{
		return _size == 0;
	}

	//[] :下标运算符重载
	T& operator[](size_t index)
	{
		assert(index < _size);
		return _array[index];
	}

	const T& operator[](size_t index)const
	{
		assert(index < _size);
		return _array[index];
	}

	~SeqList()
	{
		if (_array)
		{
			delete[] _array;
			_array = nullptr;
			_capacity = 0;
			_size = 0;
		}
	}
protected:
	T* _array;
	size_t _capacity;
	size_t _size;
};

template<class T>
//SeqList 不是具体的类,是编译器根据被实例化的类型生成具体类的模具 
//SeqList<int>才是类
void SeqList<T>::PushBack(const T& data)
{
	//CheckCapacity
	_array[_size++] = data;
}
int main()
{
	//汇编名字为 SeqList<int>::SeqList<int>
	SeqList<int> s1;	
	s1.PushBack(1); 
	s1.PushBack(2); 
	s1.PushBack(3);
	cout << s1[0] << endl;

	//汇编名字为 SeqList<int>::SeqList<int>
	SeqList<double> s2;

	system("pause");
	return 0;
}

C++ 类模板的分离式编译

未完待续…

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

程序猿的温柔香

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

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

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

打赏作者

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

抵扣说明:

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

余额充值