C++ Primer 笔记13

来源:互联网 发布:python 重定向 编辑:程序博客网 时间:2024/05/16 11:54
1、面向对象编程所依赖的多态性成为运行时多态性,泛型编程所依赖的多态性称为编译时多态性或参数式多态性。
2、函数模板(functiontemplate):模板定义以关键字template开始,后接模板形参表,模板形参表是用尖括号括住的一个或多个模板形参的列表,实参之间以逗号分隔。模板形参表不能为空。
例 template<typename T>
   int compare(constT& v1, const T& v2)
   {
     if(v1 < v2) return -1;
     if(v2 < v1) return 1;
     return 0;
   }
3、使用函数模板时,编译器会推断哪个(或哪些)模板实参绑定到模板形参,一旦编译器确定了实际的模板形参,就称它实例化(instantiate)了函数模板的一个实例。
4、inline函数模板:说明符放在模板形参表之后,返回类型之前,不能放在关键字template之前。
例 template<typename T> inline Tmin(const T&, const T&);
5、类模板的定义看起来和任意的其他类相似。类模板可以定义数据成员、函数成员和类型成员,也可以使用访问标号控制对成员的访问,还可以定义构造函数和析构函数等等。
  使用类模板时,必须为模板形参显式指定实参。例:vector<int>vec;
  编译器用用户提供的实际特定类型代替type,重新编写模板类。
6、模板形参的名字可以在声明为模板形参之后直到模板声明或定义的末尾处使用。 用作模板形参的名字不能在模板内部重用。这一限制还意味着模板形参的名字只能在同一模板形参表中使用一次。 每个模板形参前面必须带上关键字class或typename,每个非类型形参前面都必须带上类型名字,省略关键字或类型说明符是错误的。
7、在函数模板形参表中,typename和class具有相同含义,关键字typename是作为标准C++的组成部分加入到C++中的,因此旧的程序更有可能只用关键字class。
8、模板非类型形参是模板定义内部的常量值,在需要常量表达式的时候,可使用非类型形参指定数组的长度。
例: template<class T, size_t N> voidarray_init(T (&parm)[N]){...}
    int x[42]; double y[10]; array_init(x); array_init(y);
对模板的非类型形参而言,求值结果相同的表达式将认为是等价的。
    int x[42]; const int sz 40; double y[sz + 2];array_init(x);  array_init(y);这两个array_init调用引用的是相同的实例。
9、产生模板的特定类型实例的过程称为实例化,这个术语反映了创建模板类型或模板函数的新“实例”的概念。 想要使用类模板,就必须显式指定模板实参,使用函数模板时,编译器通常会为我们推断模板实参。
10、从函数实参确定模板实参的类型和值的过程叫做模板实参推断(template argumentdeduction)
多个类型形参的实参必须完全匹配。 类型实参的实参的受限转换,一般而言,不会转换实参以匹配已有的实例化,相反,会产生新的实例。除了产生新的实例化之外,编译器只会执行两种转换:
① const转换:接受const引用或const指针的函数可以分别用非const对象的引用或指针来调用。
②数组或函数到指针的转换:如果模板形参不是引用类型,则对数组或函数类型的实参应用常规指针转换。数组实参将当作指向其第一个元素的指针,函数实参当作指向函数类型的指针。
   用普通类型定义的形参可以使用常规转换,下面的函数模板sum有两个形参:
   template<class Type> Type sum(constType &op1, int op2){...}
   因为op2的类型是固定的,在调用sum的时候,可以对传递给op2的实参应用常规转换。
11、在返回类型中使用类型形参
template<class T1, class T2, classT3>  T1 sum(T2, T3);
为调用提供显式模板实参与定义类模板的实参类很类似,在以逗号分隔、用尖括号括住的列表中指定显式模板实参。例 long val3 = sum<long>(i, lng);
 显式模板实参从左到右与对应模板形参相匹配,第一个模板实参与第一个模板形参匹配,第二个实参与第二个形参匹配,以此类推。也可以为3个形参指定实参: long val2 = sum<long, int,long>(i, lng);
12、在使用类模板的名字的时候,必须指定模板形参。这一规则有个例外:在类本身的作用域内部,可以使用类模板的非限定名。
13、类模板成员函数的定义具有如下形式:
① 必须以关键字template开头,后接类的模板形参表。
② 必须指出它是哪个类的成员。
③ 类名必须包含其模板形参。
例: template <class T> ret-typeQueue<T>::member-name
调用类模板成员函数比调用类似函数模板更灵活。用模板形参定义的函数形参的实参允许进行常规转换。
类模板的成员函数只有为程序所用才进行实例化,如果某函数从未使用,则不会实例化该成员函数。
14、非类型实参的模板实参 , 例
template <int hi, int wid>
class Screen{
  public: Screen() : screen(hi * wid,'#')...
};
这个模板有两个形参,均为非类型形参。当用户定义Screen对象时,必须为每个形参提供常量表达式以供使用。类在默认构造函数中使用这些形参设置默认Screen的尺寸。像任意类模板一样,使用Screen类型时必须显式声明形参值:
Screen<24, 80> hp;
非类型模板实参必须是编译时常量表达式。
15、在类模板中可以出现三种友元声明,每一种都声明了与一个或多个实体的友元关系。
① 普通非模板类或函数的友元声明,将友元关系授予明确指定的类或函数。
② 类模板或函数模板的友元声明,授予对友元所有实例的访问权。
③ 只授予对类模板或函数模板的特定实例的访问权的友元声明。
将函数模板设为友元:
template <class T>
std::ostream &operator<<(std::ostream&, const Queue<t>&);
template<class Type> classQueueItem
{
  friend classQueue<Type>'
  friend std::ostream &operator<<<Type>(std::ostream&, constQueue<Type>&);
  ...
};
原创粉丝点击