重载的定义
函数重载:多个函数拥有相同的名字,只要它们的参数列表不同即可。
参数列表又叫参数签名,包括参数的类型、参数的个数和参数的顺序,只要有一个不同就叫做参数列表不同。
函数的重载的规则:
- 函数名称必须相同。
- 参数列表必须不同(个数不同、类型不同、参数排列顺序不同等)。
- 函数的返回类型可以相同也可以不相同。
- 仅仅返回类型不同不足以成为函数的重载。
重载、重写、重定义的区别
重载:指的是在同一个作用域内,两函数的函数名可以相同,但是参数不能完全相同,至于返回值,不影响重载。
重写:指的在继承关系中,子类中定义了一个与父类极其相似的虚函数。
重定义:也叫隐藏,指的是在继承关系中,子类实现了一个和父类名字一样的函数,(只关注函数名,和参数与返回值无关),这样的话子类的函数就把父类的同名函数隐藏了。
重载的用途
重载函数通常用来在同一个作用域内,用同一个函数名,命名一组功能相似的函数,这样做减少了函数名的数量,避免了名字空间的污染,对于程序的可读性有很大的好处,常用来处理实现功能类似数据类型不同的问题。不要用同一函数名去实现完全不相干的功能,虽然程序也能运行,但可读性不好,使人觉得莫名其妙。
C++ 是如何做到函数重载的
C++代码在编译时会根据参数列表对函数进行重命名,例如void Swap(int a, int b)
会被重命名为_Swap_int_int
,void Swap(float x, float y)
会被重命名为_Swap_float_float
。当发生函数调用时,编译器会根据传入的实参去逐个匹配,以选择对应的函数,如果匹配失败,编译器就会报错,这叫做重载决议(Overload Resolution)。从这个角度讲,函数重载仅仅是语法层面的,本质上它们还是不同的函数,占用不同的内存,入口地址也不一样。
C++函数编译流程
函数调用时,编译器主要做了下面三件事情,依次如下:名字查找、重载决议、可访问性检测
- 名字查找:在做其他事情之前,编译器会查找所有同名函数作为候选,查找时不受访问权限的限制。
- 重载决议:目的是在候选列表中,按照参数列表找到唯一一个最佳匹配。
- 可访问性检查:编译器进行访问可行检测,确定被选定的函数是否可以被调用,主要指public、private这类关键字。
重载决议发生在可访问性检查之前,因此,如果私有函数不幸参与了重载决议,并且被选中,最终也会出现无法访问的编译提示。换句话说,私有参数,在名字查找和重载决议时并非是“私有的”。如下面的程序,编译不通过。
#include <iostream>
using namespace std;
class Stu
{
public:
double Test(double dValue) { return dValue * 13; };
private:
int Test(int iValue) { return iValue * 13; };
};
int main() {
int iValue = 13;
Stu stu;
cout << stu.Test(iValue) << endl;
return 0;
}