C++函数模板

C++另一种编程思想称为泛型编程,主要采用的技术就是模板

C++提供两种模板机制:函数模板和类模板。本片文章我们介绍一下函数模板。类模板看另外一篇C++类模板 

一、函数模板

1、作用

建立一个通用函数,其函数返回值和形参类型可以不具体制定。用一个虚拟的类型来表示

2、语法

template<typename T>
函数声明或定义

template——声明模板

typename——表明后面的符号是一种数据类型,可以用class来代替

T——通用的数据类型,可以替换,但一般都是大写字母

3、注意事项

1、自动类型推导,必须要推导出一致的数据类型T才可以使用

2、模板必须要确定T的数据类型才可以使用

下面的例子来解释上面:

#include <bits/stdc++.h>
using namespace std;
const int maxn = 1e5 + 5;
template<class T>
void swapp(T &a ,T &b)
{
    T tmp=a;
    a=b;
    b=tmp;
}
template<class T>
void fun()
{
    cout<<"I am fine"<<endl;
}
int main()
{
    int a=10,b=20;
    char c='c';
    //使用函数模板第一种方式:自动类型推导
    //swapp(a,b);

    //使用函数模板的第二种方式:显式指定类型,这种方法可以发生隐式类型转换
    swapp<int>(a,b);

    //自动类型推导,必须要推导出一致的数据类型T才可以使用
    //swapp(a,c);  报错

    //模板必须要推导出确定的T的数据类型,才可以使用
    //fun(); //报错,模板不知道数据类型T
    fun<int>(); //正确,随便给一个数据类型就可以

    printf("%d %d\n",a,b);
    return 0;
}

二、普通函数与函数模板的调用规则

1、如果普通函数和函数模板都可以实现,优先调用普通函数

//如果普通函数和函数模板都可以实现,优先调用普通函数
#include <bits/stdc++.h>
using namespace std;
const int maxn = 1e5 + 5;
template<class T>
void swapp(T a ,T b)
{
    cout<<"function template"<<endl;
}
void swapp(int a ,int b); //如果只有函数声明没有函数实现,会报错
// void swapp(int a ,int b) //如果这个函数存在,那么先调用这个函数
// {
//     cout<<"simple template"<<endl;
// }
int main()
{
    int a=10,b=20;
    swapp(a,b);
    return 0;
}

2、可以利用空模板参数列表来强制调用函数模板

//可以利用空模板参数列表来强制调用函数模板
#include <bits/stdc++.h>
using namespace std;
const int maxn = 1e5 + 5;
template<class T>
void swapp(T a ,T b)
{
    cout<<"function template"<<endl;
}
void swapp(int a ,int b); //不会报错,因为偶没有调用这个函数
// void swapp(int a ,int b) //如果这个函数存在,那么先调用函数模板
// {
//     cout<<"simple template"<<endl;
// }
int main()
{
    int a=10,b=20;
    //通过空模板参数列表就可以的强制调用函数模板
    swapp<>(a,b);
    return 0;
}

3、函数模板也可以发生重载

4、如果函数模板可以产生更好的匹配,优先调用函数模板

//如果函数模板可以产生更好的匹配,优先调用函数模板
#include <bits/stdc++.h>
using namespace std;
const int maxn = 1e5 + 5;
template<class T>
void swapp(T a ,T b)
{
    cout<<"function template"<<endl;
}
void swapp(int a ,int b); //不会报错,因为没有调用这个函数
// void swapp(int a ,int b) //如果这个函数存在,那么先调用函数模板
// {
//     cout<<"simple template"<<endl;
// }
int main()
{
    char a=10,b=20;
    //因为调用普通函数需要发生隐式类型转换(char->int),而调用函数模板就不需要
    swapp(a,b);
    return 0;
}

三、模板的局限性

有些特定数据类型,需要用具体换方式做特殊实现

#include <bits/stdc++.h>
using namespace std;
class Person
{
public:
    Person(string name, int age)
    {
        this->m_Name = name;
        this->m_Age = age;
    }
    string m_Name;
    int m_Age;
};
//普通函数模板
template <class T>
bool myCompare(T &a, T &b)
{
    if (a == b)
    {
        return true;
    }
    else
    {
        return false;
    }
}
//具体化,显示具体化的原型和定意思以template<>开头,并通过名称来指出类型
//具体化优先于常规模板
template <>
bool myCompare(Person &p1, Person &p2)
{
    if (p1.m_Name == p2.m_Name && p1.m_Age == p2.m_Age)
    {
        return true;
    }
    else
    {
        return false;
    }
}
void test01()
{
    int a = 10;
    int b = 20;
    //内置数据类型可以直接使用通用的函数模板
    bool ret = myCompare(a, b);
    if (ret)
    {
        cout << "a == b " << endl;
    }
    else
    {
        cout << "a != b " << endl;
    }
}
void test02()
{
    Person p1("Tom", 10);
    Person p2("Tom", 10);
    //自定义数据类型,不会调用普通的函数模板
    //可以创建具体化的Person数据类型的模板,用于特殊处理这个类型
    bool ret = myCompare(p1, p2);
    if (ret)
    {
        cout << "p1 == p2 " << endl;
    }
    else
    {
        cout << "p1 != p2 " << endl;
    }
}
int main()
{
    test01();
    test02();
    system("pause");
    return 0;
}

 

posted @ 2021-05-02 17:52  kongbursi  阅读(548)  评论(0编辑  收藏  举报