C++ Primer 笔记14

1、任意类(模板或非模板)可以拥有本身为类模板或函数模板的成员,这种成员称为 成员模板(member template),成员模板不能为虚。 模板成员声明看起来像任意模板的声明一样:
template <class Type> class Queue{
  public:
    template<class It>
    Queue(It beg, It end):head(0),tail(0){copy_elems(beg, end);}
    template<class Iter>
    void assign(Iter, Iter);
  private:
    template<class Iter> void copy_elems(Iter, Iter);
};
成员声明的开头是自己的模板形参表。构造函数和assign成员各有一个模板类型形参,这些函数使用该类型形参作为其函数形参的类型,它们的函数形参是指明要复制元素范围的迭代器。
当在类模板作用域外部定义成员模板的时候,必须包含两个模板形参表:
template <class T>
template <class Iter>
void Queue<T>::assign(Iter beg, Iter end)
...  }
第一个模板形参表template<class T>是类模板的,第二个模板形参表 template<class Iter>是成员模板的。
成员模板遵循与任意其他类成员一样的访问规则。
2、与其他成员一样,成员模板只有在程序中使用时才实例化。成员模板有两种模板形参:由类定义的和由成员模板本身定义的。类模板形参由调用函数的对象的类型确定,成员定义的模板形参的行为与普通函数模板一样。这些形参都通过常规模板实参推断而确定。
3、类模板可以像任意其他类一样声明static成员。 像使用任意其他static数据成员一样,必须在类外部出现数据成员的定义。
4、 模板特化:
template<typename T>
int compare(const T &v1, const T &v2)
{
    if(v1 < v2) return -1;
    if(v2 < v1) return 1;
    return 0;
}
为了能够将compare函数用于字符串,必须提供一个知道怎样比较C风格字符串的特殊定义。这些版本时特化的,这一事实对模板的用户透明。对用户而言,调用特化函数或使用特化类,与使用从通用模板实例化的版本无法区别。
函数模板特化: 一个或多个模板形参的实际类型或实际值是指定的。特化的形式如下:
  关键字template 后面接一对空的尖括号(< >)
  再接模板名和一对尖括号,尖括号中指定这个特化定义的模板形参
  函数形参表
  函数体
例: template<>
        int compare<const char*>(const char * const &v1, const char * const &v2)
        { ...}
与任意函数一样,函数模板特化可以声明而无须定义。模板特化声明看起来与定义很像,但省略了函数体。
模板特化必须总是包含空模板形参说明符,即template<>,而且,还必须包含函数形参表。如果可以从函数形参表推断模板实参,则不必显式指定实参。
      当特化模板的时候,对实参类型不应用转换,在模板特化版本的调用中,实例类型必须与特化版本函数的形参类型完全匹配,如果不完全匹配,编译器将为实参从模板定义实例化一个实例。
类模板的特化: 为C风格字符串的Queue提供正确行为的一种途径,是为const char *定义整个类的特化版本。
template<>
class Queue<const char *>
{ ... };
在类特化外部定义成员时,成员之前不能加template<>标记。
例 void Queue<const char *>::push(const char * val)
{...}
特化成员而不特化类: 除了特化整个模板之外,还可以只特化push和pop成员。我们将特化push成员以复制字符数组,并且特化pop成员以释放该副本使用的内存:
template<>
void Queue<const char *>::push(const char * const &val){...}
template<>
void Queue<const char *>::pop(){...}
类模板的部分特化:如果类模板有一个以上的模板形参,我们也许想要特化某些模板形参而非全部。使用类模板的特化可以做到这一点:
template<class T1, class T2>
class some_template
{...};
部分特化:
template<class T1>
class some_template<T1, int>
{...};
some_template的部分特化只有一个名为T1的模板类型形参,第二个模板形参T2的实参已知为int。类模板的部分特化本身也是模板。部分特化的模板形参表只列出未知模板实参的那些形参。
      当声明了部分特化的时候,编译器将为实例化选择最特化的模板定义,当没有部分特化可以使用的时候,就使用通用模板定义。
5、函数模板可以重载:可以定义有相同名字但形参数目或类型不同的多个函数模板,也可以定义与函数模板有相同名字的普通非模板函数。 调用函数时,如果两个函数一样匹配,普通函数会优于模板版本。
      设计既包含函数模板又包含非模板函数的重载函数集合是困难的,因为可能会使函数的用户感到奇怪,定义函数模板特化几乎总是比使用非模板版本更好。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值