• 函数模板


    泛型编程:不考虑具体数据类型的编程

    函数模板:可用不同参数类型进行调用的函数(类型可以被参数化)

    语法:

    template < typename T >   // T 泛指任意的数据类型
    void Swap(T& a, T& b)
    {
        T c = a;
        a = b;
        b = c;
    }

    语法规则:template 关键字用于声明开始进行泛型编程(声明一个模板)。typaname 用于声明泛指类型。

    调用规则:自动类型推导调用(根据函数调用时实参的类型设置T的类型)--> Swap(a,b)。具体类型显示调用(函数调用时指定T的类型)--> Swap<float>(a,b)。

    函数模板原理:函数模板是个模子,编译器通过模板和具体参数类型产生不同的函数。编译器会进行两次编译,第一次检测模板代码,第二次检测加参数后的具体函数代码。 

     注意:模板本身不是函数,模板本身不允许隐式类型的转换。自动推导时:必须参数匹配。显示指定时:能进行隐式类型转换。

    #include <iostream>
    #include <string>
    
    using namespace std;
    
    class Test
    {
        Test(const Test&);  // 拷贝构造函数为是由函数,Test类无法进行拷贝构造
    public:
        Test()
        {}
    };
    
    template < typename T >   // 第一次编译:编译时进行模板的检查
    void Swap(T& a, T& b)
    {
        T c = a;
        a = b;
        b = c;
    }
    
    typedef void(FuncI)(int&, int&);
    typedef void(FuncD)(double&, double&);
    typedef void(FuncT)(Test&, Test&);
    
    int main()
    {
        FuncI* pi = Swap;    // 编译器自动推导 T 为 int        1.自动类型推导        2.产生一个函数     3.将函数地址赋给pi
        FuncD* pd = Swap;    // 编译器自动推导 T 为 double
        FuncT* pt = Swap;    // error 第二次编译时:编译器自动推导 T 为 Test,并生成一个参数为Test函数,但是函数内部有拷贝,出错
        
        cout << "pi = " << reinterpret_cast<void*>(pi) << endl;
        cout << "pd = " << reinterpret_cast<void*>(pd) << endl;
        cout << "pt = " << reinterpret_cast<void*>(pt) << endl;
        
        return 0;
    }

    多参函数模板:

    语法:

    template <typename T1,typename T2,typename T3>
    T1 Add(T2 a,T3 b)
    {
        return static_cast<T1>(a+b);
    }
    int ret = Add<int, float, double>(0.5, 0.8); // 函数在此才被创建

     注意:多参函数模板无法推导返回值类型,所以返回值类型必须显示指定。

        可以从左向右指定参数类型。

           推荐将返回值参数作为第一个类型参数来声明。

        // T1 = int, T2 = double, T3 = double
        int r1 = Add<int>(0.5, 0.8);            // T1显式指定返回值类型 (部分显示指定类型参数),T2,T3由编译器自动推导
        // T1 = double, T2 = float, T3 = double
        double r2 = Add<double, float>(0.5, 0.8);
        // T1 = float, T2 = float, T3 = float
        float r3 = Add<float, float, float>(0.5, 0.8);

     函数模板与被重载时:

    1. C++编译器优先考虑重载普通函数。

    2. 空实参列表模板限定编译器重载时只匹配模板Max<>(a,b)。

    #include <iostream>
    #include <string>
    
    using namespace std;
    
    
    template < typename T >   //
    T Max(T a, T b)
    {
        cout << "T Max(T a, T b)" << endl;  
        return a > b ? a : b;
    }
    
    int Max(int a, int b)      //函数重载函数模板
    {
        cout << "int Max(int a, int b)" << endl;    
        return a > b ? a : b;
    }
    
    template < typename T >    //函数模板重载函数
    T Max(T a, T b, T c)
    {
        cout << "T Max(T a, T b, T c)" << endl;    
        return Max(Max(a, b), c);
    }
    
    int main()
    {
        int a = 1;
        int b = 2;  // 进行重载时的选择根据参数类型,个数
        
        cout << Max(a, b) << endl;                   // 普通函数 Max(int, int)    
        cout << Max<>(a, b) << endl;                 // 只考虑函数模板 Max<int>(int, int)    
        cout << Max(3.0, 4.0) << endl;               // 函数模板 Max<double>(double, double)   
        cout << Max(5.0, 6.0, 7.0) << endl;          // 函数模板 Max<double>(double, double, double)    
        cout << Max('a', 100) << endl;               // 普通函数 Max(int, int)    
        return 0;
    }

    函数模板特化:特化就是模板的特殊形式,根据参数分为完全特化(参数类型完全确定),部分特化(参数类型相同)。

    函数模板特化只支持函数模板的完全特化。

    template <typename T>
    void function(T a,T b)
    {
      /* do something */
    } template < > void function<type>(type a,type b) //函数模板完全特化 {
      /* do something */
    }

    函数特化遇上函数重载:

    #include <iostream>
    #include <string>
    
    using namespace std;
    
    template
    < typename T >
    bool function(T a, T b)   // 函数模板
    {
      /* do something */
    } template
    < > bool function<double>(double a, double b) // 函数模板的完全特化 {
      /* do something */
    }
    bool function(double a, double b) // 全局函数对函数模板进行重载 {
      /* do something */
    }
    int main() { function( 1, 1 ); // 根据参数类型,调用函数模板 function( 0.001, 0.001 ); // 根据参数类型,优先调用重载的全局函数 function<>( 0.001, 0.001 ); // 使用 function<>() 时只考虑调用函数模板,根据参数选择完全特化 return 0; }
  • 相关阅读:
    Python爬取微博热搜榜,将数据存入数据库
    Python爬取网站文章数据并存到数据库
    在自己的框架系统中使用tp类
    conda环境下pip install 无法安装到指定conda环境中(conda环境的默认pip安装位置)
    jupyter notebook 加入conda虚拟环境(指定conda虚拟环境)
    本地打包好的项目如何运行在docker中
    测试
    SQL Server创建dblink跨库查询
    深入浅析BIO、NIO、AIO
    JavaWeb_html_js_css_javaweb
  • 原文地址:https://www.cnblogs.com/zsy12138/p/10858505.html
Copyright © 2020-2023  润新知