探讨为什么CPP支持函数重载而C不支持?
Windows操作系统下VS编译C文件
#include <stdio.h>
#include <Windows.h>
double add(double a, double b);
int main()
{
add(1.0, 2.0);
system("pause");
return 0;
}
这段代码编译可以通过,但是链接通过不了
报错:
错误 2 error LNK2019: 无法解析的外部符号 _add,该符号在函数 _main 中被引用
#include <stdio.h>
#include <Windows.h>
int add(int a, int b);
int main()
{
add(1, 2);
system("pause");
return 0;
}
这段代码可以通过编译阶段,但是无法通过链接阶段
报错:
错误 2 error LNK2019: 无法解析的外部符号 _add,该符号在函数 _main 中被引用
由上述两个相同功能但数据类型不同的add函数的报错可以看出:add函数在编译之后存在符号表中的名字都是_add,而main函数名字是_main
所以,
VS编译器编译C文件时对于相同名字的函数并不做区分
,都是以
_函数名
来命名
Windows操作系统下VS编译CPP文件
#include <iostream>
using namespace std;
int add(int a, int b);
double add(double a, double b);
int main()
{
add(1.0, 2.0);
add(1, 2);
system("pause");
return 0;
}
这段代码可以通过编译,但是不能通过链接
报错:
error LNK2019: 无法解析的外部符号 “int __cdecl add(int,int)” (?add@@YAHHH@Z),该符号在函数 _main 中被引用
error LNK2019: 无法解析的外部符号 “double __cdecl add(double,double)” (?add@@YANNN@Z),该符号在函数 _main 中被引用
由报错可以看出:自定义函数的函数名经过编译之后,变成了另外一种表现形式,对于同名函数有区分度
命名规则:【?函数名@@YA返回值数据类型对应字母+形参数据类型对应字母@Z】
对应关系:
- int -> H
- double-> N
- float -> M
- char -> D
- void -> X
- bool -> _N
例如:
int add(int ,int ) -> ?add@@YAHHH@Z
double func(double,double) -> ?func@@YANNN@Z
Linux操作系统下gcc编译C文件
由此可以看出gcc编译c之后,自定义函数的函数名不变,对于同名函数没有区分度。
Linux操作系统下g++编译CPP文件
由此可以看出g++编译CPP文件之后,自定义函数的函数名改变了,可以对同名函数进行区分。
命名规则:【_Z + 函数名字长度 + 函数名 + 形参数据类型首字母】
例如:
int add(int ,int ) -> _Z 3 add i i
int func(double ,double ,double) -> _Z 4 func d d d
总结:无论是Windows操作系统还是Linux操作系统,基于这些操作系统的主流编译器都有一下特点:
- 编译C文件: 编译之后,对于 相同函数名的自定义函数 无区分度
- 编译CPP文件:编译之后,对于 相同函数名的自定义函数 有区分度
结:无论是Windows操作系统还是Linux操作系统,基于这些操作系统的主流编译器都有一下特点:
- 编译C文件: 编译之后,对于 相同函数名的自定义函数 无区分度
- 编译CPP文件:编译之后,对于 相同函数名的自定义函数 有区分度
因此,至于是 命名规则 导致 C语言不支持函数重载而CPP支持函数重载 ,还是 C语言不支持函数重载而CPP支持函数重载 导致 命名规则如此,其因果关系就仁者见仁智者见智啦