C++学习:模板类学习

来源:互联网 发布:c2c电商市场份额 淘宝 编辑:程序博客网 时间:2024/04/27 23:44

 C++学习:模板类学习 

按照WHAT, WHY, HOW的思路学习。
1. 什么是C++模板?
答:模板就是实现代码重用机制的一种工具。它实现了将类型参数化,就是将类型定义为参数,实现了真正的代码可重用性。模板分为两大类:函数模板和类模板。由于类模板包含类型参数,所以类模板又称作参数化的类。如果说类是对象的抽象,抽象是类的实例;那么可以说类模板是类的抽象,而类是类模板的实例。利用类模板可以建立各种数据类型的类。
2.为什么要引入模板机制呢?
答:为了实现代码重用,避免或者减少做重复性的工作,以及避免因重载函数定义不全面引起的调用错误等。
3.如何使用(实现)?
(1)函数模板的形式:

点击(此处)折叠或打开

  1. Template <class或者也可以用typename T>//函数(类)模板的声明

  2. 返回类型 函数名(形参表)//函数模板的定义/实现
  3. {
  4.   //函数定义体
  5. }
说明:①template 是声明模板的关键字;class可以被typename代替;T是虚拟类型参数,可以被任何字母,字符串或者数字代替。
          ②
当模板类和重载函数一起使用时,会首先考虑重载函数,其次是模板类,再没有的话会考虑类型转换(可能会不精确)。
测试实例:

点击(此处)折叠或打开

  1. //main.cpp
  2. #include <iostream>

  3. using std::cout;
  4. using std::endl;
  5. //声明一个函数模板,用来比较输入的两个相同数据类型参数的大小,class也可以被typename代替
  6. //T可以被任意字母或者数字代替
  7. template <typename T>
  8. T max(T x, T y)
  9. {
  10.     return (> y) ? x : y;
  11. }

  12. int main()
  13. {
  14.     int n1 = 2, n2 = 10;
  15.     float d1 = 1.5, d2 = 5.6;

  16.     cout << "Integer result is:" << max(n1, n2) << endl;
  17.     cout << "Real result is:" << max(d1, d2) << endl;

  18.     return 0;
  19. }
(2)模板类

点击(此处)折叠或打开

  1. template <class 类型参数名>//声明模板类
  2. class 具体类型参数名 //定义具体类
  3. {
  4.    //...
  5. }
举例:
比如在未使用模板类之前:要对两个整数作比较:

点击(此处)折叠或打开

  1. class Compare_integer
  2. {
  3. public :
  4.    Compare(int a,int b)
  5.    {
  6.       x=a;
  7.       y=b;
  8.    }
  9.    int max( )
  10.    {
  11.       return (x>y)?x:y;
  12.    }
  13.    int min( )
  14.    {
  15.      return (x<y)?x:y;
  16.    }
  17. private :
  18.    int x,y;
  19. };
如果你又想对double类型的数据作比较呢,就得重新定义一个新的类来实现:

点击(此处)折叠或打开

  1. class Compare_double
  2. {
  3. public :
  4.    Compare(double a,double b)
  5.    {
  6.       x=a;
  7.       y=b;
  8.    }
  9.    double max()
  10.    {
  11.       return (x>y)?x:y;
  12.    }
  13.    double min()
  14.    {
  15.       return (x<y)?x:y;
  16.    }
  17. private :
  18.    double x,y;
  19. }
这样就会比较麻烦。做的重复性的工作很多,使用了模板机制以后就可以减少这些问题。可以声明一个通用的类模板,它可以有一个或多个虚拟的类型参数,比如对上面两个类可以综合写出以下的类模板:

点击(此处)折叠或打开

  1. template <class numtype>
  2. class Compare
  3. {
  4. public :
  5.    Compare(numtype a,numtype b)
  6.    {
  7.      x=a;
  8.      y=b;
  9.    }
  10.    numtype max()
  11.    {
  12.      return (x>y)?x:y;
  13.    }
  14.    numtype min()
  15.    {
  16.      return (x<y)?x:y;
  17.    }
  18. private :
  19.    numtype x,y;
  20. }
将这个类模板和前面的两个类作比较,会发现:
1>多出了一行template <class numtype> 即声明类模板时要先加上一行template <class 类型参数名>
2>原有的类型名int换成虚拟类型参数名numtype.这样在建立类对象时,如果将实际类型指定为int型,编译系统就会用int取代所有的numtype,如果指定为double型,就用double取代所有的numtype。这样就能实现“一类多用”。

在声明了一个类模板之后,如何使用它,将它变成一个实际的类呢?
回想一般的定义一个对象的方法:

点击(此处)折叠或打开

  1. Compare_double cmp(2.3, 5.8);//Compare_double是已经声明的类
用类模板来定义对象的方法和上面的方法类似,但是不能直接那么写。Compare是一个类模板名,而不是一个具体类;numtype是一个虚拟类型,而不是一个具体类型;因此无法用它去定义一个对象。而必须用实际的类型名取代虚拟类型,具体做法:

点击(此处)折叠或打开

  1. Compare<double> cmp(2.3, 5.8);
即在类模板名之后的尖括号内指定实际的类型名,在进行编译时,编译系统就用double取代类模板中的类型参数numtype,这样就把类模板具体化了,或者说实例化了。这时Compare<double>就相当于前面介绍的Compare_double类。
注意:前面的类模板中的成员函数是在类模板内定义的,如果改为在类模板外定义,则不能使用一般的定义类成员函数的方法:

点击(此处)折叠或打开

  1. numtype Compare::max(){...}
而应该写成类模板的形式:

点击(此处)折叠或打开

  1. template <class numtype>
  2. numtype Compare<numtype>::max()
  3. {
  4.    return (x>y)?x:y;
  5. }
总结上面的学习,可以这样声明和使用类模板:
1)先写出一个实际的类。其语义明确,含义清楚。一般不会错。
2)将该类中准备改变的类型名(比如Int要改为char、double等)改为一个自己指定的虚拟类型名(比如上面例子中的numtype)。
3)在类的声明前加一行:
     template <class 虚拟类型参数>。
4)使用类模板定义对象时使用如下形式:

点击(此处)折叠或打开

  1. 类模板名<实际类型名> 对象名;
  2. 类模板名<实际类型名> 对象名(实参列表);
5)如果在类模板之外定义成员函数,应该写成类模板形式:

点击(此处)折叠或打开

  1. template <class 虚拟参数类型>
  2. 函数类型 类模板名<虚拟参数类型>::成员函数名(函数形参列表){...}

注意:
1)类模板的类型参数可以有一个或者多个,每个类型前面都必须加class,如:

点击(此处)折叠或打开

  1. template <class T1,class T2>
  2. class someclass
  3. {};
在定义对象名时,分别带入实际的类型名,比如:

点击(此处)折叠或打开

  1. someclass<int, char> Obj;
2)和使用普通类一样,在使用模板类时一定要注意其作用域。
3)模板也可以有层次,一个类模板可以作为基类,可以派生出派生模板类。

文章来源


0 0
原创粉丝点击