网上呢一直流传着这么两个说法,我国有两个体育项目大家根本不用看,也不用担心。一个是乒乓球,一个是男足。前者是“谁也赢不了!”,后者是“谁也赢不了!
自然语言中,一个词可以有多重含义,人们可以通过上下文来判断该词真实的含义,即该词被重载了
通过上述两个生活小案例,相信你对函数重载一定有了一个基本的概念,接下去让我们正式来学习一下函数重载💻
【函数重载】:是函数的一种特殊情况,C++允许在同一作用域中声明几个功能类似的同名函数,这些同名函数的形参列表(参数个数 或 类型 或 类型顺序)不同,常用来处理实现功能类似数据类型不同的问题
.cpp
的文件中,我们才可以进行函数重载
对于C++中的函数重载来说,随着不同类型或者个数的实参传入,编译器会自动识别向对应的函数去进行一个调用
int Add(int x, int y)
{return x + y;
}double Add(double x, double y)
{return x + y;
}
int ret1 = Add(1, 2);
double ret2 = Add(1.1, 2.2);
int Add(int x, int y)
{return x + y;
}int Add(int x, int y, int z)
{return x + y + z;
}
int ret1 = Add(1, 2);
int ret2 = Add(1, 2, 3);
void Print(int x, char c)
{cout << x << " ";cout << c << " ";cout << endl;
}void Print(char c, int x)
{cout << c << " ";cout << x << " ";cout << endl;
}
Print(1, 'x');
Print('y', 2);
在观察函数重载的原理之前,我们来浅浅回顾一下C语言中所介绍的程序编译+链接全过程
test.c
就会形成一个目标文件test.o
.o
的目标文件.exe
,在Linux下是a.out
现在我们要去思考的一个点是,假如
test.cpp
中使用到了add.c
中的函数Add,而且恰好这个函数还进行了函数重载,那编译器是怎么知道要去add.c
中寻找这个重载函数的呢❓
首先你要清楚在编译阶段后的【链接】阶段,它的功能是什么
test.o
中调用到了Add函数,此时它就会去其他目标文件中通过一定的方式识别找到它所匹配调用的这个重载函数,然后通过将两个目标文件的符号表进行合并也就形成了最后的可执行文件
但是还有一点很困惑的是,编译器是怎样的方式去识别的呢?我们可以通过查看【反汇编】代码来观察一下
首先我们来看下Linux平台下对于重载函数的反汇编指令是怎样的
objdump
。这个也是Linux下的一个指令,感兴趣的可以去了解一下 链接<_Z3Addii>
,第二个函数则变成了<_Z3Adddd>
这是为什么呢?
所以我们可以得出结论:对于C语言来说是不存在函数名修饰的,只有C++支持,会将函数参数类型信息添加到修改后的名字中
Linux中查看完之后我们再来Windows中来看看,为什么要先看Linux呢?看下去你就知道了
.cpp
的文件来说,函数名在修饰之后变得是异常复杂。可是对于.c
的文件来说,使用的还是原先的Add函数名,没有发生变化
看了上面这些我想应该也够了,如果你还想要再深度地进行了解的话可以看看这篇文章 —— 链接
通过上面的观察我们就可以来总结一下有关函数名的修饰规则
【_Z + 函数长度 + 函数名 + 类型首字母】
【? + 函数名 + @@YA + 返回值 + 参数1 + 参数2 + @Z】
,int类型对应的是字母H,void类型对应的是字母X,double类型对应的是字母N。扩展:float类型对应的是字母M(可以当做了解一下) 在看了上面有关C++函数重载的原理之后,就可以回答为何C语言不支持函数重载
通过研究了函数重载的原理之后,最后再来说说比较容易误解的写法,你认为下面的两个函数构成函数重载吗?
int Add(int x, int y)
{return x + y;
}double Add(int x, int y)
{return x + y;
}
最后我们来总结一下本文所学习的的内容📖
以上就是本文要介绍的所有内容,感谢您的阅读🌹
上一篇:python调试模块ipdb
下一篇:2.线性表的顺序表示