我是靠谱客的博主 从容柚子,最近开发中收集的这篇文章主要介绍【C++】函数重载与函数模板,觉得挺不错的,现在分享给大家,希望可以做个参考。

概述

前言:
之所以将函数重载和函数模板放在一起来讲,是因为二者皆能够产生函数名相同而作用不相同的函数。函数重载的关键是函数的参数列表(也称函数特征标),C++允许定义名称相同而参数列表不同的函数,在使用这样的同名函数时,编译器将根据所传递的参数选择对应的函数原型;而函数模板更像是一个通用的函数描述,通过将具体的类型(int和double等)作为参数传递给模板,则可以使编译器产生对应类型的函数。下面将分别介绍函数的重载和模板。

一:函数重载
重载函数就如同写作文时使用的多义词,比如说“门槛”这个词,既可以表示门框下端的横木条、石条或金属条,又可以表示一件事的困难程度。只有结合语境和上下文,读者才能分辨到底表示的是哪个意思。同样,当存在多个同名的函数时,编译器会根据传入参数的数据类型和个数确定使用哪个函数。即是说编译器判断重载函数时的关键是函数的参数列表,具体来说就是参数的数目,类型和排列顺序,这其中不包括参数名!参数名对重载函数来说是无关紧要的。接下来以一段代码为例演示重载函数的用法:

void show(const char * name,int age);  //N0.1
void show(int age,int length);         //NO.2
void show(double width, int length);   //NO.3
void show(const char * name);          //NO.4

那么在调用show()函数时,就会根据传递给其的参数确定使用哪个函数,比如:

show("Alex",10);  //对应NO.1
show(10,20);      //对应NO.2
show(3.1416,20);  //对应NO.3
show("Alex");     //对应N0.4

<注1>在使用被重载的函数时,一定记得需要正确的传递参数,否则如果没有函数原型与之匹配,编译器就会报错。
<注2>引用变量和原变量不能作为共存的特征标,比如:

double cube(double x);
double cube(double &x); 

这样的声明是错误的,因为编译器将类型引用和类型本身作为同一个特征标,因此编译器将无法判断使用哪个原型,将引发混乱。
<注3>匹配函数时,不区分const和非const变量;同时,是特征标而非返回值可以对函数进行重载,比如说下面这样的声明就是错误的:

int sum(int x,int y);
double sum(int x,int y);

<注4>首先,函数重载的关键是函数的参数列表,但是调用函数时传递的参数不同不一定代表是重载函数,比如说下面这段代码:

 int x;
 x = sum()
 x = sum(1);
 x = sum(1,2);
 x = sum(1,2,3);

乍一看,四次调用sum函数有着完全不同的参数列表,那这是不是意味着这里是四个重载的函数呢?答案是无法确定,因为有默认参数的存在,C++允许使用不同数目的参数调用同一个函数,所以如果sum函数使用了默认参数,那么上面这段代码实际上是调用的一个函数,甚至在某些特定情况下,不仅调用的是同一个函数,甚至四次返回的值都是一样的。比如说:

 int sum(int a=1,int b=2,int c=3){
 a += b + c;
 return a;
}

由此可见,虽然重载函数的关键是参数列表,但是实质上却是调用名称相同的不同函数。可以使用函数重载来设计一系列完成同样工作但参数列表不同的函数。所以虽然函数重载很方便很诱人,但是不应该随意使用他,仅当函数基本上实现同样的任务,但使用不同类型的数据时才应该使用函数重载。
其实,函数的重载的定义是简单的,但是其为十分重要的操作符的重载做了铺垫,所以仍然应该认真学习这部分内容。

二:函数模板
<1>函数模板简介
函数模板是C++新增的一项特性,函数模板是通用的函数描述,使用通用类型来定义函数,其中的通用类型可以用具体的类型(int和double等)来代替,通过将类型作为参数传递给模板,编译器将生成该类型的函数。
为了创建一个函数模板,需要使用语句:

template <class Any> //也可以使用template<typename Any>

这句代码的含义是建立一个函数模板,将其类型设为Any。之后的函数体内部,只需要用Any替换所有参数类型即可。比如下面这个简单的交换函数:

 template <class Any>
 void Swap(Any &a, Any &b){
 Any temp;  //定义一个任意类型的变量
 temp = a;
 a = b;
 b = temp; 
}

这样就成功定义了一个函数模板了,在使用函数模板时,将特定的类型传递给模板即可,比如下面这段主函数:

 int main(){
 int x = 1;
 int y = 2;
 Swap(x,y); 
 cout<<x<<" "<<y;
 return 0;
}

这段代码表示将两个int类型传递给函数模板,因此编译器生成该函数的int类型版本,即是说编译器会将函数模板内的所有Any替换为int。至此,函数模板就成功创建并使用了。
但是读者读到这里可能不禁有一些问题:函数的返回值类型可不可以设置为Any,可不可以传递不同类型的参数给函数模板,在函数体内部创立的临时变量的类型是否与Any一致等等。
实际上,之所以会存在这些问题,是因为对Any的认识不足,Any确实可以表示任意的类型,但是Any不能存在多义性,同一个函数模板的Any只能表示一种类型。即是说不能将int和double同时传入一个函数模板,因为这样会让Any产生二义性从而使编译器产生报错。既然如此,那么也代表着函数体内部创立的临时变量也是跟传入其中的类型一致的。即是说,在参数列表中Any是什么类型,整个函数模板的Any就是什么类型。但是这并不代表不能使用函数处理多个类型不同的数据,比如说下面这两个函数模板:

template <class Any>
void Sum(Any a,double b);  //接受一个任意类型和double类型
template <class Any>
void Show(const char * n,Any b);  //接受一个字符串指针和任意类型

同时,函数模板的返回值类型可以设置为Any,即返回和传入函数模板相同类型的数据,也可以主动设置为int或者double等,这样返回时编译器会将返回值自动强制转化为设置的类型。
可以看出,使用函数模板能够使多个函数定义更简单,更可靠。

<2>函数模板的具体化和实例化
需要注意的是,在代码中包含的函数模板本身并不会产生函数定义,函数模板只是一个用于生成函数的方案,只有当编译器为特定类型生成函数定义时才得到函数实例。
最初,模板只能隐式的实例化,即通过传入模板的数据类型确定Any类型来实例化,但现在C++也允许使用显式实例化,这意味着可以直接命令编译器创建特定的实例,其用法是:声明所需种类,用<>指示类型并在前面加上关键字template,比如刚才的Swap()函数的显式实例化为:

template void Swap<int>(int,int);

而显式具体化则使用下面两种方式:

template void Swap<int>(int &,int &);
//或者
template void Swap(int &,int &);

函数模板实例化的语句作用是使用Swap()模板生成int类型的函数定义,而函数模板具体化的意思是不使用函数模板生成函数定义而是使用独立的,专门的函数定义显式的为int类型生成函数定义。显式实例化和显式具体化的区别在于显式具体化在template后有<>而实例化没有。
隐式实例化,显式实例化和显式具体化统称为具体化,表示的都是具体的函数定义而非通用表达。

最后

以上就是从容柚子为你收集整理的【C++】函数重载与函数模板的全部内容,希望文章能够帮你解决【C++】函数重载与函数模板所遇到的程序开发问题。

如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(87)

评论列表共有 0 条评论

立即
投稿
返回
顶部