C++类模板

1、一些基础知识点
(1)类名的使用与类类型的使用区分
定义一个模板Stack,如何区别使用Stack 与Stack

template<typename T>
class Stack {
	private:
	std::vector<T> elems; // 储存元素的数量
	public:
	Stack();   // 构造函数,不是Stack<T>
	...
};

这个类的类型是Stack,当声明中需要使用该类的类型时,必须使用Stack,但是如果使用的是类名,而不是类型,就应该只用Stack,如构造函数、析构函数等

(2)类模板使用的时候,必须显示的指定模板实参,如vector 必须显示指定模板实参类型为int
(3)对于类模板,只有哪些被调用的成员函数,才会产生这些函数的实例化代码
优点主要有两点:节省空间和时间 另外,对于某些类型,不能提供所有成员操作,仍然可以使用该类型来实例化模板,
只要不调用那些不支持的操作就行(不调用也就不会实例化相应的成员函数)

template<typename T>
class Stack {
	private:
	std::vector<T> elems; // 储存元素的数量
	public:
	Stack();   // 构造函数,不是Stack<T>
	T accumulate(); // 该函数的作用是,将vector中所有元素求和
	...
};

在上面的类模板中,成员函数accumulte的作用是对vector中的元素求和,如果类模板参数T是普通的int 等类型是可以求和的,但是如果T是一个类类型C,显然是不能对类型C求和的,但是仍然可以使用C实例化这个类,只要不调用函数accumulate,那么在实例化的时候,就不会实例化函数accumulate,就能顺利通过编译。

(4)类模板可以特化,特化一定要加上template<> 里面参数列表可以为空也可以不为空
(5)类模板支持缺省模板实参,并且后面的模板参数可以应用前面的模板参数
如:
template<tyename T, typename CONT = std::vector>

2、非类型模板参数

模板参数并不局限于类型,普通值也可以作为模板参数。

template<typename T, int MaxSize>  // MaxSize 为非类型模板参数
class Stack
{
	private:
		T elems[MaxSize];   // 用来指定数组的大小
		...
};

同样可以为非类型参数添加缺省值

template<typename T, int MaxSize = 1024>  // 指定缺省大小为1024
class Stack
{
	private:
		T elems[MaxSize];   // 用来指定数组的大小
		...
};

函数模板也可以添加非类型模板参数

非类型模板参数的限制,通常而言,它们可以是常整数(包括枚举值),或是指向外部链接对象的指针,浮点数和类对象是不允许作为非类型模板参数的

3、技巧性基础知识
(1)typename关键字
关键字typename ,引入关键字是为了说明模板内部的标识符可以是一个类型

template<typename T>
class MyClass{
	typename T::Subtype *ptr;
	...
};

如果不使用typename , Subtype 就会被认为是一个静态成员,那么它就应该是一个具体的对象或者变量,于是下面的表达式:
T::Subtype * ptr, 就会被看做是类T的静态成员Subtype 与 ptr的乘积。即解释为 (T::Subtype) * ptr

(2)使用this关键字
对于具有基类的类模板,自身使用名称x并不一定等同于this->x,即使该x是从基类继承获得的,也是如此。例如:

template<typename T>
class Base{
	public:
	void exit();
};
template<typename T>
class Drived : Base<T>
{
	public:
		void foo()
		{
			exit();  // 这里只会调用外部的exit()或者出现错误,并不会调用基类的exit()
		}
	...
};

对于那些在基类中声明,并且依赖模板参数的符号(函数或者变量),你应该在他们前面使用this-> 或者 Base:: 来限定访问的成员

(3)成员模板
类的成员函数也可以是模板

template<typename T>
class Stack {
	public:
	// 使用元素类型为T2的栈进行赋值
	template<typename T2>
	Stack<T>& operator= (Stack<T2> const &);
	...
};
// 类外进行定义时,格式如下:
template<typename T>
template<typename T2>
Stack<T> & Stack<T>::operator= (Stack<T2> const & op2)
{
	// ....
};

4、模板的模板参数
有时候,让模板本身成为模板是很有用的,如:

template<typename T, template<typename ELEM> class CONT = std::deque >
class Stack {
	private:
	CONT<T> elems;    //保存元素的容器
	public:
	...
};

不同之处在于,第二个模板参数被声明为一个类模板。同时由于并不会用到上面的”模板的模板参数“的模板参数,即ELEM
因此,可以把该名称省略。
template<typename T, template class CONT = std::deque >
class Stack {
private:
CONT elems; //保存元素的容器
public:

};
需要说明的是:函数模板并不支持,模板的模板参数

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值