模板(三) 函数模板

一、函数模板介绍

函数模板是一个生成函数的公式,可以用来生成针对特定类型的函数版本;

如:求两个具有相同的数据类型的数值中的最大值;普通的一个函数只能使用于某种特定类型,不能适用于其他数据类型,而使用函数模板则可以进行泛型编程,

对于使用该函数模板的各个数据类型在编译时期则会生成相应的适用于该数据类型的函数版本,这样就避免对于每一种数据类型编写相应的函数版本,

可以加快开发速度,减少不必要的重复代码。

template<typename T>
T Max(const T &lhs, const T &rhs)
{
    return lhs > rhs ? lhs : rhs;
}

 

二、函数模板定义

1、函数模板定义方式: 以关键字template开始,后接由一个或者多个模板参数组成的模板参数列表,通常模板参数可以是模板类型参数或者非类型模板参数;

2、模板参数的作用:模板参数表示在类或者函数作用域中需要用到的类型或者值,在使用模板时,通过显式或者隐式的指定模板实参,可以将其绑定到模板参数上

 

三、函数模板的使用与实例化

    a = 0.0, b = 1.0;
    std::cout << Max(a, b) << endl;

在使用函数模板时,编译器在编译时期会根据使用函数模板的对象来推断出函数模板实参,并由推断出来的函数模板实参实例化一个特定版本的函数;

编译器实例化一个特定版本的函数时,会用推断出的函数模板实参替代函数模板中的模板参数,这些编译器生成的特定版本的函数通常被称为该模板的实例

在上面的例子中,会生成如下的特定版本的函数;

double Max(const double &lhs, const double &rhs)
{
    return lhs > rhs ? lhs : rhs;
}

 

四、函数模板实参推断

1、模板实参推断:在函数模板被使用时,编译器会根据模板函数的实参来推断出函数模板的实参,这个过程称为模板实参推断

2、模板实参与形参的类型转换:如果一个函数形参类型使用了函数模板实参,那么将根据下面的规则对实参进行类型转换,再进行模板实参推断

(1)const转换:可以将一个非const对象的引用或者指针传递给一个const引用或者指针

(2)数组或者函数指针转换:如果函数形参为非引用类型,则可以对一个数组或者函数类型的实参应用正常的指针转换;

 

五、函数模板显式实参

在函数模板中,编译器可以根据函数模板的实参来推断出函数模板的实参,但当函数的返回值的类型与函数的所有形参的类型不同时,编译器根据调用该

模板函数的实参推断出函数返回值的类型,这时需要显式的指定实参;如定义一个求最大值的函数,其接受两个相同类型的函数实参,如int、unsigned类型,

但是需要返回float或者double类型;

template<typename T, typename U>
T Max(const U &lhs, const U &rhs)
{
    return lhs > rhs ? lhs : rhs;
}

int main()
{
    unsigned u_a = 0, u_b = 1;
    int int_a = 0, int_b = -1;

    std::cout << Max<double>(u_a, u_b) << endl;
    std::cout << Max<float>(int_a, int_b) << endl;

    return 0;
}

当使用函数模板实参时,函数模板实参按照从左到右的顺序匹配函数模板参数列表中的模板参数;函数模板参数列表中未匹配的模板参数根据函数模板的实参推断进行匹配

 

六、函数重载与模板

函数模板可以被普通非模板函数或者另一个模板函数重载,重载的函数具有相同的名字且具有不同数量或者类型的参数;

对于某个函数调用,如果被调用函数被多个普通非模板函数和多个模板函数重载,那么其函数匹配规则将会变得复杂;

涉及到函数模板的函数匹配规则如下:

(1)确定候选函数集合:所有能够成功进行形参与实参匹配的普通非模板函数与所有模板实参推断成功的模板函数;

(2)函数匹配程度排序:可行函数(非模板函数与模板函数)按照类型转换排序;

(3)如果存在某一个函数比其他函数提供更好的匹配,则选择调用该函数;否则,按照以下规则选择匹配函数:

<1>同样好的匹配函数中有非模板函数,优先选择;

<2>同样好的匹配函数中没有非模板函数,但在所有模板函数中存在一个模板函数比其他函数更加特例化,则选择该模板函数;

<3>否则,匹配失败;

时间: 2024-11-09 17:09:42

模板(三) 函数模板的相关文章

类模板和函数模板

函数模板: 函数模板全特化:所谓特化,是指相对普通模板的特化,是另外一个模板.但不是实例,只是模板 template <class T>                                      //普通函数模板,泛型T mymax(const T t1, const T t2){   return t1 < t2 ? t2 : t1;} template <>const char* mymax(const char* t1,const char* t2)  

