模版笔记002 - 类模版

  1. 类可以被一种或多种类型参数化。容器类就是一个典型的例子
  2. eg:MyStack< T >是类的类型,在声明的时候,如果模版类型的地方,直接使用T就行,如果要使用类类型的地方就需要指明是MyStack < T >, 例如拷贝构造,赋值构造,移动构造,右值拷贝构造。这当然不是绝对要求的,但是为了保证不出错,还是最好这么写。如果是使用类名而不是类类型时,应该使用MyStack,例如构造函数和析构函数。
  3. 对于成员函数,还应该使用完整的类型限定符:MyStack < T >::
  4. 如果一个类模版中含有10个成员函数,其中3个没有被调用到,那么这3个就不会实例化(针对具体类型而言),eg:针对int类型可能有3个没有被实例化,可能针对string类型有9个没有被实例化。因为他们没有被调用到。
  5. 特化。
    为了特化一个类模板,必须在起始出声明一个template<>,接下来声明用来特化模板的类型。这个类型将会被用作模板的实参,且必须在类名后面直接指定。eg:
template<>
class A<std::string>
{};

进行特化时,每个成员函数都必须重新定义为普通函数。

怎么理解特化?

eg:给动物们喂食,写成模板,动物类型就成了模板参数,鸡鸭鱼给饲料就行,但是对于老虎,就需要给肉了,这就需要特殊对待,写成模板特化就是类名后面接<老虎>,且所有类成员中所有用到模板参数T(动物类型)的地方,全换成老虎,之前的模板成员函数,需要全部换成普通函数,因为,老虎类型已经被指定了。
接下类接触一下偏特化,就是并非所有的类型都需要做特殊处理,只对其中部分类型做处理,这就是偏特化,上面讲的特化相应的就是全特化。
偏特化容易出现声明二义性的现象:定义一个对象时,发现有多个偏特化相同程度的匹配。eg:

// 类模板
template <typename T1, typename T2>
class A{};

// 偏特化:两个模板参数一样
template <typename T>
class A<T, T>{};

// 偏特化:第二个参数类型为int
template <typename T>
class A<T, int>{};

// 偏特化:两个都是指针类型
template <typename T1, typename T2>
class A<T1*, T2*>{};

// 二义性
A<int, int> obj; // 第一个偏特化和第二个具有相同的匹配度
A<int*, int*> obj; // 第一个偏特化和第三个具有相同的匹配度

为了解决偏特化的二义性,可以额外提供一个指向相同类型的指针的特化。具体,后面再详细解释。
6. 缺省模板实参
对于类模板,可以为模板参数指定缺省值,这个值就称为缺省模板实参,而且这个缺省值还有可以引用之前的模板参数。eg:

template <typename T, typename CONT = std::vector<T>>
class A{};

额外话题:如果类模板有多个模板参数,那么成员函数的定义都必须有这些个参数。

小结:
类模板是一种类,只是这个类的部分类型还没有指定。
为了使用类模板,必须传入具体的类型作为模板实参,然后编译器会基于传入类型来实例化类模板,那些并未被调用的成员函数不会被实例化
可以用指定类型来对类模板进行特化,也可以只特化部分(偏特化)
可以为类模板的模板参数定义缺省值,这些缺省值还可以引用之前的模板参数。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值