一个函数在C++中能够被重载,但是在C语言确不能被重载的,是由于函数名在内存中存储方式不同所导致的。
C语言
例如在C语言中,有以下三个函数,只给声明不给定义!
int fun(int a, int b);
int fun2(int a, char b);
char fun3(char a, char b);
在main函数中调用之
int main()
{
fun(1, 2);
fun2(2, 3);
fun3(3, 4);
system("pause");
return 0;
}
会发现4个连接错误:
我们仔细来看一下,在C语言中,编译器区分一个函数,仅仅是靠 “_” + 函数名
来区分的,如果我们将三个函数写成同名函数呢:
int fun(int a, int b);
int fun(int a, char b);
char fun(char a, char b);
int main()
{
fun(1, 2);
fun(2, 3);
fun(3, 4);
system("pause");
return 0;
}
会发现,编译通不过,报出重定义错误
这是当然的,因为三个函数的函数名相同,在编译器看来都是_fun
,当出现第二个时,编译发现这个函数名已存在,便出现重定义编译失败。
这也就是为什么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;
}
同样的函数,同样不进行定义直接调用,会发现:
同样是4个连接错误,但是不同的是,函数名变长了,我们仔细研究发现一个函数在C++中的符号总是以?函数名@@YA
开头,之后是H
或者D
,最后是以@Z
结尾,共三部分。我们在仔细看会发现,在第二部分中H
表示int
,D
表示char
,且第一个表示返回值,之后的表示函数的参数。
如int fun(char a, char b, int c);
就是 ?fun@@YAHDDH@Z
这样编译器就能区分每个函数了,尽管函数名相同,但只要是参数不同,在编译器看来也是不同的标识符:
int fun(int a, int b);
int fun(int a, char b);
char fun(char a, char b);
int main()
{
fun(1, 2);
fun(1, 'c');
fun('1', '2');
system("pause");
return 0;
}
当三个函数构成重载时,会发现:
函数名相同,但编译器还是能够区分的。
总结:
虽然在两个语言中, 函数的调用约定都是_cdecl
,但是由于函数在内存中的存储方式不相同,C语言是“_” + 函数名
形式,而C++是?函数名@@YA返回值 参数@Z
形式,导致C++支持重载,而C语言不支持重载。