提起函数重载,很多人都耳熟能详,那么它到底为何存在,有何神奇之处?今天,我就会好好去研究一下它,揭开它的深层面纱~
函数重载是什么?
函数重载是一种特殊情况,c++允许在同一作用域中声明几个功能类似的同名函数,这些函数的形参列表必须不同【参数类型或参数个数或参数顺序不同】,用来处理功能类似但数据类型不同的问题。
函数重载的例子:
#include <iostream> using namespace std; void Func(int a, int b) { cout << a << "+" << b << "=" << a + b << endl; } void Func(double a, double b) { cout << a << "+" << b << "=" << a + b << endl; } int main() { Func(1, 2); Func(1.5, 1.0); system("pause"); return 0; }
编译成功~
结果正确~
那为什么要有函数重载呢?
-
试想如果没有函数重载机制,如在C中,你必须要这样去做:为这个print函数取不同的名字,如print_int、print_string。这里还只是两个的情况,如果是很多个的话,就需要为实现同一个功能的函数取很多个名字,如加入打印long型、char*、各种类型的数组等等。这样做很不友好。
-
类的构造函数跟类名相同,也就是说:构造函数都同名。如果没有函数重载机制,要想实例化不同的对象,那是相当的麻烦。
-
操作符重载,本质上就是函数重载,它大大丰富了已有操作符的含义,方便使用,如+可用于连接字符串等。
所以百科的解释:重载函数通常用来命名一组功能相似的函数,这样做减少了函数名的数量,避免了名字空间的污染,对于程序的可读性有很大的好处。
现在终于明白了,c++支持函数重载的意义真的非比寻常,那么另一个问题来了,C语言支持函数重载码?
我们来验证一下:
#include <stdio.h>
#include <stdlib.h>
void Func(int a, int b)
{
printf("%d + %d = %d\n", a, b, a+b);
}
void Func(double a, double b)
{
printf("%lf + %lf = %lf\n", a, b, a + b);
}
int main()
{
Func(1, 2);
Func(1.5, 1.0);
system("pause");
return 0;
}
结果显示:不可以!!!
我们现在知道了,C语言不支持函数重载,而c++支持函数重载,它究竟怎么做到的呢?
【在vs2013编译器下】函数重载的底层实现原理是什么?
先来看一段代码:
void ADD(double a, double b)
{
cout << a << "+" << b << "=" << a + b << endl;
}
void ADD(int a, int b)
{
cout << a << "+" << b << "=" << a + b << endl;
}
int main()
{
ADD(1, 2);
system("pause");
return 0;
}
在主函数里面调用ADD函数的地方设置断点,然后逐步调试,观察一下:
我们发现它直接进入了第二个ADD函数,我们可以推想一下:既然它在编译阶段直接跳到了第二个函数体内,这就说明了在编译阶段编译器已经识别到了该函数要调用第二个ADD函数,而不能调用第一个ADD函数,那么编译器是如何判定要使用第二个ADD函数呢?其实不难发现,仔细比较两个ADD函数会发现,他们的参数类型不同,我们就有理由猜想:编译阶段编译器是通过函数名加函数参数来断定该使用哪个函数,接下来让我们探索一下~
我们只声明函数,不定义函数,看看编译器的报错信息:
此刻,我们可以清晰地看到:在vs编译器里,编译器阶段应该使用哪个函数,在底层其实是按照_cdecl的调用约定来决定调用哪个函数,我们可以看到括号里面的编译器最终识别的函数名,两个函数名的区别在于参数类型double用N表示,而参数类型int用H表示,因此,在底层的函数名其实并不相同,因为编译器识别的函数名是由上层的函数名和其参数一起组成的新函数名,这个新函数名就是整个工程里独一无二的函数名。现在终于真相大白,原来并不是编译器有神通可以凭借火眼金睛识别函数,其实都是在底层做了‘手脚‘’才使得编译器可以轻松知道使用哪个函数,同时,现在我们也明白了:重载函数的参数必须不同的重要性了【它是底层组成独一无二的函数名的重要成员】~~~
【注意:重载函数与返回值类型无关哦~~~~】
补充一点:
【extern "c"】 有时候在C++工程中可能需要将某些函数按照C的风格来编译,在函数前加extern "C",意思是告诉编译器, 将该函数按照C语言规则来编译】
由此可见,在C语言中,在底层,函数名仅仅是 给函数名前加一个_ 【_Add】
到现在,我们完全揭开了重载函数的神秘面纱,其实它的本质是那么简单,我不得不说:重载函数,认识你真好~~~