• C++ 模板


    0.前言

    模板是一种通用的描述机制,当使用模板时,允许使用通用类型来定义函数或类。通用类型可被具体类型(如int,double甚至是用户自定义类型)来代替。模板引入了一个全新的编程思维方式,称为“泛型编程”或者“通用编程”。

    1.函数模板

    1)函数模板声明形式如下:

    template  <class(或typename) A,...,int B (常数)>
    返回类型   函数名(参数列表)
    {
        //函数体
    }

    class用于定义类,在模板引入c++后,最初定义模板的方法为:template<class T>,这里class关键字表明T是一个类型,后来为了避免class在这两个地方的使用可能给人带来混淆,所以引入了typename这个关键字,它的作用同class一样表明后面的符号为一个类型。

    2)函数模板的使用

    函数模板定义形式如下:

    template  <class T1[,  class T2, ......]>
    函数原型;

    3)函数模板实例化

    3.1)隐式实例化:

     1 /*************************main.c********************/
     2 #include <iostream.h>
     3 using namespace std;
     4 template<class Ex>
     5 Ex  Greater(Ex x,Ex y);
     6 
     7 int main()
     8 {
     9     int inx=1;iny=2;
    10     cout<<Greater(inx,iny)<<endl;   //实参为int类型,生产int型模板函数,并对第二个进行实参检查
    11     return 0;
    12 }
    13 
    14 template<class Ex>
    15 Ex  Grearer(Ex x,Ex y)
    16 {
    17     return x>y?x:y;
    18 }
    View Code

    输出结果如下为2;

    3.2)显示实例化标准格式如下:

    template  返回类型   函数名<类型实参表>  (函数参数表)
     1 /*************************main.c********************/
     2 #include <iostream.h>
     3 using namespace std;
     4 template<class Ex>
     5 Ex  Greater(Ex x,Ex y);
     6 
     7 template  int  Greater<int>  (int,int);
     8 
     9 int main()
    10 {
    11     int inx=1;iny=2;
    12     cout<<Greater(inx,iny)<<endl;   //调用实例化模板函数
    13     return 0;
    14 }
    15 
    16 template<class Ex>
    17 Ex  Grearer(Ex x,Ex y)
    18 {
    19     return x>y?x:y;
    20 }
    View Code

    3.3)利用特化可以解决某些类型在函数中的特殊操作,特化的基本格式如下:

    template<>  返回类型  函数名[(类型实参表)](函数参数表)

    其中类型实参表可以省略,有后续的函数参数表来指定。

     1 /*************************main.c********************/
     2 #include <iostream.h>
     3 using namespace std;
     4 template<class Ex>
     5 Ex  Greater(Ex x,Ex y);
     6 
     7 template<>  double  Greater<double>(double,double);   //特化声明
     8 
     9 int main()
    10 {
    11     int inx=1;iny=2;
    12     double dbx = 3.0,dby = 2.9;
    13     cout<<Greater(inx,iny)<<endl;      //隐式实例化
    14     cout<<Greater(dbx,dby)<<endl;    //优先调用特化函数
    15     return 0;
    16 }
    17 
    18 template<class Ex>
    19 Ex  Grearer(Ex x,Ex y)
    20 {
    21     return x>y?x:y;
    22 }
    23 
    24 template<>  double  Greater(double x,double y)   //特化定义
    25 {
    26     return x+y;
    27 }
    View Code

    输出结果为:

    1 2
    2 5.9
    View Code

    3.4)优先级和执行顺序

    一般函数的执行顺序优先于模板的特化函数,模板的特化函数优先于实例化函数。

    更特化的含义体现在“编译器做决定是执行的转换最少”,c++遵循部分排序规则来选择最优化模板函数。

     1 template<class T>  void  f(T) {}        #1
     2 template<class T>  void  f(T*) {}        #2
     3 template<class T>  void  f(const T*) {}        #3
     4 template<class T>  void  g(T) {}        #4
     5 template<class T>  void  g(T&) {}        #5
     6 
     7 int main()
     8 {
     9     const int *p;
    10     f(p);
    11     int q;
    12     //g(q);
    13 }
    View Code

    模板#2比模板1更特化,模板3比模板2更特化,因此f(p)调用#3。然而模板#4和#5没有谁比谁更特化,因此g(q)会带来二义性错误。

    2.类模板

    1)类模板的定义

    template<class 模板参数表>
    class 类名{
        // 类定义
    };

    2)类模板实例化

    2.1)隐式实例化

    首先定义类模板:

     1 template  <class T,int num>
     2 class Stack
     3 {
     4     private:
     5         T  sz[num];
     6         int point;
     7     public:
     8         Stack();
     9         ...
    10 }
    11 
    12 template<class T,int num>
    13 Stack<T,num>::Stack()
    14 {
    15     point = 0;
    16 }
    View Code

    然后使用一下语句隐式实例化:

    Stack<int,10> st;

    下述语句不需要创建对象,编译器不会隐式生成类定义:

    Stack<int,10> *ps;

    2.2)显示实例化

    template  class 类名<类型参数表>

    2.3)显示特化

    template<>  class 类名<特殊类型>
    {
         类定义;
    }

    2.4)部分特化

    template<class T1 , class T2> class Example
    {
       //类定义
    };
    部分特化定义为:
    template<class T2> class Example<int ,T2>
    {
       //类定义
    }

    3)模板的嵌套

    3.1)函数成员模板

    成员模板不能声明为虚函数。

     1 #include <iostream.h>
     2 using namespace std;
     3 template<class A>
     4 class Test
     5 {
     6     public:
     7         template<class B>
     8          A f(B);
     9 };
    10 
    11 template<class A>
    12 template<class B>
    13 A Test<A>::f(B)
    14 {
    15    return A(B);
    16 }
    17 
    18 int main()
    19 {
    20     Test<int> t;
    21     cout<<t.f(3.14)<<endl;
    22     return 0;
    23 }
    View Code

    输出结果是:3

    3.2)对象成员模板

    类模板的定义可以放在另一个类中,实例化后的模板对象可以作为另一个类的成员。

     1 #include <iostream.h>
     2 using namespace std;
     3 template<class T>
     4 class Outside
     5 {
     6     public:
     7         template<class R>
     8         class Inside
     9         {
    10              private:
    11                   R r;
    12              public:
    13                   Inside(R r)     //类模板的成员函数可以在定义时实现
    14                   {
    15                       r = x;
    16                    }
    17              void disp();
    18         };
    19        void disp();
    20      private:
    21           Inside<T> t;
    22 } ;
    23 
    24 template<class T>
    25 template<class R>
    26 void Outside<T>::Inside<R>::disp()    //类模板的成员函数也可以在定义外实现
    27 {
    28     cout<<"Inside: "<<Outside<T>::Inside<R>::r<<endl;
    29 }
    30 
    31 template<class T>
    32 void  Outside<T>::disp()
    33 {
    34     cout<<"Outside:";
    35    t.disp();
    36 }
    37 
    38 int main()
    39 {
    40     Outside<int>::Inside<double> obin(3.5);  //声明Inside类对象
    41     obin.disp();
    42     Outside<int> obout(2);                          //创建Outside对象obout
    43     obout.disp();
    44     return 0;
    45 }
    View Code

    输出结果如下:

    Inside:  3.5
    Outside:Inside:  2
    View Code

    4)模板参数

    模板可以作为另一个模板的参数类型,形式如下:

    template<template <class T1> class T2,class T3,int Num>;
     1 #include <iostream>
     2 using namespace std;
     3 
     4 template<class T,int num>
     5 class Stack
     6 {
     7     private:
     8          T sz[num];
     9     public:
    10          int ReturnNum();  
    11 };
    12 template<class T1,int num1>
    13 int Stack(T1,num1>::ReturnNum()
    14 {
    15      return num1;
    16 }
    17 
    18 template<template<class Type,int NUM> class TypeClass,class T1,int N>
    19 void  disp()
    20 {
    21      TypeClass<T1,N> ob;     //类模板的隐式实例化,创建对象ob
    22      cout<<ob.ReturnNum()<<endl;
    23 }
    24 
    25 int main()
    26 {
    27    disp<Stack,int,8>();
    28    return 0;
    29 }
    View Code

    输出结果为:8。

  • 相关阅读:
    poj3083(Children of the Candy Corn)
    poj3278(Catch That Cow)
    poj2996(Help Me with the Game)
    poj2993(Emag eht htiw Em Pleh)
    js 对多sheet Excel赋值操作
    学习进度总结(三)
    学习进度总结(二)
    学习进度总结(一)
    《人月神话》阅读笔记(1)
    Android studio的安装与使用
  • 原文地址:https://www.cnblogs.com/wlzy/p/5903260.html
Copyright © 2020-2023  润新知