国有两个体育项目大家根本不用看,也不用担心。一个是乒乓球,一个是男足。前者是“谁也赢不了!”,后者是“谁也赢不了!”
一样的文字,不同的意思。
函数重载:是函数的一种特殊情况,C++允许在同一作用域中声明几个功能类似的同名函数,这些同名函数的形参列表(参数个数 或 类型 或 类型顺序)不同,常用来处理实现功能类似数据类型不同的问题
//参数类型不同
int Add(int a, int b)//Add(2,5)
{
return a + b;
}
double Add(double a, double b)//Add(2.5,5.5)
{
return a + b;
}
//类型顺序不同
double Add(int a, double b)//Add(2,5.5)
{
return (double)a + b;
}
int Add(double a, int b)//Add(2.5,5)
{
return (int)a + b;
}
//参数个数不同
int Add(int a)//Add(5)
{
return a;
}
C++支持函数重载的原理——名字修饰
运行程序的时候,会先进行预处理,编译,汇编,链接
在链接期间,会将编译期间的符号表合并,里面每个位置都有对应的名和地址,需要调用哪一个内容就根据名字找到符号表中名字对应的地址
C对于函数的函数名和地址处理到符号表中时,函数名原封不动,所以当有多个同名函数时,编译器无法区分
但是对于C++来说,在对函数的函数名和地址处理到符号表中时,会根据函数的参数来对函数名进行修饰,
以下用linux环境下来解释
-
采用C语言编译器编译后结果
结论:在linux下,采用gcc编译完成后,函数名字的修饰没有发生改变 -
采用C++编译器编译后结果
结论:在linux下,采用g++编译完成后,函数名字的修饰发生改变,编译器将函数参数类型信息添加到修改后的名字中
通过上面我们可以看出gcc的函数修饰后名字不变。而g++的函数修饰后变成【_Z+函数长度+函数名+类型首字母】
函数名修饰在vs下的规则:C++编译时函数名修饰约定规则:
__stdcall调用约定:
-
以“?”标识函数名的开始,后跟函数名;
-
函数名后面以“@@YG”标识参数表的开始,后跟参数表;
-
参数表以代号表示:
X–void ,
D–char,
E–unsigned char,
F–short,
H–int,
I–unsigned int,
J–long,
K–unsigned long,
M–float,
N–double,
_N–bool,
…
PA–表示指针,后面的代号表明指针类型,如果相同类型的指针连续出现,以“0”代替,一个“0”代表一次重复; -
参数表的第一项为该函数的返回值类型,其后依次为参数的数据类型,指针标识在其所指数据类型前
-
参数表后以“@Z”标识整个名字的结束,如果该函数无参数,则以“Z”标识结束。其格式为“
?functionname@@YG*****@Z”或“?functionname@@YG*XZ
”,
例如
int Test1(char *var1,unsigned long)-----“?Test1@@YGHPAK@Z
void Test2() -----“?Test2@@YGXXZ
__cdecl调用约定:
规则同上面的_stdcall调用约定,只是参数表的开始标识由上面的“@@YG”变为“@@YA”。
__fastcall调用约定:
规则同上面的_stdcall调用约定,只是参数表的开始标识由上面的“@@YG”变为“@@YI”。
VC++对函数的缺省声明是"__cedcl",将只能被C/C++调用
注意:如果两个函数函数名和参数是一样的,返回值不同是不构成重载的,因为调用时编译器没办法区分
比如:
int Add(int a, int b)
{
return a + b;
}
double Add(int a, int b)
{
return a + b;
}
int main()
{
Add(1,2);
Add(2,3);
}
其实我们并没有办法区分,编译器也没有办法区分,虽然同名函数返回类型不相同,但是使用这个函数时并不会像定义函数那样标明返回类型,所以我们和编译器都无法区分这个情况
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)