C++实现函数重载

来源:互联网 发布:linux 运动算法库 编辑:程序博客网 时间:2024/06/07 07:35

1、函数重载的概念:

重载函数是函数的一种特殊情况,C++允许在同一作用域中声明几个功能类似同名函数,这些同名函数的形参列表(参数个数、类型、顺序)必须不同,常用来处理实现功能类似数据类型不同的问题。也就是说c++中相同的函数名函数参数不同代表了不同的函数,当你去调用这些函数时,编译器可以根据你的传入参数的类型去判断你调用的是哪个函数。这样做减少了函数名的数量,避免了名字空间的污染,对于程序的可读性有很大的好处。

注:关于重载一定要注意:重载函数的参数类型和参数个数一定要不同(即:要么参数的类型不同,要么参数的个数不同,要么参数的类型和个数都不同),否则,编译器就不知道该调用那个函数了。


2、为什么需要函数重载(why)?

  • 试想如果没有函数重载机制,如在C中,你必须要这样去做:为这个print函数取不同的名字,如print_int、print_string。这里还只是两个的情况,如果是很多个的话,就需要为实现同一个功能的函数取很多个名字,如加入打印long型、char*、各种类型的数组等等。这样做很不友好!
  • 类的构造函数跟类名相同,也就是说:构造函数都同名。如果没有函数重载机制,要想实例化不同的对象,那是相当的麻烦!
  • 操作符重载,本质上就是函数重载,它大大丰富了已有操作符的含义,方便使用,如+可用于连接字符串等!

3、   调用匹配

      在定义完重载函数之后,用函数名调用的时候是如何去解析的?为了估计哪个重载函数最适合,需要依次按照下列规则来判断:

  • 精确匹配:参数匹配而不做转换,或者只是做微不足道的转换,如数组名到指针、函数名到指向函数的指针、T 
  • 到const T;
  • 提升匹配:即整数提升(如bool 到 int、char到int、short 到int),float到double 
  • 使用标准转换匹配:如int 到double、double到int、double到long double、Derived*到Base*、T*到void*、int到unsigned int;
  • 使用用户自定义匹配;
  • 使用省略号匹配:类似printf中省略号参数

如果在最高层有多个匹配函数找到,调用将被拒绝(因为有歧义、模凌两可)。


4、如何判断重载函数

void S();void S(int)void S(double, double = 1.2);void S(const char*, const char*);void Max (int ,int);//......int main (){S(2.4);return;}//S (2.4);的调用与S();//S(int);S(double,double = 1.2);S(const char*, const char*),//的声明在同一域,即是可见的

     编译器判断重载函数的第一步是确定该调用中所考虑的重载函数的集合,该函数集合被称为候选函数(candidant

function)。所谓候选函数就是与被调用函数同名的函数。上面的前四个函数都可以成为候选函数(当然可以是多个),

而唯有Max ( int , int ) 被排除在外了。

    编译器判断重载函数的第二步分为两动作。第一个动作是编译器从第一步选出的候选函数中调出可行函数(viable

function)。可行函数的函数参数个数与调用的函数参数个数相同(如S ( int )),或者可行函数的参数可以多一些,但是

多出来的函数参数都要有相关的缺省值(如 S (double , double =1.2 );)第二个动作是根据参数类型的转换规则将被调

用的函数实参转换(conversion)成候选函数的实参。这里本着充分利用参数类型转换的原则,换句话说,尽可能的使

用上参数类型转换。当然转换要以候选函数为转换的目标。上面的函数中只有两个是可行函数,它们分别是S ( int ); S

( double , double )。

     如果依照参数转换规则没有找到可行函数,则该调用就是错误的,则说没有函数与调用匹配,属于无匹配情况(no

match function)。

      编译器判断重载函数的第三步是从第二步中选出的可行函数中选出最佳可行函数(best match situation)。在最佳

可行函数的选择中,从函数实参类型到相应可行函数参数所用的转化都要划分等级,根据等级的划分(ranked),最后

选出最佳可行函数。最佳可行函数即编译器要调用的函数。


5、例子

1)参数类型上不同的重载函数

下面举一个在参数类型不同的重载函数的例子:

#include <iostream.h>

int add(int, int);

double add(double, double);

void main()

{

cout<<add(5, 10)<<endl;

cout<<add(5.0, 10.5)<<endl;

}

int add(int x, int y)

{

return x+y;

}

double add(double a, double b)

{

return a+b;

}


该程序中,main()函数中调用相同名字add的两个函数,前边一个add()函数对应的是两个int型数求和的函数实现,

而后边一个add()函数对应的是两个double型数求和的函数实现。这便是函数的重载。

以上程序输出结果为:

15

15.5

2)参数个数上不同的重载函数

下面举一个在参数个数上不相同的重载函数的例子:

#include <iostream.h>

int min(int a, int b);

int min(int a, int b, int c);

int min(int a, int b, int c, int d);

void main()

{

cout<<min(13, 5, 4, 9)<<endl;

cout<<min(-2, 8, 0)<<endl;

}

int min(int a, int b)

{

return a<b?a:b;

}

int min(int a, int b, int c)

{

int t = min(a, b);

return min(t,c);

}

int min(int a, int b, int c, int d)

{

int t1 = min(a, b);

int t2 = min(c, d);

return min(t1, t2);

}


该程序中出现了函数重载,函数名min对应有三个不同的实现,函数的区分依据参数个数不同,这里的三个函数实现

中,参数个数分别为2,3和4,在调用函数时根据实参的个数来选取不同的函数实现。

函数重载在类和对象应用比较多,尤其是在类的多态性中。在以后我们将碰到更多的在类型不同的函数重载,尤其是

在结合类的继承性和指针类型的不同,而这些都是我们以后用VC编程中经常要用到的。







原创粉丝点击