zoukankan      html  css  js  c++  java
  • C++学习笔记之模板(1)——从函数重载到函数模板

    一、函数重载

    因为函数重载比较容易理解,并且非常有助于我们理解函数模板的意义,所以这里我们先来用一个经典的例子展示为什么要使用函数重载,这比读文字定义有效的多。

    现在我们编写一个交换两个int变量值得函数,可以这样写:

    1 void swap(int & a, int & b)
    2 {
    3    int tmp;
    4    
    5    tmp = a;
    6    a = b;
    7    b = tmp;  
    8       
    9 }

    假如我们现在想在与上面函数相同的文件中(可以理解为同一个main函数中)交换两个float变量呢,是不是需要重新整一个函数名,重新定义一个函数呢?当然是不需要!

    可以直接这样写:

    #include <iostream>
    
    void swap(int & a, int & b);
    void swap(float & a, float & b);
    
    int main()
    {
       using namespace std;
    
       int wallet1 = 300;
       int wallet2 = 350;
       float wallet3 = 125.33;
       float wallet4 = 235.82;
    
       cout << "Before swapping wallet1 and wallet2:" << endl;
       cout << "wallet1 = $" << wallet1 << endl;
       cout << "wallet2 = $" << wallet2 << endl;
       swap(wallet1, wallet2);
       cout << "After swapping wallet1 and wallet2:" << endl;
       cout << "wallet1 = $" << wallet1 << endl;
       cout << "wallet2 = $" << wallet2 << endl;
    
       cout << "Before swapping wallet3 and wallet3:" << endl;
       cout << "wallet3 = $" << wallet3 << endl;
       cout << "wallet4 = $" << wallet4 << endl;
       swap(wallet3, wallet4);
       cout << "After swapping wallet3 and wallet4:" << endl;
       cout << "wallet3 = $" << wallet3 << endl;
       cout << "wallet4 = $" << wallet4 << endl;
    
       return 0;
    }
    
     void swap(int & a, int & b)
    {
        int tmp;
        
        tmp = a;
        a = b;
        b = tmp;  
           
     }
    
     void swap(float & a, float & b)
    {
        float tmp;
        
        tmp = a;
        a = b;
        b = tmp;  
           
     }

    执行结果如下:

    由此可以总结出函数重载的相关知识:函数重载就是允许存在多个同名的函数,但是函数的参数列表必须不同,即参数的类型或者数目不一样。如示例中的swap()函数有两个,但是输入的参数类型不一样,编译器就是根据参数列表(也称为函数特征)的不同来确定到底选择哪一个函数去执行!这样我们就可以为相同的操作,但是参数类型不同的函数只用同一个函数名,如示例中都是交换操作,只是参数类型不同而已。虽然函数重载很吸引人,但是很明显看出代码量比较大,所以不要滥用,仅当函数基本上执行相同的任务,但使用不同形式的数据时,才应采用函数重载……

    一下,我们要交换char, int, short, double, float ...等等这许多变量,如果按照上述方式,正常人都疯了,于是函数模板款款而来……

    二、函数模板

    首先不说函数模板的定义,待洒家展示一下函数模板的神奇之处先,还是以事实说话,用函数模板实现上述功能:交换两个变量!

     

     1 #include <iostream>
     2 
     3 template <typename T>
     4 void Swap(T &a, T &b);
     5 
     6 int main()
     7 {
     8    using namespace std;
     9 
    10    int wallet1 = 300;
    11    int wallet2 = 350;
    12    cout << "Before swapping wallet1 and wallet2:" << endl;
    13    cout << "wallet1 = $" << wallet1 << endl;
    14    cout << "wallet2 = $" << wallet2 << endl;
    15    Swap(wallet1, wallet2);
    16    cout << "After swapping wallet1 and wallet2:" << endl;
    17    cout << "wallet1 = $" << wallet1 << endl;
    18    cout << "wallet2 = $" << wallet2 << endl;
    19 
    20    double wallet3 = 125.33;
    21    double wallet4 = 235.82;
    22    cout << "Before swapping wallet3 and wallet3:" << endl;
    23    cout << "wallet3 = $" << wallet3 << endl;
    24    cout << "wallet4 = $" << wallet4 << endl;
    25    Swap(wallet3, wallet4);
    26    cout << "After swapping wallet3 and wallet4:" << endl;
    27    cout << "wallet3 = $" << wallet3 << endl;
    28    cout << "wallet4 = $" << wallet4 << endl;
    29 
    30    char x = 'a';
    31    char y = 'b';
    32    cout << "Before swapping x and y:" << endl;
    33    cout << "x = " << x << endl;
    34    cout << "y = " << y << endl;
    35    Swap(x, y);
    36    cout << "After swapping wallet3 and wallet4:" << endl;
    37    cout << "x = " << x << endl;
    38    cout << "y = " << y << endl;
    39    return 0;
    40 }
    41 
    42 template <typename T>
    43 void Swap(T &a, T &b)
    44 {
    45     T tmp;
    46     tmp = a;
    47     a = b;
    48     b = tmp;
    49 }

     执行如下:

     

    这里我们实现了int, double, char类型的交换(但是其他任何类型的两个变量的交换均可实现,有兴趣的同学可以自己试一试,很简单,声明两个变量,调用一下函数就是了),但是可以看到,模板函数的定义就只是这么一小段:

    1 template <typename T>
    2 void Swap(T &a, T &b)
    3 {
    4     T tmp;
    5     tmp = a;
    6     a = b;
    7     b = tmp;
    8 }

    好了,来好好解释一下,缓解同志们迫不及待的心情,嘿嘿……

    所谓函数模板,就是让我们编写的函数独立于参数类型,只要函数执行的操作不变,就不用改变代码。函数模板以任意类型的方式来定义函数,以上面的Swap()模板函数为例:第一行指出要建立一个模板,类型为T,关键字template声明这是一个模板,关键字typename声明类型(有些老版本编译器不支持typename,用关键字class代替也一样),这里T是一个标志符,习惯上都用T(当然可以是S,Q,ABC等其他合法标识符),这个T代表着一种类型,但是具体代表什么类型(int?double?char?)是根据编译时输入的参数确定的,如上述main()函数的10,11,15行,编译器发现输入参数是int类型,那么T具体化为int, 同样第30,31,35,T就被具体化为char. 后面的代码就是交换两个变量的值。

    要注意的是,函数模板本身并不是函数,它只是告诉编译器如何定义函数(这就是称之为模板的原因,提供一个框架而已),具体的函数是在编译过程中生成的。需要交换int的函数时,编译器按照模板的模式创建这样的函数,用int代替T,即函数是在编译过程中生成的,函数模板并不创建函数,只是创建一个模板去告诉编译器如何生成函数而已,最终的代码(编译之后)不包含任何模板,而只包含了为具体程序生成的实际函数。使用模板的好处是,它使得生成多个函数定义更简单、可靠。

    专业一点的表述是,函数模板是通用的函数描述(ps:因为适合任何类型的参数),它们使用泛型来定义函数(ps:T可以带便任何类型),其中泛型可以用具体的类型(如int或者double)替换。通过将类型作为参数传递给模板,可是编译器生成该类型的函数。由于模板允许以泛型(刚刚ps中解释了泛型的感性理解哈)的方式编写程序,因此有时也被称为通用编程。由于类型是用参数表示的,因此模板特性也被称为参数化类型(parameterized types).

  • 相关阅读:
    .NET正则基础之——平衡组
    网站架构探索负载均衡的方式
    Sql2005 全文索引详解
    构架师之路(4) 里氏代换原则(Liskov Substitution Principle, LSP)
    Ubuntu 9.04 server安装nginx+php(fastcgi)
    构架师之路(2) 开闭原则(OpenClosed Principle,OCP)
    SQL Server中常用全局变量介绍
    构架师之路(3) 1 IoC理论的背景
    linux ubuntu 命令集合
    理解nginx 和 php(fastcgi)的关系
  • 原文地址:https://www.cnblogs.com/90zeng/p/Cpp_overload_function_templat.html
Copyright © 2011-2022 走看看