为啥C++支持函数重载,C语言不行?

通过C++的函数重载的学习,我相信大家很疑惑C++支持函数重载,C语言为啥不行?现在就给你揭开疑惑的面纱。


目录

一、小知识: 

二、小问题:

a.采用C语言编译器编译后结果

b.采用C++编译器编译后结果

三、得出结论:

四、小拓展:


一、小知识: 

在C/C++中,一个程序要运行起来,需要经历以下几个阶段:预处理、编译、汇编、链接。

通过上述简单了解,我们知道一个项目由多个头文件和源文件组成。

二、小问题:

那在a.cpp中调用了b.cpp中定义的Add函数时,编译后,链接前,a.o的目标文件中没有Add的函数地址,因为Add是在b.cpp中定义的,所以Add的地址在b.o中。

这怎么办呢?

所以链接阶段就是专门处理这种问题,链接器看到a.o调用Add,但是没有Add的地址,就会到b.o的符号表中找Add的地址,然后链接到一起。

那么链接时,面对Add函数,链接接器会使用哪个名字去找呢?这里每个编译器都有自己的函数名修饰规则。由于Windows下vs的修饰规则过于复杂,而Linux下g++的修饰规则简单易懂,下面我们使用了g++演示了这个修饰后的名字。


以这段代码为例

int Add(int a, int b)
{
	return a + b;
}

void func(int a, double b, int* p)
{}

int main()
{
	Add(1, 2);
	func(1, 2, 0);

	return 0;
}

a.采用C语言编译器编译后结果

结论在linux下,采用gcc编译完成后,函数名字的修饰没有发生改变。
 

b.采用C++编译器编译后结果

结论在linux下,采用g++编译完成后,函数名字的修饰发生改变,编译器将函数参数类型信息添加到修改后的名字中。


三、得出结论:

通过上面我们可以看出gcc的函数修饰后名字不变。而g++的函数修饰后变成<_Z+函数长度+函数名+类型首字母>。

通过这里就理解了C语言没办法支持重载,因为同名函数没办法区分。而C++通过函数修饰规则来区分只要参数不同,修饰出来的名字就不一样,就支持了重载。

由此得出:

C++支持函数重载的原理--名字修饰。



四、小拓展:

在C++上的这段代码

int fun(int a, int b);
int fun2(int a, char b);
char fun3(char a, char b);

int main()
{
    fun(1, 2);
    fun2(1, 'c');
    fun3('1', '2');
    //system("pause");
    return 0;
}

我们仔细研究发现一个函数在C++中的符号是以?函数名@@YA开头,之后是H或者D,最后是以@Z结尾,共三部分。且大胆推测,在第二部分中H表示int ,D表示char,且第一个表示返回值,之后的表示函数的参数。

如int fun(char a, char b, int c);就是 ?fun@@YAHDDH@Z

又对比Linux会发现,windows下vs编译器对函数名字修饰规则相对复杂,但道理都是类似的。


C/C++函数调用约定和名字修饰规则--有兴趣好奇的同学可以看看这个博客:

C/C++ 函数调用约定-优快云博客

<think>嗯,用户的问题是关于函数重载函数重载的区别,以及C语言是否支持函数重载。首先,我需要确认这两个术语的具体含义,因为有时候不同的资料可能会有不同的叫法。 首先,函数重载(Function Overloading)应该是指在同一个作用域内,函数名相同但参数列表不同(类型、数量或顺序)。这允许程序员用同一个名字实现不同功能,根据参数自动选择对应的函数。比如C++中的例子,`add(int a, int b)`和`add(double a, double b)`就是重载函数。 接下来是“函数重载”这个术语。用户可能是指函数名的重复定义,或者是名称修饰(Name Mangling)的问题。不过通常来说,“函数重载”并不是一个标准术语,可能用户有误解,或者想了解其他相关概念。比如,可能是指函数名相同但通过不同方式处理,或者链接时的名称处理。但根据参考资料,C语言在编译时函数名不会进行修饰,所以无法区分同名函数的不同参数版本,导致不支持重载。 然后,关于C语言是否支持函数重载。根据引用[1]、[2]、[3]、[4],C语言确实不支持函数重载,因为它的编译器不会对函数名进行修饰,直接使用原函数名,导致链接时无法区分不同参数的函数。而C++通过名称修饰(比如参数类型编码到函数名中)来支持重载。 现在需要区分“函数重载”和“函数重载”的区别。可能用户将两者混淆了,或者“函数重载”是指其他机制。根据现有资料,没有提到函数重载,所以需要推测可能用户指的是函数名的重复定义,即同名函数,这在C语言中会导致冲突,而C++通过名称修饰避免这个问题。因此,可能函数重载并不存在,用户可能误用了术语,应该解释清楚。 接下来要组织答案,先明确两者的区别,然后解释C语言支持函数重载的原因,并引用提供的资料来支持结论。需要确保回答结构清晰,分点说明,并使用正确的中文表达。同时要生成相关问题,可能需要围绕函数重载的实现机制、C与C++的区别、名称修饰等方向提问。</think>### 函数重载函数重载的区别及C语言支持性分析 #### 1. 函数重载 vs 函数重载 - **函数重载(Function Overloading)** 指在同一作用域内定义多个同名函数,但这些函数的参数列表不同(类型、数量或顺序)。例如: ```cpp int add(int a, int b); double add(double a, double b); ``` 编译器会根据调用时传入的参数类型自动选择匹配的函数版本[^1][^4]。 - **函数重载(非常规术语)** 该术语并不属于编程语言的标准化定义,可能是对以下两种概念的混淆: 1. **函数名重复定义**:在C语言中,若定义多个同名函数(即使参数不同),会引发编译错误,因为C编译器不会对函数名进行修饰[^2][^3]。 2. **函数名修饰(Name Mangling)**:在C++中,编译器通过将参数信息编码到函数名中(如`_add_int_int`),生成唯一的符号名称以支持重载。 #### 2. C语言是否支持函数重载? **不支持**,原因如下: 1. **无函数名修饰机制** C语言编译器直接使用原始函数名作为符号名称。例如函数`void foo(int a, int b)`会被存储为`foo`,而非包含参数信息的名称。若定义同名函数(即使参数不同),链接器无法区分它们,导致冲突[^3]。 2. **静态类型检查限制** C语言在编译时仅依赖函数名匹配调用,无法根据参数类型或数量动态选择函数版本。例如以下代码会报错: ```c void print(int x) {} void print(double x) {} // 编译错误:重复定义 ``` #### 3. 对比C++的实现 C++通过**函数名修饰**支持重载。例如: - `void foo(int, int)` → 符号名为`_foo_int_int` - `void foo(int, float)` → 符号名为`_foo_int_float` 编译器通过修饰后的名称区分不同参数列表的函数[^4]。 --- ###
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值