函数重载
所谓函数重载是指同一个函数名可以对应着多个函数的实现。
确定函数实现时,要求从函数参数的个数和类型上来区分。
- 参数个数不同
- 参数类型不同。
为什么要重载一个函数名?
希望定义一组函数,它们执行同样的动作,但是应用在不同的参数类型上。
例如:假设定义一个函数,它返回参数中的最大值。
如果没有重载一个函数名的能力,那么我们就必须为每个函数给出一个惟一的名字 例如如下定义一组 max()函数:
int i_max( int, int );
float f_max( float,float );
double d_max( double,double );
这些函数都执行了相同的动作,都返回参数集合中的最大值,从用户的角度来看,只有一种操作,就是判断最大值。至于怎样完成其细节,函数的用户一点也不关心。
这种词汇上的复杂性不是判断一组数中最大值问题本身固有的,而是反映了程序设计环境的一种局限性。在同一个域中出现的名字必须指向一个惟一的对象,函数,class 类型等等。
这种复杂性给程序员带来了一个实际问题,他们必须记住或查找每一个名字,函数重载把程序员从这种词汇复杂性中解放出来。
在 C++中,可以为两个或多个函数提供相同的名字,只要它们的每个参数表惟一或者是参数的个数不同,或者是参数类型不同,下面是重载函数 max()的声明:
int max( int, int);
float max( float,float );
double max( double,double );
在代码区键入如下代码,编译运行查看结果:
#include <iostream>
using namespace std;
int max(int a,int b)
{
return a>b?a:b;
}
float max(float a,float b)
{
return a>b?a:b;
}
double max(double a,double b)
{
return a>b?a:b;
}
void main()
{
cout<<max(3,5)<<endl;
cout<<max(3.14f,1.23f)<<endl;
cout<<max(2.0,1.5)<<endl;
system("pause");
}
如果两个函数的返回类型和参数表精确匹配,则第二个声明被视为第一个的重复声明,例如:
void print( const string &str );
void print( const string & );
如果两个函数的参数表相同,仅仅是返回值类型不同,那么第二个函数声明被视为第一个函数声明的错误重复声明,会导致程序产生编译性错误,例如:
unsigned int max( int _a, int _b );
int max( int , int );
函数的返回值类型不同,不能构成函数的重载
在代码区键入如下代码,编译运行查看结果:
#include <iostream>
using namespace std;
int max(int a,int b)
{
return a>b?a:b;
}
float max(int a,int b)
{
return a>b?a:b;
}
double max(int a,int b)
{
return a>b?a:b;
}
void main()
{
system("pause");
}
编译器将会提示如下错误:
如果在两个函数的参数表中,只有可选参数不同,则第二个函数声明被视为第一个函数的重复声明,例如:
#include <iostream>
using namespace std;
int max(int _a , int _b = 3)
{
return _a>_b?_a:_b;
}
int max(int _a , int _b = 4)
{
return _a>_b?_a:_b;
}
void main()
{
max(2);
system("pause");
}
编译器将会提示如下错误:
仅仅靠修饰符const 标注的参数,如果参数的类型一样,则也不能构成函数重载,例如:
#include <iostream>
using namespace std;
int max(int _a , int _b)
{
return _a>_b?_a:_b;
}
int max(const int _a ,const int _b)
{
return _a>_b?_a:_b;
}
void main()
{
system("pause");
}
编译器将会提示如下错误:
当重载的函数中有缺省参数的时候,还有种情况也会发生参数不明:
如以下代码,如果调用的函数为Test(‘A’)时,就会发生参数调用不明的情况,因为在调用的时候不写缺省参数,因此编译器认为以上声明的函数都有可能,所以就会发生参数调用不明确。
#include <iostream>
using namespace std;
void Test(char _a)
{
cout<<_a<<endl;
}
void Test(char _a,int _b = 0)
{
cout<<_a<<_b<<endl;
}
void main()
{
Test('A');
Test('A',10);
system("pause");
}
当我们调用红色Test(‘A’)时,程序会报出如下错误:
当我们调用Test(‘A’,10)时,程序能够正确执行! 为什么?
函数重载解析:一个重载函数在被调用的时候,会根据实参来决定调用的哪一个函数。
函数重载之所以会报错,是因为:
- 根据实参不能匹配重载函数中的任何一个
- 根据实参能够匹配重载函数的2个或2个以上,导致了对于重载函数的调用不明确
函数重载解析的过程有三个步骤:
- 确定函数调用考虑的重载函数的集合,确定函数调用中实参表的属性。
- 从重载函数集合中选择函数,该函数可以在给出实参个数和类型的情况下,用函数调用中指定的实参进行调用。
- 选择与调用最匹配的函数。
函数参数传递中的内存管理
当我们在调用一个函数的时候,系统会在被调函数内部开辟形参类型所占用的内存空间,将实参的值存入到开辟的内存空间中。
当该函数结束的时候,系统分配的内存空间会自动收回。
在代码区键入如下代码,编译运行查看结果:
#include <iostream>
using namespace std;
int Test( int _iValue )
{
int iTemp = _iValue;
cout<<iTemp<<endl;
return iTemp+10;
}
void main()
{
cout<<Test(10)<<endl;
cout<<_iValue<<endl; //错误的,无法访问Test函数的形参
cout<<iTemp<<endl; //错误的,无法访问Test函数内部的变量
system("pause");
}
①本次学习了C++中的函数重载,并且分析了函数重载可能会发生的二义性,以及二义性的处理,使用好重载也是面向对象编程中的重点。
②函数在调用过程中内存如何进行分配。是后续学习的基础
③关于复杂函数参数类型(指针型参数、引用型参数、常量指针、常量引用等参数类型,我们将在学习了“指针”后为大家讲解)
学习资料领取:
https://pan.baidu.com/s/1VX_zb_eqWH_coos1ZB9QQw
提取码:w8st
学习从来都不是一个人的事,如果你感觉小编的这篇文章对你有帮助的话,可以关注小编首页和小编来一起学习C/C++语言,小编会持续更新后续的内容哦!!