C++函数重载

12 篇文章 0 订阅

C++函数重载

1.函数重载概念

函数重载:是函数的一种特殊情况,C++允许在同一作用域中声明几个功能类似的同名函数,但这些同名函数的形参列表(参数个数类型顺序)必须不同,常用来处理实现功能类似数据类型不同的问题。

// 形成函数重载的三个函数
int Add(int left, int right)
{
	return left + right;
}

double Add(double left, double right)
{
	return left + right;
}

long Add(long left, long right)
{
	return left + right;
}

int main()
{
	Add(10, 20);
	Add(10.0, 20.0);
	Add(10L, 20L);
	return 0;
}

:下面函数属于函数重载吗?

short Add(short left, short right)
{
	return left+right;
}

int Add(short left, short right)
{
	return left+right;
}

:由于函数的形参个数类型以及顺序完全相同。所以不构成函数重载。

2.名字修饰

为什么C++支持函数重载,而C语言不支持函数重载呢?

2.1.程序编译过程

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

2.1.1.程序编译过程

1.预处理阶段

1. 展开头文件
2. 宏替换
3. 去注释
4. 条件编译

2.编译阶段

1. 检查语法错误
2. 生成汇编代码

3.汇编阶段

1. 将汇编代码转换成二进制代码(机器语言)
2. 将指令打包成一种叫做可重定位的目标程序格式

4.链接阶段

1.合并段表
2.合并符号表与符号表的重定位
3.得到可执行文件可以被加载到内存中,由系统执行。

2.1.2.程序编译过程图示

编译过程

编译过程

2.2.过程模拟
2.2.1.链接的作用

1.我们知道项目通常是由多个头文件和多个源文件构成,通过编译链接过程,我们可以知道,假设当a.cpp程序中调用了b.cpp中定义的Add函数时,在编译后并且在链接之前,a.o的目标文件中并没有Add的函数地址,因为Add是在b.cpp中定义的,所以Add的地址在b.o中。那么该怎么办呢?

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

3. 那么链接时,面对Add函数,链接器会使用哪个函数名字去寻找呢?每个编译器都有自己的函数名修饰规则。

2.2.2.使用Linux进行过程模拟

1.使用vim创建程序

头文件:list.h

#pragma once
#include <stdio.h>

void list_push_back(int x); 

源文件:list.c

#include "list.h"

void list_push_back(int x)
{
	printf(" %d ", x);
}

测试文件:test.c

#include "list.h"

int main()
{
	list_push_back(1);
	return 0;
}    

2.查看函数名

(1). 使用 gcc 编译器编译,将源代码转化成可执行程序 listc
输入指令:
gcc -o listc list.c test.c list.h

(2). 使用 g++ 编译器编译,将源代码转化成可执行程序 listcpp
输入指令:
g++ -o listcpp list.c test.c list.h

(3).分别输入
objdump -S listcobjdump -S listcpp;
转到反汇编

可以看到如下函数名:
gcc编译器
g++编译器

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

2.2.3.Windows下名字修饰规则

windows修饰规则

对比Linux之后可以看出,windows的c++编译器对函数名字修饰比较诡异,但是基本原理是相同的。

3.结果比较
3.1.C++编译器与C编译器比较

结论:通过上述结果我们就理解了C语言无法支持重载,因为同名函数无法区分。而C++是通过函数修饰规则来区分,只要参数不同,修饰出来的名字就不一样,所以就支持了重载。

: 函数重载只要求参数不同!而跟返回值没关系 !!!

3.2.extern “C”

有时候在C++工程中可能需要将某些函数按照C风格来编译,则可以在函数前加 extern “C”。含义是告诉编译器,将该函数按照C语言规则来编译。

比如:tcmalloc是google用C++实现的一个项目,提供tcmallc()和tcfree两个接口来使用,但如果是C项目就没办法使用,那么就使用extern “C”来解决。

代码表示:

extern "C" int Add(int left, int right);
int main()
{
	Add(1,2);
	return 0;
} 
4.面试题

1.下面两个函数能形成函数重载吗?有问题吗或者什么情况下会出问题?

void TestFunc(int a = 10)
{
	cout<<"void TestFunc(int)"<<endl;
}
void TestFunc(int a)
{
	cout<<"void TestFunc(int)"<<endl;
} 

答:虽然两个函数一个为全缺省,一个没有缺省,但是函数名和函数的形参类型、个数、顺序完全相同。所以不形成重载;函数会在链接阶段出问题。

2. C++中能否将一个函数按照C的风格来编译?

可以,在函数前加 extern "C"即可。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值