函数模板,函数模板重载,可变参数模板,函数模板覆盖,通过引用交换数据

 1.函数模板初级,如果想使用模板,需要实例化,实例化的方式是加上<数据类型> #include <iostream> //函数模板可以对类型进行优化重载,根据类型会覆盖 //如果仍然要使用模板函数,需要实例化 template<class T> T add(T a, T b) { std::cout << "T add " << std::endl; return a + b; } int add(int a, int

模板类与类模板、函数模板与模板函数等的区别

在C++中有好几个这样的术语,但是我们很多时候用的并不正确,几乎是互相替换混淆使用.下面我想彻底辨清几个术语,这样就可以避免很多概念上的混淆和使用上的错误.这几个词是: 函数指针——指针函数 数组指针——指针数组 类模板——模板类 函数模板——模板函数 最终在使用中,我们就可以让它们实至名归,名正言顺. 1.函数指针——指针函数   函数指针的重点是指针.表示的是一个指针,它指向的是一个函数,例子: int   (*pf)(); 指针函数的重点是函数.表示的是一个函数,它的返回值是指针.例子:

C++入门经典-例9.1-函数模板,函数模板的作用,使用数组作为模板参数

1:函数模板不是一个实在的函数,因此编译器不能为其生成可执行的代码.定义函数模板只是一个对函数功能框架的描述,在具体执行时,将根据传递的实际参数决定其功能. 2:函数模板定义的一般形式如下: template <类型形式参数> 返回类型 函数名(形式参数表) { ...//函数实现 } 其中template为关键字,表示定义一个模板,尖括号"<>"中为模板参数,模板参数主要有两种,一种是模板类型参数,另一种是模板非类型参数.上述代码中定义的模板使用的是模板类型参

类模板和函数模板引发的思考

首先我们在学习类模板和函数模板时候会遇到这样一个问题: 类模板 与模板类 函数模板与模板函数 这些不仅仅是简单的文字游戏,而是需要我们深深的区分一下才可以理解其中的奥秘! 再回想一下我们在学习C语言的时候也遇到了这样几个类似的名词 函数指针与指针函数 数组指针与指针数组 函数指针即是重点在后边的名词指针,前边的函数只是修饰名词指针的一个定语而已,欧,这是一个语文的奥秘哟,忽然觉得自己好博学,言归正传,重点在指针,那就是指向一个函数的指针,其中保存了这个函数的地址通过指针解引用可以调用这个函数 就

C++模板(类模板、函数模板)

1.在c++Template中很多地方都用到了typename与class这两个关键字,而且好像可以替换,是不是这两个关键字完全一样呢? 答:class用于定义类,在模板引入c++后,最初定义模板的方法为:template<class T>,这里class关键字表明T是一个类型,后来为了避免class在这两个地方的使用可能给人带来混淆,所以引入了typename这个关键字,它的作用同class一样表明后面的符号为一个类型,这样在定义模板的时候就可以使用下面的方式了:      template

C++STL - 函数模板

模板主要是为了泛型编程,做到与类型无关 模板有函数模板和类模板,本文主要整理的是函数模板 1.函数模板定义 template<typename 类型形参1,typename 类型形参2,...> 返回类型 函数模板名(调用形参表){函数体} 在返回类型,调用形参表和函数体中,所需要类型的地方都可以引用模板形参表中类型形参 template<typename A,typenamen B,typename _C> A function(B arg){ _C var; ... } 2.使

函数模板注意事项

一.模板重载 ①和常规重载一样,被重载的模板的函数特征标必须不同. ②并非所有的模板参数都必须是模板参数类型.例如: template<class T> void swap(T& a,T& b); template<class T> void swap(T* a,T* b,int n);//第三个参数类型为具体类型int,而不是通用类型 二.显示具体化 对于某些类型的参数,我们的算法可能略有不同,比如:对于一个结构体,虽然将一个结构体赋给另一个结构体是允许的,但是,

C++--模板的概念和意义、深入理解函数模板、类模板的概念和意义

一.模板的概念与意义 Q:C++中有几种交换变量的方法?定义宏代码与定义函数A.定义宏代码优点:代码复用,适合所有的类型缺点:编译器不知道宏的存在,缺少类型检查B.定义函数优点:真正的函数调用,编译器对类型进行检查缺点:根据类型重复定义函数,无法代码复用 C.泛型编程--不考虑具体数据类型的编程方式Swap泛型写法中的T不是一个具体的数据类型,而是泛指任意的数据类型C++中的泛型编程函数模板--一种特殊的函数可用不同类型进行调用,看起来和普通函数很相似,区别是类型可被参数化函数模板的语法规则1.