C++之函数重载

函数重载

函数重载构成条件

函数重载是C++允许在同一个作用域中声明几个名字相同功能相似的函数,函数重载常被用于处理功能类似、数据类型不同的问题。
高级语言在设计时就有一条原则,语言不能存在二义性,C++为了保证语言不存在二义性对函数重载进行约束:
要构成重载函数必须满足以下几个条件之一:

  1. 形参类型不同
  2. 形参个数不同
  3. 形参顺序不同

通过代码实现一个重载函数,以下代码位于三个文件:
test.cpp

#include"func.h"


int main()
{
	f(1, 1.1);

	return 0;
}

func.h

#include<stdio.h>
#include<stdlib.h>

void f(int a, float b);
void f(float a, int b);

func.cpp

#include"func.h"

void f(int a, float b)
{
	printf("f(int a, float b)\n");
}

void f(float a, int b)
{
	printf("f(float a, int b)\n");
}

以上函数构成重载。上面函数构成重载满足了函数形参顺序不同的规则。运行结果为:
image-20220102142053935

从程序运行结果来看,我们不需要指定函数来运行,程序本身根据所传实参类型来联系实际场景判断用哪个函数,这种方式极大的方便程序员。

无法构成重载的特例

值得注意的是,函数的返回类型不同是无法构成函数重载的如:

void f(int a, float b)
{
	printf("f(1)\n");
}

int f(int a, float b)
{
	printf("f(2)\n");
}

还有无法构成重载的特例:

void f(a = 1)
{
    printf("f(a = 1)\n");
}

void f()
{
    printf("f()\n");
}

上面这种情况若是调用时有实参,编译器可以判断为有形参的函数执行,若无实参调用f();,由于上面函数有缺省参数,编译器无法判断调用的是哪个函数,程序也就无法执行。
!!!注意 main函数无法重载!!!

不建议使用函数重载的场景

函数重载对于程序员使用起来确实方便,但在有些场景不建议使用函数重载。函数重载使用时最好应用于功能相似的函数。有些时候给函数起不同的名字有利于程序员理解函数的功能。举个例子以下为几个负责移动屏幕光标的函数:

void moveHome();
void moveAbs(int, int);
void moveRel(int, int, string direction);

将以上几个函数名字起为move固然也可以,但是这几个函数构成重载之后函数名就失去了本来拥有的信息:

void move();
void move(int, int);
void move(int, int, string direction);

显然第二个命名方式是不如第一个的。

C语言无法构成重载

在vs2019环境中将上面三个文件中的.cpp后缀全改为.c后缀,编译程序后程序报错

image-20220102162759548

由此可以看出C语言不支持函数重载。
那么为什么C语不支持函数重载而C++支持呢?

函数名字修饰

从代码到程序经过预处理,编译,汇编,链接几个过程,C++为了支持函数重载在编译阶段对函数名做了修饰,即名字修饰。由于Windows系统下名字修饰较为复杂,后面的名字修饰演示全为Linux系统下的演示。
在Linux系统下将test.cpp文件进行汇编后反汇编查看:

image-20220102173430008

image-20220102173534172

对比两个函数修饰过的名字和咨询大佬后知道Linux系统下函数名修饰规则:

_Z+函数名长度+函数名+形参类型
形参类型:
i int
f float
c char
pi *int
其它照此类推

由此可以看出,被以上的3个条件约束的函数重载时修饰后的名字是不会重复的,如此才能构成函数重载

C语言反汇编

我们可以通过此方法来看一下C语言的名字修饰情况,揭秘以下C语言为什么不知此重载。
将一个f函数注释掉后反汇编:

image-20220102192958741

可以看到,f函数是没有经过任何修饰的。所以每个f函数名字都是一样的,编译器无法区分函数,所以无法构成重载。
Windows下反汇编的函数名字不太好看,但还是可以通过一些方法看到。

image-20220102193921311

如上图,修饰过的函数名有些复杂,不利于分析,关于Windows下的函数名修饰规则可以在搜索引擎上看一下。