缺省参数以及函数重载

在这里插入图片描述


在C语言中,对于函数传参,形参和实参是一一对应,必须由程序员自己传值,但对于有些程序来说,有些参数的传值较为固定,或者说并不必要。如果是在C语言中遇到后者,就需要写多个函数,来应对需求,除此之外,对于具有相同功能的情况,我们想要通过改变传参的类型来区分我们的需求,这在C语言中也做不到,因此祖师爷本贾尼等人对此进行了改善,在C++中实现了这些功能。

缺省参数

概念

缺省参数是声明或定义函数时为函数的参数指定一个默认值,在调用该函数时,如果没有传该参数,则使用默认值,如果传了该参数,就用我们自己传的参数,这使得函数更加灵活和可扩展(可扩展体现在可以任意增加函数的缺省参数,而不改变函数调用部分),也使得函数调用更加简洁.
例子:

void Print(int num = 0)
{
	cout << num << endl;
}
int main()
{
	Print(10);// 10
	Print();// 0
	return 0;
}

这里被赋值的num就是缺省参数,0赋值给num,0就是缺省值

缺省参数的两种类型

全缺省参数

void Print(int a = 1, int b = 2, int c = 3)
{
	cout << a << endl;
	cout << b << endl;
	cout << c << endl;
}
int main()
{
	Print();//1 2 3
	Print(10);// 10 2 3
	Print(10, 20);//10 20 3
	Print(10, 20, 30);//10 20 30
	Print( ,10, 20);//err
	return 0;
}

也就是说,全缺省参数依旧是一一对应的,并且如果需要自己赋值,只能按照顺序赋值,不能跳跃着赋值

半缺省参数

int Add(int a, int b = 2)
{
	return a + b;
}
int Add(int a = 1, int b)//err define
{...}
int Add(int a, int b = 1, int c)//err define
{...}
int main()
{
	cout << Add() << endl;// err
	cout << Add(1) << endl;// 3
	cout << Add(1, 3) << endl;// 4
	return 0;
}

对于半缺省参数的情况,缺省部分可以不赋值,但是非缺省部分必须赋值,比如上例的a,并且缺省部分必须是从右向左依次给出,并且不能间隔这给出。
缺省参数在以后会用的很多。

//考试分权重 考试分 平时分权重 平时分 默认平时分满分
double Fin_score(double wt, int test, double wd, int credit = 100)
{
	return test * wt + credit * wd;
}
//...

注意

如果声明和定义分开在.h和.c文件中,缺省值不能同时出现(就算是相同也会报错),建议缺省值赋值在声明中,因为声明中的内容是作为目录来来使用。

//.h
void Fun(int a, int b = 2);

//.cpp
void Fun(int a, int b)
{ ... }

缺省值常用
常量、全局变量,前者用的更多。

函数重载

概念

函数重载是函数的一种特殊情况,C++允许在同一作用域中声明几个功能类似的同名函数,并且需要保证:参数个数 或者 参数类型 或者 参数顺序 不同(没有返回类型),函数重载常用来处理实现功能类似数据类型不同的问题。

不同类型的函数重载

类型一:参数类型不同

int Add(int a, int b)
{
	return a + b;
}
double Add(double a, double b)
{
	return a + b;
}
void Swap(int& a, int& b)
{
	int tmp = a;
	a = b;
	b = tmp;
}
void Swap(int* a, int* b)
{
	int tmp = *a;
	*a = *b;
	*b = tmp;
}
int main()
{
	printf("%d\n", Add(1, 2));
	printf("%d\n", Add(1.0, 2.0));
	
	int a = 1, b = 2;
	printf("a = %d b = %d\n", a, b);
	Swap(a, b);
	printf("a = %d b = %d\n", a, b);
	Swap(&a, &b);
	printf("a = %d b = %d\n", a, b);
	return 0;
}

类型二:参数顺序不同

int sub(int a, char b)
{
	return a - (int)b;
}
int sub(char c, int d)//不关注参数名
{
	return (int)c - d;
}
int main()
{
	printf("%d\n", sub(1, 'a'));//调用第一个函数
	printf("%d\n", sub('a', 1));//调用第二个函数
	return 0;
}

类型三:参数个数

int Add(int a, int b)
{
	return a + b;
}
int Add(int a, int b, int c)
{
	return a + b + c;
}
int main()
{
	printf("%d\n", Add(1, 2));//调用第一个函数
	printf("%d\n", Add(1, 2, 3));//调用第二个函数
	return 0;
}

注意

参数名的改变并不是函数重载

int Add(int a, int b)
{
	return a + b;
}
int Add(int c, int d)
{
	return c + d;
}
//err Add(int, int)已有主体

底层逻辑

这是肯定会有人问,为什么C++能够做到?

原因在于:C++在调用函数时,对函数名进行了修饰,用修饰后的函数名去寻找( call )定义,修饰后的函数名包括函数名以及参数类型(C语言在调用时,直接用函数名去寻找定义),需要注意的是函数名的修饰规则windows、Linux等平台都不同。

windows的修饰较复杂不易理解(shit),我这里用Linux平台的修饰规则讲解底层逻辑

基础方式:_Z + 函数名字符数 + 函数名 + 类型首字母集

如果参数有指针存在,需要在类型首字母前加一个 p (ps:数组传过去也是指针)

如果参数有引用存在,需要在类型首字母前加一个 r

如果参数有自定义类型(struct class),那么在基础方式中的类型首字母变成自定义类型字符数 + 自定义类型名

举例

//定义已经省略,这里只写出了函数声明

int Add(int a, int b);
Add(1, 2)//修饰后的函数名:_Z3Addii

void Change(double a, int b = 3);
Change(1.0, 1);//修饰后的函数名:_Z6Changedi


void Swap(int* a, int* b);
int x = 1, y = 2;
Swap(&x, &y);//修饰后的函数名:_Z4Swappipi

void Swap(int& a, int& b);
int x = 1, y = 2;
Swap(x, y);//修饰后的函数名:_Z4Swapriri

struct Stu
{
	char name[20];
	int score;
};
void upload(Stu student, int number);
Stu student1 = { "Lihua", 92 };
upload(Stu, 1);//修饰后的函数名:_Z6upload3Stui

注意

有人会问那么是否可以通过返回值来区分不同的函数?
不可以!函数名修饰规则是针对调用处修饰,函数调用时没有返回值,因此是无法通过返回值来重载不同函数。
函数重载是否会影响运行速度?
不会!函数重载发生在编译阶段,只会让程序在编译阶段稍稍变慢一点(编译时对 调用函数 与 对应的函数定义 进行匹配,编译时会让调用的函数以call + 函数地址的方式链接起对应的函数定义),不会影响到运行时的速度

总结

祖师爷本贾尼用这两种方式处理了函数调用以及重名问题,提高了函数的灵活性和可复用性,以及减少编写代码时需要传递的参数数量,简化代码,使得函数调用更加方便易读,提高了开发效率。

当然C++在函数传参方面不止缺省参数和函数重载,更核心的便是提出了引用的概念,这是C++的另一大杀器,下一篇博客我将会尝试为大家讲解。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

失去梦想的小草

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值