【C++】一篇文章搞懂为什么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文件时对于相同名字的函数并不做区分

扫描二维码关注公众号,回复: 11870613 查看本文章

,都是以

_函数名

来命名

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文件

image.png

由此可以看出gcc编译c之后,自定义函数的函数名不变,对于同名函数没有区分度

Linux操作系统下g++编译CPP文件

image.png

由此可以看出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支持函数重载 导致 命名规则如此,其因果关系就仁者见仁智者见智啦

猜你喜欢

转载自blog.csdn.net/weixin_45437022/article/details/108911870