3.15.1 函数重载概述
能使名字方便使用,是任何程序设计语言的一个重要特征! |
我们现实生活中经常会碰到一些字在不同的场景下具有不同的意思,比如汉语中的多音字“重”。
当我们说: “他好重啊,我都背不动!”我们根据上下文意思,知道“重”在此时此地表示重量的意思。
如果我们说“你怎么写了那么多重复的代码? 维护性太差了!”这个地方我们知道,“重”表示重复的意思。
同样一个字在不同的场景下具有不同的含义。那么在c++中也有一种类似的现象出现,同一个函数名在不同场景下可以具有不同的含义。
在传统c语言中,函数名必须是唯一的,程序中不允许出现同名的函数。在c++中是允许出现同名的函数,这种现象称为函数重载。
函数重载的目的就是为了方便的使用函数名。
函数重载并不复杂,等大家学完就会明白什么时候需要用到他们,以及是如何编译,链接的。
3.15.2 函数重载
3.15.2.1 函数重载基本语法
实现函数重载的条件:
|
//1. 函数重载条件 namespace A{ void MyFunc(){ cout << "无参数!" << endl; } void MyFunc(int a){ cout << "a: " << a << endl; } void MyFunc(string b){ cout << "b: " << b << endl; } void MyFunc(int a, string b){ cout << "a: " << a << " b:" << b << endl;} void MyFunc(string b, int a){cout << "a: " << a << " b:" << b << endl;} } //2.返回值不作为函数重载依据 namespace B{ void MyFunc(string b, int a){} //int MyFunc(string b, int a){} //无法重载仅按返回值区分的函数 } |
注意: 函数重载和默认参数一起使用,需要额外注意二义性问题的产生。
void MyFunc(string b){ cout << "b: " << b << endl; } //函数重载碰上默认参数 void MyFunc(string b, int a = 10){ cout << "a: " << a << " b:" << b << endl; } int main(){ MyFunc("hello"); //这时,两个函数都能匹配调用,产生二义性 return 0; } |
思考:为什么函数返回值不作为重载条件呢? 当编译器能从上下文中确定唯一的函数的时,如int ret = func(),这个当然是没有问题的。然而,我们在编写程序过程中可以忽略他的返回值。那么这个时候,一个函数为 void func(int x);另一个为int func(int x); 当我们直接调用func(10),这个时候编译器就不确定调用那个函数。所以在c++中禁止使用返回值作为重载的条件。 |
3.15.2.2 函数重载实现原理
编译器为了实现函数重载,也是默认为我们做了一些幕后的工作,编译器用不同的参数类型来修饰不同的函数名,比如void func(); 编译器可能会将函数名修饰成_func,当编译器碰到void func(int x),编译器可能将函数名修饰为_func_int,当编译器碰到void func(int x,char c),编译器可能会将函数名修饰为_func_int_char我这里使用”可能”这个字眼是因为编译器如何修饰重载的函数名称并没有一个统一的标准,所以不同的编译器可能会产生不同的内部名。
void func(){} void func(int x){} void func(int x,char y){} |
以上三个函数在linux下生成的编译之后的函数名为:
_Z4funcv //v 代表void,无参数 _Z4funci //i 代表参数为int类型 _Z4funcic //i 代表第一个参数为int类型,第二个参数为char类型 |