1.函数重载的概念
在C++中可以为两个或两个以上的函数提供相同的函数名称,只要参数类型不同,或参数类型相同而参数个数不同,称为函数重载。
在C语言中实现int,char,double类型的比较大小函数:
int my_max_i(int a,int b){return a > b ? a : b;}
char my_max_ch(char a,char b){return a > b ? a : b;}
double my_max_d(double a,double b){return a > b ? a : b;}
这些函数都执行了相同的一般性动作,都返回两个形参中的最大值。
在C++中使用函数重载来实现int,char,double类型的比较大小函数:
#include<iostream>
using namespace std;
int my_max(int a,int b)
{
return a > b ? a : b;
}
char my_max(char a, char b)
{
return a > b ? a : b;
}
double my_max(double a, double b)
{
return a > b ? a : b;
}
int main()
{
int ix = my_max(12, 23);
cout << "ix=" << ix << endl;
char chx = my_max('a', 'b');
cout << "chx=" << chx << endl;
double dx = my_max(12.23, 34.45);
cout << "dx=" << dx << endl;
return 0;
}
输出结果为:
编译器的工作:
当一个函数名在同一个域中被声明多次时,编译器按如下步骤解释第二个(以及后续的)的声明。
如果两个函数的参数表中参数的个数或类型或顺序不同,则认为这两个函数是重载。
例如:
//重载函数
void print(int a, int b);
void print(char a,char b);
2.判断函数重载的规则
(1)如果两个函数的参数表相同,但是返回类型不同,会被标记编译错误,原因是函数的重复声明。
//错误
int my_max(int a, int b){}
unsigned int my_max(int a, int b) {}
只有返回类型不同,函数的返回类型不足以区分两个重载函数,无法重载仅按返回类型区分的函数。
(2)参数表的比较过程与形参名无关。
//错误
int my_add(int a,int b);
int my_add(int x,int y);
形参名不同不可以构成函数重载
(3)如果在两个函数的参数表中,只有缺省实参不同,则第二个声明被视为第一个声明的重复声明。
只有缺省参数不同不可以构成函数重载
void Print(int*br,int n);
void Print(int *br,int len=10);
(4)typedef名为现有的数据类型提供了一个替换名,它并没有创建一个新类型,因此,如果有两个函数参数表的区别只在于一个使用了typedef,而另一个使用了与typedef相应的类型,则该参数表被视为相同的参数表,从而不可以构成函数重载。下列Print()
的两个函数声明被视为具有相同的参数表,第二个声明导致编译时刻错误,因为虽然它声明了相同的参数表。
//错误
typedef unsigned int u_int;//typedef 并不引入一个新类型
//错误: 相同参数表,相同返回类型
int Print(u_int a);
int Print(unsigned int b);
(5)当一个参数类型是const 或volatile 修饰时,如果形参是按值传递方式定义,在识别函数声明是否相同时并不考虑const 和volatile 修饰符。
// 声明同一函数
void f( int );
void f( const int );
参数是const 这只跟函数的定义有关系,它意味着函数体内的表达式不能改变参数的值,但是对于按值传递的参数,这对函数的用户是完全透明的,用户不会看到函数对按值传递的实参的改变。当实参被按值传递时,将参数声明为const之后就不会改变可以被传递给该函数的实参种类,任何int 型的实参都可以被用来调用函数f(const int) ,因为两个函数接受相同的实参集,所以刚才给出的两个声明并没有声明一个重载函数,然后将函数f()可以定义为:
void f( int i ) { }
void f( const int i ) { }
然而在同一个程序中同时提供这两个定义将产生错误,因为这两个定义把一个函数定义了两次,还是没有构成函数重载。
(6)当一个形参类型有const或者volatile修饰时,如果形参定义指针或引用时,在识别函数声明是否相同时,就要考虑const和volatile修饰符。
//下列两个声明声明了不同的函数
void fun(int *p){}
void fun(const int *p){}
//下列两个声明声明了不同的函数
void fun(int &a){}
void fun(const int &a){}
(7)注意函数调用的二义性
如果在两个函数的参数表中,形参类型相同,而形参个数不同,形参默认值将会影响函数的重载。
void fun(int a){}
void fun(int a,int b){}
void fun(int a,int b=10){}
(8)函数重载解析步骤
①确定函数调用考虑的重载函数的集合,确定函数调用中实参表的属性。
②从重载函数集合中选择函数,该函数可以在(给出实参个数和类型)的情况下调用函数。
③选择与调用最匹配的函数。
3.函数重载的规则
函数名称必须相同。
参数列表必须不同(个数不同、类型不同、参数排列顺序不同等)。
函数的返回类型可以相同也可以不相同。
仅仅返回类型不同不足以成为函数的重载。
4.函数重载的作用
重载函数通常用来在同一个作用域内用同一个函数名去命名一组功能相似的函数,这样做减少了函数名的数量,避免了名字空间的污染,对于程序的可读性有很大的好处。