重载和模板的知识点总结

来源:互联网 发布:c sort为指针数组排序 编辑:程序博客网 时间:2024/06/03 12:02

一、函数重载


        重载函数是函数的一种特殊情况,为方便使用,C++允许在同一范围中声明几个功能类似的同名函数,但是这些同名函数的形式参数(指参数的个数、类型或者顺序)必须不同,也就是说用同一个运算符完成不同的运算功能。这就是重载函数。重载函数常用来实现功能类似而所处理的数据类型不同的问题。

        特点:①函数名相同

                   ②返回值类型相同

                   ③功能相似

                   ④参数(函数特征标)不同

例如,可以定义一组原型如下的print()函数

void print (const char * str, int width); //#1void print (double d, int width);         //#2void print (long l, int width);           //#3void print(int i, int width);            //#4void print (const char * str);            //#5

         使用print()函数时,编译器将根据所采取的用法使用有相应特征标的原型:

print ("Pancakes", 15);   //use #1print ("Syrup");          //use #2print (1999.0, 10);       //use #3print (1999, 12);         //use #4print (1999L, 15);        //use #5
         代码摘自《c++ Primer  Plus》
         

         优点:①不用为了对不同的参数类型或参数个数,而写多个函数

                   ②缩减代码,提高可读性


二、函数模板

       

        所谓函数模板,实际上是建立一个通用函数,其函数类型和形参类型不具体指定,用一个虚拟的类型来代表。这个通用函数就称为函数模板。凡是函数体相同的函数都可以用这个模板来代替,不必定义多个函数,只需在模板中定义一次即可。在调用函数时系统会根据实参的类型来取代模板中的虚拟类型,从而实现了不同函数的功能。

        

定义函数模板的一般形式为:
    template < typename T>
    通用函数定义  通用函数定义

    template <class T>
    通用函数定义  通用函数定义


例子:

#include <iostream>using namespace std;template<typename T>  //模板声明,其中T为类型参数T max(T a,T b,T c) //定义一个通用函数,用T作虚拟的类型名{   if(b>a) a=b;   if(c>a) a=c;   return a;}int main( ){   int i1=185,i2=-76,i3=567,i;   double d1=56.87,d2=90.23,d3=-3214.78,d;   long g1=67854,g2=-912456,g3=673456,g;   i=max(i1,i2,i3); //调用模板函数,此时T被int取代   d=max(d1,d2,d3); //调用模板函数,此时T被double取代   g=max(g1,g2,g3); //调用模板函数,此时T被long取代   cout<<"i_max="<<i<<endl;   cout<<"d_max="<<d<<endl;   cout<<"g_max="<<g<<endl;   return 0;}



类型参数可以不只一个,可以根据需要确定个数。如:
    template <class T1, typename T2>
可以看到,用函数模板比函数重载更方便,程序更简洁。但应注意它只适用于函数的参数个数相同而类型不同,且函数体相同的情况,如果参数的个数不同,则不能用函数模板。


三、类模板


类模板与函数模板的定义和使用类似。

一般,有两个或多个类,其功能是相同的,仅仅是数据类型不同,可以声明一个通用的类模板,它可以有一个或多个虚拟的类型参数。

例子:

#include <iostream>using namespace std;template <class T>//定义类模板class Compare{   public :   Compare(T a,T b)   {x=a;y=b;}   T max( )   {return (x>y)?x:y;}   T min( )   {return (x<y)?x:y;}   private :   T x,y;};int main( ){   Compare<int > cmp1(3,7);  //定义对象cmp1,用于两个整数的比较   cout<<cmp1.max( )<<" is the Maximum of two integer numbers."<<endl;   cout<<cmp1.min( )<<" is the Minimum of two integer numbers."<<endl<<endl;   Compare<float > cmp2(45.78,93.6);  //定义对象cmp2,用于两个浮点数的比较   cout<<cmp2.max( )<<" is the Maximum of two float numbers."<<endl;   cout<<cmp2.min( )<<" is the Minimum of two float numbers."<<endl<<endl;   Compare<char> cmp3('a','A');   //定义对象cmp3,用于两个字符的比较   cout<<cmp3.max( )<<" is the Maximum of two characters."<<endl;   cout<<cmp3.min( )<<" is the Minimum of two characters."<<endl;   return 0;}


用类模板定义对象的方法与此相似,但是不能直接写成
   Compare cmp(4,7); // Compare是类模板名
Compare是类模板名,而不是一个具体的类,类模板体中的类型T并不是一个实际的类型,只是一个虚拟的类型,无法用它去定义对象。必须用实际类型名去取代虚拟的类型,具体的做法是:
    Compare <int> cmp(4,7);
即在类模板名之后在尖括号内指定实际的类型名,在进行编译时,编译系统就用int取代类模板中的类型参数T,这样就把类模板具体化了,或者说实例化了。


归纳-----可以这样声明和使用类模板:
1) 先写出一个实际的类。由于其语义明确,含义清楚,一般不会出错。

2) 将此类中准备改变的类型名(如int要改变为float或char)改用一个自己指定的虚拟类型名(如上例中的T)。

3) 在类声明前面加入一行,格式为:
    template <class 虚拟类型参数>
如:
    template <class T> //注意本行末尾无分号
    class Compare
    {…}; //类体

4) 用类模板定义对象时用以下形式:
    类模板名<实际类型名> 对象名;
    类模板名<实际类型名> 对象名(实参表列);
如:
    Compare<int> cmp;
    Compare<int> cmp(3,7);

5) 如果在类模板外定义成员函数,应写成类模板形式:
   template <class 虚拟类型参数>
   函数类型 类模板名<虚拟类型参数>::成员函数名(函数形参表列) {…}

关于类模板的几点说明:
1) 类模板的类型参数可以有一个或多个,每个类型前面都必须加class,如:
    template <class T1,class T2>
    class someclass
    {…};
在定义对象时分别代入实际的类型名,如:
    someclass<int,double> obj;

2) 和使用类一样,使用类模板时要注意其作用域,只能在其有效作用域内用它定义对象。

0 0
原创粉丝点击