目录
概念
是函数的一种特殊情况,c++允许在同一个作用域中出现函数名相同的函数,但这些函数的参数部分必须要不同(参数的个数,类型或者顺序不同(这与c++的底层逻辑处理有关,可通过汇编学习)),这样就可以构成函数重载(此部分是c++学习的重要部分)
产生
那为什么c++会支持函数重载呢,主要在于c语言不支持,会导致名字不一样,用起来就不方便
例如:一个加法add函数,由于实参的类型不同,要写很多个add函数,他们只是参数类型不同, 函数的实现代码都一样,c语言会显得繁琐,会有AddInt,AddShort,Addchar等等
c++支持函数名重载共同用一个名字add,传参不一样就会调用不一样的函数
为什么c++支持函数重载,底层原理如何处理
在c\c++中,一个程序运行起来需要经过预处理,编译,汇编,链接
预处理阶段:预处理器会对源文件中的预处理指令进行处理,这些指令以 # 开头,常见的预处理指令包括 #include、#define、#ifdef 等。经过预处理后,会生成一个经过处理的源文件,通常以 .i(C 语言)或 .ii(C++ 语言)为扩展名。
编译阶段:编译器会将预处理后的源文件翻译成汇编代码。编译器会对代码进行语法分析、语义分析、代码优化等操作
- 语法检查:检查代码的语法是否正确,如括号是否匹配、语句是否以分号结尾等。
- 语义分析:分析代码的语义,确保变量和函数的使用符合语言规则,例如变量是否在使用前声明等。
- 代码优化:对代码进行优化,提高代码的执行效率,如消除冗余代码、常量折叠等。
- 生成文件:编译阶段会生成汇编代码文件,通常以
.s为扩展名。
汇编阶段(Assembly)
- 作用:汇编器会将汇编代码翻译成机器语言代码,也就是目标文件。目标文件包含了机器指令和数据,但还不能直接运行。
- 处理内容:汇编器将汇编代码中的助记符(如
mov、add等)翻译成对应的机器指令。 - 生成文件:汇编阶段会生成目标文件,通常以
.o(Unix/Linux 系统)或.obj(Windows 系统)为扩展名
链接阶段(Linking)
- 作用:链接器会将多个目标文件和库文件链接成一个可执行文件。在程序中可能会调用其他目标文件或库文件中的函数和变量,链接器的作用就是将这些引用和定义进行关联。
- 处理内容
- 符号解析:链接器会解析目标文件中的符号引用,找到这些符号的定义所在的位置。例如,在一个源文件中调用了
printf函数,链接器会在标准库中找到printf函数的定义。 - 地址重定位:链接器会对目标文件中的地址进行调整,确保程序在运行时能够正确访问各个变量和函数。
- 符号解析:链接器会解析目标文件中的符号引用,找到这些符号的定义所在的位置。例如,在一个源文件中调用了
-
生成文件:链接阶段会生成可执行文件,在 Unix/Linux 系统中通常没有扩展名,在 Windows 系统中以
.exe为扩展名。
原因:函数修饰规则
以Linux下gcc为例,通过汇编可以看出,C语言中函数名编译后的结果为函数名<add>
而c++中为<_Z3addii>, _Z 是一个固定的前缀,它是修饰后的名字起始标识,用于告知链接器这是一个经过 C++ 名字修饰的符号,编译器和链接器看到 _Z 开头的符号,就知道要按照 C++ 的名字修饰规则去解析这个符号所代表的具体函数信息。3为函数名的字母个数,ii为两个类型int int,那么在连接时就可以辨认出是哪个函数,例如add(int,int)就会找到<_Z3addii>,如果是add(char,char)就会找到<_Z3addcc>,windows也是同样的道理,只是命名风格不一样,那么通过这样看,如果是返回类型不一样是不能构成函数名重载的,只要参数不同就可以构成函数名重载,参数的个数,类型或者顺序不同
在一些特殊场合可以通过 extern "C"来告诉编译器按照c的风格来编译
例如extern "C" int add(int x,int y);
extern "C" {
void func1();
int func2(int a, int b);
}
在这个代码块中声明的所有函数 func1 和 func2 都会按照 C 语言的方式进行处理。
1020

被折叠的 条评论
为什么被折叠?



