(一)函数重载

(1)函数的原型

函数返回值 函数名 形参列表(参数的类型 和个数 形参名可省略),且不需要函数体。

(2)函数重载条件

  • 同一作用域下;
  • 函数名相同;
  • 函数的参数个数不同、参数的类型不同,或者顺序不同;

注意:函数的返回值不能作为函数重载的条件;


(二)C为什么不能函数重载,C++却可以?

  • C语言区分函数是以函数名来区分(C编译器会在编译阶段将函数命名为_函数名),若是使用同名函数,就会发生重定义。

  • C++区分函数是以函数的原型来区分(C++编译器使用了名字粉碎技术

(1)vs2019 C编译器编译

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
#include <iostream>
using namespace std;

//使用C编译器
//编译成_fun
extern "C" int Max(int a, int b)
{
return a > b ? a : b;
}

int main()
{
Max(10, 20);
return 0;
}

从汇编角度看:C编译器将Max函数编译成_Max
在这里插入图片描述

(2)vs2019 C++编译器编译

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
#include <iostream>
using namespace std;

//使用C++编译器
//编译成_fun
extern "C++" int Max(int a, int b)
{
return a > b ? a : b;
}

int main()
{
Max(10, 20);
return 0;
}

从汇编角度来看:vs2019未给出真实的函数名字粉碎的结果
在这里插入图片描述

(3)vc6.0编译结果

在这里插入图片描述


(三)C++名字粉碎技术

重新生成函数名?函数名@@YG参数代号@Z (详细解释如下)

标准调用约定:__stdcall

  • 1、以“?”标识函数名的开始,后跟函数名
  • 2、函数名后面以“@@YG”标识参数表的开始,后跟参数表
  • 3、参数表以代号表示
代号参数类型
Xvoid
Dchar
Eunsigned char
Fshort
Hint
Iunsigned int
Jlong
Kunsigned long
Mfloat
Ndouble
Nbool

所以对(二)中的Max函数使用__stdcall调用约定,在编译时将Max函数使用名字粉碎技术得到的结果就是:?Max@@YGHHH@Z,所以在调用该函数Max(10, 20)时,通过形参类型(int, int)得到应该使用哪个函数。


(四)返回类型不同的函数是否可以重载

不能通过函数的返回值类型来区分函数重载

举个栗子:使用__stdcall调用约定

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
#include <iostream>
using namespace std;
//名字粉碎:?Sum@@HHH@Z
int Sum(int a, int b)
{
return a + b;
}
//名字粉碎:?Sum@@NHH@Z
double Sum(int a, int b)
{
return (double)(a + b);
}

int main()
{
Sum(10, 20);
return 0;
}

调用Sum函数时,系统根据参数类型int,int(HH)来调用Sum函数,两个函数的参数类型都是HH,并且在调用时发生了二义性。所以不能使用返回值作为函数重载的条件。


后期讲解函数调用约定,敬请期待!!