C++ —— 缺省参数和函数重载


1.缺省参数

1.1 缺省参数的概念

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

#include<iostream>
using namespace std;

		   //缺省参数
void Func(int a = 10)
{
	cout << a << endl;
}

int main()
{
	Func();//形参使用默认缺省
	Func(20);//使用指定实参

	return 0;
}

1.2缺省参数的分类

1.全缺省参数

void Func(int a = 10, int b = 20, int c = 30)
{
	cout << "a = " << a << endl;
	cout << "b = " << b << endl;
	cout << "c = " << c << endl;
}

2.半缺省参数

void Func(int a, int b = 20, int c = 30)
{
	cout << "a = " << a << endl;
	cout << "b = " << b << endl;
	cout << "c = " << c << endl;
}

注意:
1. 半缺省参数必须从右往左依次给出,不能间隔着给;
错误示范:

void Func(int a = 10, int b = 20, int c);
void Func(int a = 10, int b, int c = 20);

正确示范:

void Func(int a = 10, int b = 20, int c = 30);

2. 缺省参数不能在声明和定义中同时出现; 原因:如果两个位置出现的缺省值不一样,那编译器就不知道用哪一个缺省值了;
错误示范:

void Func(int a = 10, int b = 20, int c = 30);
//定义和声明同时出现缺省参数
void Func(int a, int b = 20, int c = 30)
{
	cout << "a = " << a << endl;
	cout << "b = " << b << endl;
	cout << "c = " << c << endl;
}

正确示范:

//第一种:
//建议在函数声明中使用缺省
void Func(int a = 10, int b = 20, int c = 30);

void Func(int a, int b, int c)
{
	cout << "a = " << a << endl;
	cout << "b = " << b << endl;
	cout << "c = " << c << endl;
}

//第二种:
void Func(int a, int b, int c);

void Func(int a = 10, int b = 20, int c = 30)
{
	cout << "a = " << a << endl;
	cout << "b = " << b << endl;
	cout << "c = " << c << endl;
}

3. 缺省值必须是常量全局变量
4. C语言不支持(编译器不支持);

2.函数重载

自然语言中,一个词可以有多重含义,人们可以通过上下文来判断该词真实的含义,即该词被重载了;

2.1函数重载的概念

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

#include<iostream>
using namespace std;

//1.参数类型不同
int Add(int left, int right)
{
	cout << "int Add(int left, int right)" << endl;

	return left + right;
}

double Add(double left, double right)
{
	cout << "double Add(double left, double right)" << endl;

	return left + right;
}

//2.参数个数不同
void f()
{
	cout << "f()" << endl;
}

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


//3.参数类型顺序不同
void F(int a, char b)
{
	cout << "F(int a, char b)" << endl;
}

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

int main()
{
	//参数类型不同
	Add(1, 2);
	Add(1.0, 2.0);

	//参数个数不同
	f();
	f(1);

	//参数类型顺序不同
	F(1, 'a');
	F('a', 1);

	return 0;
}

在这里插入图片描述

注意:
当参数是char类型时,尽量不要使用ASCI码来传参,否则会导致二义性

2.2 当函数重载遇上缺省参数

先看看下面这段代码中的函数构不构成函数重载,如果构成,那是否可以调用?

int f(int a = 10, int b = 20)
{
	return a + b;
}

void f()
{
	cout << "hello world" << endl;
}

int main()
{
	f(1, 2);
	f();

	return 0;
}

当运行程序后,可以发现:第二个函数调用失败了,但它的错误却并不是不构成函数重载(上述两个函数构成函数重载);其失败原因刚才也提到过:二义性;因为第二个函数调用既可以调用无参的那个函数,也可以调用全缺省的那个函数,这就导致编译器也不知道你要调用的是哪一个函数了!

结论:
哪怕你的函数构成函数重载,也应该避免出现二义性的情况,否则调用也会失败;

2.3 函数重载的原理 —— 函数名修饰

为什么C++支持函数重载,而C语言不支持呢?
在C/C++中,一个程序要运行起来,需要经历以下几个阶段:预处理、编译、汇编、链接
在这里插入图片描述
在这里插入图片描述
先用一段小代码来举例:

int Add(int a, int b)
{
	return a + b;
}

int func(int a, double b, int* p)
{};

当上述这段代码在进行编译后,各个函数就会形成符号(该符号以函数名为名并具有函数地址),在汇编时便会将这些符号汇总到一起形成符号表,在链接时,函数的调用就会去符号表中寻找指定函数;
C为什么不支持函数重载便是出在这符号命名上!
在C语言中,编译阶段生成的符号一般都是以函数名为名的,比较粗糙;
由于vs下的符号名较为繁琐,我们下面以linux中的gcc和g++为例;
在linux下gcc(C编译器) 对上述代码编译后生成的符号:
在这里插入图片描述
在linux下g++(C++编译器) 对上述代码编译后生成的符号:
在这里插入图片描述
可以看到,在C++编译器完成编译后,函数名发生了变化;如果再仔细一点,可以看出编译器将函数参数类型信息添加到修改的函数名中;
g++的函数修饰后变成:_Z + 函数名长度 + 函数名 + 类型首字母;

结论:
C++支持函数重载的原因是:C++编译器在进行编译时,会对函数生成的符号进行特殊处理:将函数参数类型加入到生成的符号名中; 而C编译在编译时,则缺少这样的处理,其符号名与函数名是相同的,导致了同名函数无法共存;

2.3函数重载为什么只与参数有关,而与返回值无关

我们现在已经知道了:函数重载与函数的参数(参数类型 或 参数的个数 或 参数类型的顺序)有关,这也是因为函数的参数与函数名修饰规则关联;
既然函数参数可以进行函数名修饰,为什么返回值没有一同进行修饰呢?
答案是:因为在调用重载函数时,编译器只能根据函数参数来确定你要调用的是哪一个函数,而无法根据返回值来确定比如:

//错误示范
int Add(int a, int b)
{
	return a + b;
}

void Add(int a, int b)
{
	cout << a + b << endl;
}

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

	return 0;
}

上述代码,编译器无法确定你要调用的Add函数到底是哪一个,因为其调用参数都相同;

结论:
返回值不同,不构成重载的原因,并不是因为函数名修饰规则;真正的原因是调用时的二义性,编译器无法区分你要调用的究竟是哪个函数,因为调用时并不指定返回值类型;

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值