从c到c++——03:函数重载

    不知道大家在写c语言程序时会不会有这样一个问题,比方说我和我的铁哥们张三一起做一个项目

     我写了一个两个整数相加的函数:

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

       张三写个一个两个浮点数相加函数

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

 本来两个程序都是好好的,但是当我们把俩程序堆到一起运行时,因为c语言不允许重名函数的存在,编译器报了错,我和张三一检查,哦原来是因为重名函数的问题,把函数重命名一下就好

我想:我原本的函数名是三个字符,我女神李翠花的首字母是L,两个整形参数,一个整形返回值是三个i于是改函数名为L3Addiii

张三以自己的首字母Z,两个参数d,一个返回值d,改函数名为ZAddddd

int L3Addiii(int a, int b)
{
	return a + b;
}
double ZAddddd(double a, double b)
{
	return a + b;
}

程序可以正常运行.

        这时,女神李翠花发了消息,女神早就听说我写的代码风流倜傥,特来借鉴一番,我自豪地给她看了我刚写的代码,她含情脉脉的看着我的代码,丝毫不掩饰对我的敬佩,若是时间能永远停留在这一刻那该多好.可惜,她看到了我刚刚写的L3Addiii函数,"这些的什么啊!我看隔壁经贸系王五哥哥的代码比你好一万倍",说完头也不回就走了.

这个故事告诉我们不统一的函数命名规则会导致可读性变差.//进而导致没有女朋友(确信)


函数重载

        如果同一作用域内的几个函数名字相同但参数列表不同,我们称这些函数为重载函数,当调用这些函数时,编译器会根据实参类型和个数(仅返回值类型相同不可以)来判断具体调用哪个函数.(c++中允许重名函数的存在,但是参数类型必须存在不同)

main函数不能重载!!!

实现

从c到c++——03:函数重载_第1张图片

特殊情况

//正确
void tmp(int x, int y, char z = 'a');
void tmp(int x, int y, double z= 1.5);
//错误,两个函数参数个数及类型都相同
void tmp2(int x, int y);
int  tmp2(int x, int y);
//错误
void lookup(int a);
void lookup(int);
//错误
typedef int Nodetype;
void lookup(Nodetype a);
void lookup(int a);

在局部作用域中调用其他作用域的函数:

namespace s1 {
	void print(int x)
	{
		cout << x << endl;
	}
}
int main()
{
	void s1::print(int x);
	print(10);
	system("pause");
	return 0;
}

函数重载的底层实现

        同c语言一样,一个cpp程序从源码到一个可执行的二进制文件需要经历预处理,编译,汇编,链接四个阶段.

  1. 预处理:执行宏定义操作,展开头文件,删除注释等
  2. 编译   :把每个c++语言程序文件翻译为汇编语言文件,后缀为i
  3. 汇编   :把每个汇编文件转成二进制文件,后缀为s
  4. 链接   :把所有的二进制文件合并成一个可执行文件,后缀为o

在链接过程中,如果源程序中调用了一个声明了但是没有定义的程序,它报错并会把链接时的函数名返回.

从c到c++——03:函数重载_第2张图片

 error LNK2019: 无法解析的外部符号 "int __cdecl add(int,int)" (?add@@YAHHH@Z),

 error LNK2019: 无法解析的外部符号 "double __cdecl add(double,double)" (?add@@YANNN@Z)

可以看出在链接之前,cpp程序中的函数名编译过程中会和参数类型一起被重命名,

函数重载的本质是在编译过程中对函数按编译器指定的规则进行重命名,从而在写c++代码时允许重名参数的存在

在vs2022环境下,新名字为"?"+函数名+"@@YZ"+返回值对应的类型+参数对应的类型.图中显然int对应H,double对应N,同理可以测试出long long->_J;long->J;char->D;short->F

从c到c++——03:函数重载_第3张图片

在g++环境下为"_Z"+原函数长度+参数缩写


感谢观看!!!

你可能感兴趣的:(c++,开发语言)