【C++】函数重载的定义、用法及底层原理

函数重载

重载函数是函数的一种特殊情况,为方便使用,C++允许在同一作用域中声明几个功能类似的同名函数,这些同名函数的形参列表(参数个数类型顺序)必须不同,常用来处理实现功能类似数据类型不同的问题

构成函数重载的条件

  • 形参类型不同
  • 形参个数不同
  • 形参顺序不同

示例

//参数类型不同
int Add(int left, int right)
{
	cout << "int Add(int left, int right)" << endl;
	return 0;
}
double Add(double left, double right)
{
	cout << "double Add(double left, double right)" << endl;
	return 0;
}
//参数个数不同
void f()
{
	cout << "void f()" << endl;
}

void f(int a)
{
	cout << "void f(int a)" << endl;
}
//参数顺序不同
void f(int a, char b)
{
	cout << "void f(int a, char b)" << endl;
}

void f(char b, int a)
{
	cout << "void f(char b, int a)" << endl;
}

int main()
{
	Add(1, 2);
	Add(1.1, 2.2);

	f();
	f(10);

	f(10, 'A');
	f('A', 10);

	return 0;
}

程序的结果
在这里插入图片描述

不能构成重载的情况

  • 形参相同的情况下,函数返回值类型不同,不能构成重载。构成函数重载的条件只与形参参数有关。
  • 形参的缺省值不同,不能构成重载。

示例

//1.不能构成函数重载
void f(int a)
{
	cout << "void f()" << endl;
}

void f(int a = 0)
{
	cout << "void f(int a)" << endl;
}
//2.构成函数重载,但调用f()时下面两个函数都可调用,出现歧义
void f()
{
	cout << "void f()" << endl;
}

void f(int a = 0)
{
	cout << "void f(int a)" << endl;
}

缺省参数

概念:缺省参数是声明定义函数时为函数的参数指定一个默认值。 在调用该函数时,如果没有给定实参则采用该默认值,否则使用指定的实参

  • 缺省参数不能在函数声明和定义中同时出现。(如果两个位置提供的值不同,会产生歧义。要么写在定义,要么写在声明(推荐))
  • 缺省参数必须是常量全局变量
  • C语言不支持缺省参数在这里插入图片描述

全缺省参数

给所有参数都指定一个默认值

半缺省参数

给部分参数指定一个默认值

使用规则

半缺省参数必须从右往左依次来给出,必须连续不能间隔着给

C++支持函数重载的原理–名字修饰

先回顾一下程序编译的过程
在这里插入图片描述

编译器如何去查找调用函数

在filename.o文件里会生成一个符号表,符号表里存着函数的修饰名,修饰名记录保存着函数的地址。在调用函数时,编译器会通过到符号表里查找修饰名来得到函数的地址实现调用。

函数名修饰

函数的名字修饰(Decorated Name)就是编译器在编译期间创建的一个字符串,用来指明函数的定义或原型。LINK程序或其他工具有时需要指定函数的名字修饰来定位函数的正确位置。 多数情况下程序员并不需要知道函数的名字修饰,LINK程序或其他工具会自动区分他们。当然,在某些情况下需要指定函数的名字修饰,例如在C++程序中, 为了让LINK程序或其他工具能够匹配到正确的函数名字,就必须为重载函数和一些特殊的函数(如构造函数和析构函数)指定名字装饰。另一种需要指定函数的 名字修饰的情况是在汇编程序中调用C或C++的函数。如果函数名字,调用约定,返回值类型或函数参数有任何改变,原来的名字修饰就不再有效,必须指定新的 名字修饰。C和C++程序的函数在内部使用不同的名字修饰方式

C编译器的函数名修饰规则

C编译器对函数的函数名的修饰,规则比较简单,一般为在函数名前加一个下划线,变成 _FunctionName()。所以如果C程序里有两个相同名字的函数,那么在编译的时候它们的生成的修饰名一样,调用时编译器找的时候就不知道用哪一个,也就解释了为什么C不支持函数重载。

C++编译器的函数名修饰规则

C++的函数名修饰规则有些复杂,但是信息更充分,通过分析修饰名可以知道函数的调用方式,返回值类型,参数个数甚至参数类型。在不同的编译器下规则会有所不同。所以C++的重载函数名字相同,但编译出的修饰函数名不同,就可以对应参数的不同调用到相应的函数了。

例如在Linux下反汇编中观察到的g++编译器对C++函数的修饰名
在这里插入图片描述

本图文内容来源于网友网络收集整理提供,作为学习参考使用,版权属于原作者。
THE END
分享
二维码
< <上一篇
下一篇>>