C++ 函数模板(1)

文章概述

  1. 为什么会出现函数模板
  2. 函数模板的定义
  3. 函数模板的语法
  4. 函数模板当参数
  5. 函数模板遇上函数重载(函数模板和普通函数成为函数重载)
  6. 函数模板和普通函数调用规则研究

为什么会出现函数模板

我们有一个需求,将int,char类型的数据交换?

void MySwap01(int& a,int& b)
{
    int temp = a;
    a = b;
    b = temp;
}
void MySwap02(char& a, char& b)
{
    char temp = a;
    a = b;
    b = temp;
}

我们发现两个函数参数的类型不同,但是函数的业务逻辑类似。为了方便我们编码,有没有一种方法,就是写一个通用函数来满足不同的参数需求。答案是有的,那就是我们今天介绍的函数模板。


函数模板的定义

建立一个通用函数,其类型(函数类型或者参数类型)不具体指定,用一个虚拟的类型代替,这个通用函数就是函数模板。
凡是函数体相同的函数都可以用这个模板代替,不必定义多个函数,只需要在模板中定义一次即可。
调用函数会根据实参的类型代替模板中的虚拟类型,从而实现了不同函数的功能。


函数模板的语法

函数模板由模板说明和函数定义组成。
模板说明:

template <类型形式参数表>
类型形式参数表:
typename T,....typename Tn或者 class T,....class Tn

函数定义:

类型 函数名(形式参数)
{
   语句序列
}

注意: a.模板说明的虚拟参数必须在函数定义中至少出现一次;
b.函数参数表中既可以使用虚拟参数,又可以使用一般参数。

//函数模板:
template<typename T>
void myswap(T& a,T& b)
{
    T temp = a;
    a = b;
    b = a;
}
//函数模板的调用:
int a = 1, b = 2;
//1.显示类型调用:
    myswap<int>(a,b);
//2.自动类型调用:(一般较少使用)
    myswap(a,b);

函数模板当参数

template<typename T>
void MySwap(T* arr,int length)
{
    for (int i=0;i<length;i++)
    {
        for (int n=i+1;n<length;n++)
        {
            if (arr[i]>arr[n])
            {
                T temp = arr[i];
                arr[i] = arr[n];
                arr[n] = temp;
            }
        }
    }
}

template<typename T>
void Printf(T * arr,int len)
{
    for (int i=0;i<len;i++)
    {
        cout << arr[i] << endl;
    }
}

int main()
{
    //需求: 对不同类型的数组进行排序(int char)
    int     brr[5] = {1,5,6,2,3};
    char    crr[] = "asddsc";
    //交换
    MySwap<int>(brr,5);
    int len = strlen(crr);
    MySwap<char>(crr,len);
    ////输出
    Printf<int>(brr,5);
    Printf<char>(crr,len);
    return 0;
}

函数模板遇上函数重载(函数模板和普通函数成为函数重载)

template <typename T>
void myswap(T &a, T &b)
{
    T t;
    t = a;
    a = b;
    b = t;
    cout << "myswap 模板函数do" << endl;
}

void myswap(char &a, int &b)
{
    int t;
    t = a;
    a = b;
    b = t;
    cout << "myswap 普通函数do" << endl;
}

void main()
{
    char cData = 'a';
    int  iData = 2;

    //myswap<int>(cData, iData);  //结论 函数模板不提供隐式的数据类型转换  必须是严格的匹配
    myswap(cData, iData);
    return;
}

函数模板调用将按照严格的类型进行匹配,不会自动类型转换。
普通函数调用可以隐式的类型转换。


函数模板和普通函数调用规则研究

我们首先说结论:
1. 函数模板可以像普通函数一样被重载;
2. 当普通函数和函数模板都符合调用时,会优先选择普通函数调用;
3. 可以通过空模板实参列表(<>)的语法限定编译器只通过模板匹配;
4. 如果函数模板能产生更好的匹配(普通函数需要隐式转换),使用函数模板。

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)
{
    cout << "T Max(T a, T 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);
}


void main()
{
    int a = 1;
    int b = 2;

    cout << Max(a, b) << endl;          //当函数模板和普通函数都符合调用时,优先选择普通函数
    cout << Max<>(a, b) << endl;        //若显示使用函数模板,则使用<> 类型列表

    cout << Max(3.0, 4.0) << endl;      //如果 函数模板产生更好的匹配 使用函数模板

    cout << Max(5.0, 6.0, 7.0) << endl; //重载

    cout << Max('a', 100) << endl;      //调用普通函数 可以隐式类型转换 
    system("pause");
    return;
}

猜你喜欢

转载自blog.csdn.net/wue1206/article/details/81357644