• C++模板小结


    面向对象和泛型编程在C++的编程思想中占据绝对的地位,而模板又是泛型编程的主要内容。

    函数模板

    1. 普通模板

    //以Swap名称为例
    template <typename T0,typename T1> //or class
    void Swap(T0 &a, T1 &b)
    {......}

    2. 具体化

    隐式实例化、显式实例化、显式具体化统称为具体化。

    (1) 显式具体化(可以写成两种形式)

    //以Swap名称为例
    template <> 
    void Swap<int>(int &a, int &b) 
    {......}
    //or
    /*
    template <> 
    void Swap(int &a, int &b) //<int>是可选的
    {......} */

    (2)显式实例化

    在模板声明中用符号‘<>’显式的指出类名。

    //以Swap名称为例
    template void Swap<int>(int , int );

     (3)隐式实例化

    依赖输入实参类型实例化模板。

    //以Swap名称为例
    //
    模板声明 template <Typename T0, typename T1> void Swap(T0 &, T1 &) //程序入口 void main() { int a = 1; int b = 2; Swap(a, b);//隐式实例化为函数定义void Swap(int &, int &){} ........ }

    3. 使用哪个函数版本

    对于函数重载、函数模板、函数模板重载,C++有一个良好的策略,决定函数调用使用哪一个函数定义。这个过程称作重载解析

    对此,编译器需要决定哪一个可行函数是最佳的,从最佳到最差的顺序如下:

    一、完全匹配,常规函数优先于模板;

    二、提升转换(如char,short —> int或float —> double)

    三、标准转换(数值类型之间的非提升转换)

    四、用户(用户指使用模板定义的程序员)定义的转换(?用户定义的转换是什么,怎么表示?如何直观地验证其优先级最低?)

    (1)完全匹配和最佳匹配

    完全匹配允许一些无关紧要的转换(如数组和指针、引用和变量之间)

    有两个函数完全匹配是一种错误,但这一规则有两个例外:

    一个是指向非const的引用或指针优先与非const指针或引用匹配,其次与const指针或引用匹配(注:只限于引用或指针);

    另一个是当两个函数完全匹配时将选择最具体(需要进行的转换最少)的版本。

    (2)创建自定义选择

    (?)在函数调用中显式地使用符号‘<>’使模板函数具体化。(?)

    类模板

    1. 类模板语法规则

    (1)类声明和定义

    如果在类声明中定义了方法(内联),则可以省略模板前缀和类限定符;

    不能将模板成员函数放在独立的实现文件中。

     1 //a.h
     2 #ifndef A_H_
     3 #define A_H_
     4 #include<iostream>
     5 using namespace std;
     6 
     7 template<class T>
     8 class A
     9 {
    10     T t;
    11 public:
    12     A() : t(0){}
    13     void show(){std::cout << t << std::endl;} //内联
    14     void view();//模板类方法声明
    15 };
    16 
    17 template<class T>//模板类方法定义
    18 void A<T>::view()
    19 {
    20     std::cout << "view T: " << t << std::endl;
    21 } 
    22 
    23 #endif

    (2)模板类的使用

     1 #include"a.h"
     2 
     3 void show(int &);
     4 
     5 void main()
     6 {
     7     A<int> a;
     8     a.show();
     9     system("pause");
    10 }

    2. 模板的参数

    (1)使用非类型参数

    模板中由typename或class限定的类型称作类型参数;已知类型称作非类型(或表达式)参数。

    template<typename T, int n>  // T为类型参数,n为非类型参数。

    非类型参数可以是整型、枚举、引用或指针。(double m是不合法的,但double &和double*是合法的)

    模板代码不能修改参数的值,也不能使用参数的地址。

    实例化模板时,用作非类型参数的值必须是常量表达式(比如不能把变量赋给模板类array<int, n>中的非类型参数n,array类相对于vector类运行速度快,适合处理大量小数组)。

    (2)具体化的模板类可以作为其它模板的类型参数

    Array < Stack<int> > asi //外层尖括号内侧最好用空格隔开

    (3)可以将具体化的模板用作自身的类型参数,达到递归的目的。

    1 typedef array ArrayTP;
    2 ArrayTP< ArrayTP<int, 5>, 10 > twodee; //等价于int twodee[10][5]

    (4)将模板用作参数

    模板可以包含本身就是模板的参数。

    1 template< template<typename T> class Thing >
    2 class Crab
    3 {
    4     ......
    5 };

    (5)使用多个类型参数

    模板可以使用多个类型参数。

    (6)给模板参数提供默认值

    可以给类模板参数提供默认值,但不能给函数模板参数提供默认值,可以为非类型参数提供默认值。

    1 template<class T1, class T2 = int, int n = 0>
    2 class ToPo
    3 {
    4 }

    3. 类模板的具体化

    (1)隐式实例化

    ArrayTP<double, 100> stuff;

    (2)显式实例化

    template class ArrayTP<string, 30>;

    (3)显式具体化

    当对特殊类型实例化时,要对模板进行修改,使其行为不同。这种情况下可以创建显式具体化。

    template <> class Classname<specialized-type-name>{......};

    (4)部分具体化

    //普通模板
    template <class T1, class T2> class Pair{......};
    //具体化T2为int
    template <class T1> class Pair<T1, int>{......};

    4. 模板成员

    我们提到过数据成员,函数成员,这里引入模板成员。

    模板可以作为结构、类和模板类的成员。

    5. 模板类和友元

    模板类的声明也可以有友元。模板的友元分三类:

    1. 非模板友元(类似于普通类的友元);

    2. 约束模板友元

    使得模板类的每一个具体化,都获得与友元匹配的具体化。包含以下三部:

    (1)在类定义的前面声明每个模板函数;

    (2)在函数中再次将模板声明为友元;

    (3)为友元函数提供模板定义。

    3. 非约束模板友元

    对于非约束化模板友元,友元模板类型参数与类模板类型参数是不同的。

    在类定义中声明模板函数,并声明其为友元;之后再为模板函数提供友元定义。

  • 相关阅读:
    UUID含义及ubuntu配置系统默认JDK
    MYSQL 问题小总结
    纯CSS3实现常见多种相册效果
    Docker Api 实测
    Dijkstra with priority queue 分类: ACM TYPE 2015-07-23 20:12 4人阅读 评论(0) 收藏
    hash值的计算与转换 分类: ACM TYPE 2015-05-07 17:49 36人阅读 评论(0) 收藏
    NYOJ
    进制转换函数 2015-02-15 09:41 32人阅读 评论(0) 收藏
    操作系统图解 2015-02-03 23:44 71人阅读 评论(0) 收藏
    [kuangbin带你飞]专题一 简单搜索
  • 原文地址:https://www.cnblogs.com/sungnox/p/7633190.html
Copyright © 2020-2023  润新知