【C++】模版(template)

目录

一、函数模版:

1、概念:

2、关键字template:

3、函数模版原理:

二、类模板:

1、定义格式:

2、类模板的实例化:

三、typename与class

四、非类型模版参数:

五、模板的特化:

1、函数模版的特化:

2、类模板的全特化:

3、类模版的偏特化:


引言:

在C语言中诸多函数例如交换函数Swap存在“写死”,但是一会儿要交换int类型,一会儿要交换double类型,那么就要我们写很多不同种类的函数,就很繁琐,在C++中就引入了模版的概念,这样可以大大减少代码的重复度。

一、函数模版:

1、概念:

函数模版在定义时与类型无关,在参数化的时候根据实参类型产生函数的特定类型版本,实际上是不同的函数。

2、关键字template:

函数模板格式:

emplate<typename T1,typename T2,......,typename Tn>

void 函数名(T& 形参名1,......,T& 形参名n)//注意权限情况加const

{}

例如:

template<typename T>
void Swap(T& x, T& y)
{
	T tmp = x;
	x = y;
	y = tmp;
}
int main()
{
	int a = 1;
	int b = 2;
	Swap(a, b);
	double c = 1.1;
	double d = 2.2;
	Swap(c, d);
	cout << "a = " << a << endl << "b = " << b << endl;
	cout << "c = " << c << endl << "d = " << d << endl;

	return 0;
}

3、函数模版原理:

实际上调用是因为编译器帮我们通过函数模版实现了不同的函数,再调用它们来达到不同类型函数的调用。

二、类模板:

1、定义格式:

template<class T1, class T2, ..., class Tn>
class 类模板名
{
 // 类内成员定义
};

2、类模板的实例化:

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

比如在下面写的例子栈模板中:

template<class T>
class Stack
{
public:
	Stack(size_t capacity = 3);

	void Push(const T& data);

	~Stack()
	{
		if (_array)
		{
			free(_array);
			_array = NULL;
			_capacity = 0; 
			_size = 0; 
		}
	}
private:
	T* _array;
	int _capacity;
	int _size;
};

如上,实例化的时候在类后加上<>,里面给所需要的类型,

那么栈的类名:Stack

栈的类型:Stack<T>

如果将声明与定义分离,在函数外面进行定义就需要加上模版的声明和类域的划分

三、typename与class

在C++中,模板的定义可以使用两个关键字:class和typename。这两个关键字在大多数情况下可以互换使用,但它们在特定情况下存在细微的差别。

差别:
如果一个模板参数是一个类,而你想使用这个类的成员类型,那么应该使用typename来告诉编译器该名称是一个类型。

由于C++允许在类内定义类型别名,且其使用方法与通过类型名访问类成员的方法相同。

在类定义不可知的时候,编译器无法知晓类似的写法具体指的是一个类型还是类内成员。

C++ 中 typename 和 class 的区别 (runoob.com)

四、非类型模版参数:

非类型模版参数主要解决的是数组大小问题,

比如,如果我想通过一个类来定义对象,里面有一个成员变量的数组,这个时候就可以通过非类型的模版参数的传值来控制数组的大小。

五、模板的特化:

1、函数模版的特化:

模版的特化是在已经存在一个基础模版上实现的,

然后再另一个地方通过template<>下面的原函数后跟上<>,然后在里面指定需要特化的类型,可以是任意类型,指针引用等也可以。

最后,要保证特化模版的要和模版函数的基础参数类型完全相同。

template<class T>
bool Less(T left, T right)
{
	return left < right;
}
 
template<>
bool Less<int*>(int* left, int* right)
{
	return left < right;
}

2、类模板的全特化:

template<class T1,class T2>
class Date
{
public:
	Date()
	{
		cout << "调用了未特化的类class Date<class T1,class T2>" << endl;
	}
private:
	T1 _d1;
	T2 _d2;
};
 
template<>
class Date<int, double>
{
public:
	Date()
	{
		cout << "调用了全特化的类class Date<int, double>" << endl;
	}
private:
	int _d1;
	double _d2;
};
 
int main()
{
	Date<int, int> d1;
	Date<double, int> d2;
	Date<int, double> d3;
 
	return 0;
}

如上所示,如果对模板进行全特化后,如果在类实例化的时候找得到全特化的模版就会走全特化的模版,找不到就会走没有进行特化的模版。

3、类模版的偏特化:

template<class T1, class T2>
class Date
{
public:
	Date()
	{
		cout << "调用了未特化的类class Date<class T1,class T2>" << endl;
	}
private:
	T1 _d1;
	T2 _d2;
};

//偏特化T1为double
template<class T2>
class Date<double, T2>
{
public:
	Date()
	{
		cout << "调用了偏特化的类class Date<double, T2>" << endl;
	}
private:
	double _d1;
	T2 _d2;
};

//偏特化T2为int*
template<class T1>
class Date<T1, int*>
{
public:
	Date()
	{
		cout << "调用了偏特化的类class Date<T1, int*>" << endl;
	}
private:
	T1 _d1;
	int* _d2;
};
int main()
{
	Date<int, int> d1;
	Date<double, int> d2;
	Date<float, int*> d3;
	return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值