zoukankan      html  css  js  c++  java
  • C++笔记(3)模板与泛型编程

    3.1 函数模板

     1  
    2
    3 template <typename T>
    4
    5 inline int compare(const T &v1, const T &v2) //inline放在template之后
    6
    7 {
    8
    9 if (v1 < v2)
    10
    11 {
    12
    13 return -1;
    14
    15 }
    16
    17 if (v2 < v1)
    18
    19 {
    20
    21 return 1;
    22
    23 }
    24
    25 return 0;
    26
    27 }
    28
    29 string s1;
    30
    31 string s2;
    32
    33 compare(s1, s2) //用string 替代T创建compare.
    34
    35



    T表示的实际类型由编译器所用的函数而确定.

    使用函数模板时, 编译器会推断哪个模板实参绑定到模板形参,一旦编译器确定了实际的模板实参,就称它实例化了一个函数模板的实例, 实际上,编译器编写了一个函数实例.

     

    3.2 模板类

     

    关键字class or typename.

     1  
    2
    3 template <class Type> class tempclass
    4
    5 {
    6
    7 public:
    8
    9 tempclass();
    10
    11 Type func(void);
    12
    13 void func2(Type);
    14
    15 //...
    16
    17 private:
    18
    19 //...
    20
    21 };
    22
    23 tempclass<string> obj;
    24
    25 tempclass<vector<double>> obj;
    26
    27
    28
    29 typedef double T
    30
    31 template <typename T>
    32
    33 inline int compare(const T &v1, const T &v2){
    34
    35 T temp; /*将T定义为double的全局类型别名被T的类型形参所屏蔽,因此temp为绑定到模板形参的任意类型. */
    36
    37 //
    38
    39 }
    40
    41
    42
    43 template <typename T>
    44
    45 inline int compare(const T &v1, const T &v2){
    46
    47 typedef double T
    48
    49 T temp; //error, redeclares T
    50
    51 //
    52
    53 }
    54
    55



    模板可以只声明不定义, 且同一模板的声明和定义中,模板形参的名字可以不同.

     1 template <typename parm, typename u >
    2
    3 parm fcn(parm *array, U value)
    4
    5 {
    6
    7 parm::size_type *p; /*编译器会无法辨识是size_type或是数据成员,默认是数据成员,则重定义.*/
    8
    9 typename parm::size_type * p; //typename告诉编译器姜size_type当做类型.
    10
    11 }



     

    多个类型的实参必须完全匹配。

    short i(9);

    compare(i, 10); //error, ambiguous, compare(short, short), compare(int,int)

    如果允许常规转换,则可以定义

     1 template <typename A, typename B>
    2
    3 inline int compare(const A &v1, const B &v2){
    4
    5
    6
    7 }
    8
    9 short i(9);
    10
    11 compare(i, 10); //ok
    12
    13
    14
    15 template <typename T>
    16
    17 inline int compare(const T &v1, const T &v2);
    18
    19 int a[10],b[20];
    20
    21 compare(a, b); /*error,当形参为引用时,数组不能转换为指针,a和b的类型不匹配.*/
    22
    23
    24
    25 template <typename T>
    26
    27 inline int compare(const T v1, const T v2);
    28
    29 int a[10],b[20];
    30
    31 compare(a, b); /*ok,非引用形参,对数组或函数类型的实参,都用常规指针转换,指向数组第一个元素和指向函数. */
    32
    33
    34
    35 int (*p)(const int&, const int&) = compare; //实例化compare(const int&, const int&);
    36
    37



    在返回类型中使用形参。

    1 template < typename C ,typename A, typename B>
    2
    3 inline C compare(const A &v1, const B &v2);
    4
    5 int i = 9;
    6
    7 short s = 10;
    8
    9 long l = compare<long>(i, s);



    模板实参从左至右与与对应模板形参相匹配,只有最右边形参的显示模板实参可以忽略。

     

     1 //如果定义
    2
    3 template <typename A ,typename B, typename C>
    4
    5 inline C compare(const A &v1, const B &v2);
    6
    7 //必须像是指模板形参
    8
    9 long l =cmpare< int, short, long>(i, s);
    10
    11 long l = compare<long>(i, s); //error, long给了A
    12
    13
    14
    15 void func(int (*)(const int &, const int &));
    16
    17 void func(string (*)(const string &, const string &));
    18
    19 func(compare); //error, ambiguous
    20
    21 func(compare<int>); //ok,显示指定模板参数
    22
    23



    普通函数只需要在源文件中声明,而定义类对象时,类定义必须可用,所以函数声明和类定义放在头文件中。

    编译器实例化的时候,必须要能够访问函数模板定义和类模板定义,

    包含编译模型

    xxx.h

     1 #ifndef xxx
    2
    3 #define xxx
    4
    5 template <typename T>
    6
    7 inline int compare(const T v1, const T v2);
    8
    9 #include "xxx.cc"
    10
    11 #endif



     

    xxx.cc

    1 template <typename T>
    2
    3 inline int compare(const T v1, const T v2)
    4
    5 {
    6
    7 }



     

    分别编译模型

    xxx.cc

    1 export template <typename T>
    2
    3 inline int compare(const T v1, const T v2);
    4
    5 #include "xxx.h"



     

    xxx.h

    1 template <typename T>
    2
    3 inline int compare(const T v1, const T v2)
    4
    5 {
    6
    7 }
    8
    9



    类声明必须放在头文件中,头文件中的类定义体中不应该使用export关键字,如果在头文件中使用了export,则该头文件中只能被程序中的一个源文件使用。

    xxx.h

     1 template <class Type> class tempclass
    2
    3 {
    4
    5 public:
    6
    7 tempclass();
    8
    9 Type func(void);
    10
    11 void func2(Type);
    12
    13 //...
    14
    15 private:
    16
    17 //...
    18
    19 };
    20
    21



    xxx.cc

    1 export template <class Type> class tempclass;
    2
    3 #include "xxx.h"



     

    3.3 类模板成员函数

     

    xxx.cc

    1 template <class type> void tempclass<type>::func2(type)
    2
    3 {
    4
    5 }



     

    3.4 类模板友元

     1 template <class Type> class tempclass
    2
    3 {
    4
    5 public:
    6
    7 tempclass();
    8
    9 Type func(void);
    10
    11 void func2(Type);
    12
    13 friend class friendclass;
    14
    15 friend void friendfunc(); /*普通友元,可以访问tempclass的任意实例的private和protected成员 */
    16
    17 template <class T> friend friendclass2;
    18
    19 template <class T> friend void friendfunc2(void);
    20
    21 /* 一般模板友元关系,模板类friendclass2和模板函数friendfunc2的任何实例都可以访问任何tempclass的任意实例的私有成员. */
    22
    23 //...
    24
    25 private:
    26
    27 //...
    28
    29 static std::size_t ctr;
    30
    31 };
    32
    33 template<class type> size_t tempclass<type>::ctr = 0;



     

    类模板的模板友元函数定义有2种方式:
    1.
    将友元模板函数直接定义在类模板中。这种方式比较简单直接。

     1 template <typename T>class Number;
    2
    3 template <typename T> void print(const Number<T>& n);
    4
    5
    6
    7 template <typename T>
    8
    9 class Number {
    10
    11 public:
    12
    13 Number(T v){}
    14
    15 friend void print(const Number& n)
    16
    17 {
    18
    19 }
    20
    21 };
    22
    23 Number<int> n(1);
    24
    25 print(n);




    2.
    将友元模板函数声明在类模板中,定义在类模板之外。这种方式的写法,如果不小心,通常会出现编译没问题,链接时无法解析的错误。

     1 template <typename T>class Number;
    2
    3 template <typename T> void print(const Number<T>& n);
    4
    5
    6
    7 template <typename T>
    8
    9 class Number {
    10
    11 public:
    12
    13 Number(T v){}
    14
    15 friend void print<T>(const Number<T>& n);
    16
    17 };
    18
    19 template <typename T>void print<T> (const Number<T>& n) {}
    20
    21 Number<int> n(1);
    22
    23 print(n);



     

    特定的模板友元关系

     1 template <class type> class foo; //必须先声明
    2
    3 template <class type> void func(const type&);
    4
    5 template <class Type> class tempclass
    6
    7 {
    8
    9 public:
    10
    11 friend class foo<char *>;
    12
    13 friend void func<char *>(char * const &);
    14
    15 friend class foo<type>;
    16
    17 friend void func<type>(const type &);
    18
    19 private:
    20
    21
    22
    23 };



     

    3.5 函数模板特化

     

    一个或多个模板形参的实际类型或实际值是指定的,特化的声明必须与模板相匹配.

    使用模板特化的文件必须包含模板特化的声明.

     1 template <>
    2
    3 int compare<const char*>(const char * const &v1, const char * const &v2)
    4
    5 {
    6
    7 return strcmp(v1, v2);
    8
    9 }
    10
    11 int a = 2, b = 3;
    12
    13 const char *cp1 = "a", *cp2 = "b";
    14
    15 compare(a, b); //calls the generic version instantiated with int
    16
    17 compare(cp1, cp2); // calls the specialization
    18
    19
    20
    21 template <typename T> int compare(const T&v1, const T&v2)
    22
    23 {
    24
    25 if (v1 < v2) return -1;
    26
    27 if (v2 < v1) return 1;
    28
    29 return 0;
    30
    31 }
    32
    33 /* template <> int compare<const char*>(const char * const &v1, const char * const &v2); 声明放这则OK. */
    34
    35 int _tmain(int argc, _TCHAR* argv[])
    36
    37 {
    38
    39 const char *cp1 = "a", *cp2 = "b";
    40
    41 compare(cp1, cp2); /*无法编译, explicit specialization; 'int compare<const char*>(const T &,const T &)' has already been instantiated */
    42
    43 return 0;
    44
    45 }
    46
    47
    48
    49 template <> int compare<const char*>(const char * const &v1, const char * const &v2)
    50
    51 {
    52
    53 return strcmp(v1, v2);
    54
    55 }
    56
    57



    3.6 类模板特化

     

     1 template <> class tempclass<const char*>
    2
    3 {
    4
    5 public :
    6
    7 void func2(const char *);
    8
    9 };
    10
    11 void tempclass<const char*>::func2(const char * v)
    12
    13 {
    14
    15 }



     

    3.7 类成员特化

     

    xxx.h

     1 template <class Type> class tempclass
    2
    3 {
    4
    5 public :
    6
    7 int compare(const Type&v1, const Type&v2);
    8
    9 };
    10
    11 int tempclass <const char *>::compare(const char * const &v1, const char * const &v2);



    xxx.cc

     1 template <class Type>
    2
    3 int tempclass<Type>::compare(const Type &v1, const Type &v2)
    4
    5 {
    6
    7 if (v1 < v2) return -1;
    8
    9 if (v2 < v1) return 1;
    10
    11 return 0;
    12
    13 }
    14
    15
    16
    17 template <>
    18
    19 int tempclass <const char *>::compare(const char * const &v1, const char * const &v2)
    20
    21 {
    22
    23 return strcmp(v1, v2);
    24
    25 }
    26
    27



    3.8 类模板的部分特化

     

     1 template <class T1, class T2> class some_tempclass
    2
    3 {
    4
    5 };
    6
    7 template <class T1> class some_tempclass<T1, int>
    8
    9 {
    10
    11 };
    12
    13 some_tempclass<int, string> obj; //use template <class T1, class T2> class some_tempclass
    14
    15 some_tempclass<string, int> obj2; //use template <class T1> class some_tempclass<T1, int>



     

    3.9 重载和函数模板

     

     1 template <class T>
    2
    3 int compare(const T &v1, const T &v2);
    4
    5 template <class T1, class T2>
    6
    7 int compare(const &T1, const &T1, const &T2);
    8
    9 int compare(const char * const &v1, const char * const &v2);
    10
    11
    12
    13 const char *cp1 = "a", *cp2 = "b";
    14
    15 compare("a", "b"); /*call int compare(const char * const &v1, const char * const &v2); 普通函数优先级比函数模板更高. */
    16
    17 compare(1, 2); //call int compare(const T &v1, const T &v2);
    18
    19 compare(1, 1, 2); //call int compare(const &T1, const &T1, const &T2);
    20
    21 char *cp3 = "a", *cp3 = "b"; /*call int compare(const T &v1, const T &v2); 因为调用普通函数需要从char *转换为const char * */


  • 相关阅读:
    19.SimLogin_case07
    19.SimLogin_case06
    19.SimLogin_case05
    19.SimLogin_case04
    19.SimLogin_case03
    闲说性能测试
    iostat命令详解
    Linux vmstat命令实战详解
    RAC集群节点故障模拟测试
    Oracle RAC功能测试
  • 原文地址:https://www.cnblogs.com/zengyou/p/2195586.html
Copyright © 2011-2022 走看看