函数的重载
对于出现在相同作用域的两个函数,如果它们的名字相同,而行参不同,则称为重载函数。
举一个简单的例子,假设电话号码本中有序号、人名,号码等信息。我们希望通过一个输入其中的一个来或得这个人完整的信息。
要完成这个功能,我们需要定义3个函数:
Record lookup(const Account&); // find by Account
Record lookup(const Phone&); // find by Phone
Record lookup(const Name&); // find by Name
Record r1, r2;
r1 = lookup(acct); // call version that takes an Account
搜索函数的名字通常都定义的相同(没有人希望对于不同的搜索内容,还要掌握不同的函数名),但是这些函数的形参却不相同(可以是序号,也可以是人名,也可以是电话号码)。
注意:如果两个函数声明的返回类型和形参列表完全匹配,则第二个函数是第一个函数的重复声明;如果两个函数仅是返回类型不同,而行参列表相同,则第二个函数是错误的。
重载函数的关键是编译器如何决定在调用该函数时,使用重载函数中的哪一个。
先看一个特殊的情况,两个函数在不同的作用域中:
在定义变量时,我们知道,局部变量会屏蔽全局变量;同理局部函数(虽然我们很少这样定义),则会屏蔽全局的重载函数,举一个例子:
void print(const string &);
void print(double); // overloads the print function
void fooBar(int ival)
{
void print(int); // new scope: hides previous instances of print
print("Value: "); // error: print(const string &) is hidden
print(ival); // ok: print(int) is visible
print(3.14); // ok: calls print(int); print(double) is hidden
}
这是因为,调用 print 时,编译器首先检索这个名字的声明,找到只有一个 int 型形参的 print 函数的局部声明。一旦找到这个名字,编译器将不再继续检查这个名字是否在外层作用域中存在,即编译器将认同找到的这个声明即是程序需要调用的函数,余下的工作只是检查该名字的使用是否有效。
所以,下面的情况才会调用重载函数:
void print(const string &);
void print(double); // overloads print function
void print(int); // another overloaded instance
void fooBar2(int ival)
{
print("Value: "); // ok: calls print(const string &)
print(ival); // ok: print(int)
print(3.14); // ok: calls print (double)
如何确定到底使用的是哪个函数呢?举一个例子来说明:
void f();
void f(int);
void f(int, int);
void f(double, double = 3.14);
f(5.6);
首先要先确定候选函数,就是那些作用域相同,且名字相同的函数,这里的4个都是。
其次要选出可行的函数:形参个数与实参个数相同,形参类型与实参类型相匹配,或者实参能够隐式的转换为形参。特别要注意,因为有的函数可能提供了默认参数,所以在调用时,实参可能会比需求的少。
在这里,对于f(5.6),肯定不对的是void f()和void f(int, int),因为它们参数的个数不匹配。而void f(int)是可行的,因为可以通过隐式转换将double转为int;void f(double, double = 3.14);也是可行的,因为它的第二个参数提供了默认实参,而第一个形参则与实参完全匹配。
最后需要寻找最佳匹配。最佳指得是实参类型与形参类型越接近越好。所以,编译器会选用void f(double, double = 3.14),因为这里实参与形参的类型完全相同,而void f(int)还需要转化。
当然,也会出现找不到最佳匹配的情况,比如调用f(42, 2.56)时,void f(int, int)与void f(double, double = 3.14)都有一个实参精确匹配,另一个实参需要转化。出现这种情况,往往意味着你的重载函数设计的不合理。
有一点也需要注意如果函数返回值类型,函数名,形参都相同,唯一的区别在于形参多了const限定符修订的话,这种情况不属于重载,只是重复声明。原因在于函数在传递实参时,不论型参是否为const,都会复制实参,而且对形参的修改不会影响实参。所以,可以将const实参传递给const形参,也可以传递给非const形参。二者并无本质区别。
最后考虑类中的情况。在类中,也会遇到函数重载,规则跟上面是一样的,唯一要注意的是,成员函数只能重载本类的其他成员函数,不能重载其他类的成员函数或者类外的成员函数。
分享到:
相关推荐
(3)编写重载函数Maxl可分别求取两个整数,三个整数,两个双精度数,三个双精度数的最大值。 (4)使用重载函数模板重新实现上小题中的函数Maxl。 (5)使用系统函数pow(x,y)计算xy的值,注意包含头文件math.h。 ...
重载函数
重载函数模板与非模板函数示例 帮助初学者
void main() { int fab(int x); float fab(float x); double fab(double x); int ifab; float ffab; double dfab; cout; cin>>ifab; cout的绝对值为"(ifab); cout; cout;
对C++编译器区分重载函数无任何意义的信息是 A.参数类型B.参数个数.docx
sqrt对重载函数的调用不明确-的处理方法.txt,在编程过程中遇到的问题!
实现两个整数和三个浮点数的排序,按从小到大的顺序将排序结果输出。
通过string转换比较好些,很多重载函数要么是char * ,要么是String
重载函数相关知识
1、掌握重载函数概念及用法 2、掌握内联函数概念及用法 实验环境: VC++6.0 ;Clion;Visual Studio 2019 ; Visual Studio code 实验内容: ①在主函数给出数据,利用函数重载,分别求出三角形,梯形,圆的面积 ② 利用内联...
重载函数的小应用 用于初步了解重载函数 重载函数的小应用 用于初步了解重载函数 重载函数的小应用 用于初步了解重载函数
对Point类重载“++”、“--”运算符,实现坐标值的改变。 #include using namespace std; class point { public: point(){}; point(int a,int b) { x=a; y=b; } point operator++(); point operator++(int)...
C++ 重载运算符和重载函数 C++ 允许在同一作用域中的某个函数和运算符指定多个定义,分别称为函数重载和运算符重载。 重载声明是指一个与之前已经在该作用域内声明过的函数或方法具有相同名称的声明,但是它们的参数...
PB重载函数,利用PB也可以实现重载函数
matlab匿名函数M文件函数嵌套函数子函数私有函数重载函数.pdf
C++为什么要重载函数,以及如何实现重载函数机制。
编写一个重载函数,可变输入,可变输出。计算边长分别为a、b和c的一个三角形的周长及面积。公式是p=a+b+c,s=p/2,A=sqrt(s*(s-a)*(s-b)*(s-c))
此压缩文件是关于重载函数的细节,重整函数是C++中面对对象的函数表达方式