目录
一 缺省参数
1.缺省参数特性(备胎)
缺省参数是指我们定义函数时有给缺省值的参数,如果我们没传参数,那形参就默认用这个数,如下代码
#include<iostream>
using std::cout;
using std::endl;
void test1(int a = 2)
{
cout << a << endl;
}
int main()
{
test1();
test1(3);
return 0;
}
当我们没给test1函数传参时,cout输出为2,用的是缺省参数,若是传参了就用传的参数,缺省参数此时不起作用。
缺省参数分半缺省和全缺省。
2.半缺省参数
半缺省参数必须是从右往左,缺省参数不能间隔着定义,也就是不能year不给默认值,然后month,day都给默认值,而我们传的实参则是从左到右对应形参。
一个函数有很多参数,我们可以一部分参数给默认值,一部分不给,但是我们在函数调用的时候都得把参数给齐全,也就是说缺省参数和形参的个数和必须等于形参。
void test2(int day, int month = 5, int year = 2023)
{
cout<<day<< " " << month<<" " << year<< endl;
}
int main()
{
//半缺省函数
test2();
return 0;
}
如果像这个代码一样,day既没有缺省值又没有传参,此时就会报错说test2函数调用中的参数太少。
3.全缺省参数
是全缺省参数的函数,我们可以不传参数也可以传一部分。
void test3(int day=6, int month = 5, int year = 2023)
{
cout << day << " " << month << " " << year << endl;
}
int main()
{
//全缺省参数
test3();
test3(7);
test3(7,6);
test3(7,6,2024);
return 0;
}
但是传参不能间断传参。必须从左往右传。(下面是错误示范)
void test3(int day=6, int month = 5, int year = 2023)
{
cout << day << " " << month << " " << year << endl;
}
int main()
{
test3(7,,2024);
return 0;
}
4.缺省参数的注意事项
参数缺省值只能在声明或者定义的地方给,不能定义和声明都有缺省值,如果值不相同,编译器不知道用谁的,所以直接一刀切,不能同时给,一般给声明,如果给在函数定义,并且声明和定义在不同源文件,编译的时候就会发现函数少传了参数,直接就报错,就想去其它源文件找也要到链接阶段,但可惜编译就报错了不会到链接阶段。
二 函数重载
1. 函数重载
当我们实现功能相同的函数,比如加法函数,但是如果要处理不同类型的加法,在c语言我们只能写多个不同名函数来处理不同的数据类型,这在函数的起名字上会很麻烦,那可不可以实现多个同名函数分别针对不同的数据类型来相加,c++就设计出了函数重载,如下代码,有两个同名函数Add,但是他们的参数类型不同时(包括参数的类型,个数和顺序),我们就说这两个函数构成函数重载,当我们传参给Add的时候,编译器会主动识别参数类型,此时找到对应的函数用的参数匹配规则,但是如果Add定义在其它源文件,那就只能在链接阶段才能去找函数定义,c语言去其它源文件找函数定义是靠函数名,而但c++调用函数不是仅仅靠函数名的,因为重载函数会同名,所以是用一个修饰后的函数名,这个修饰函数名的重要部分就是参数的数据类型(具体在函数名修饰规则详说)
2. 函数重载参数类型不同强调
注意:是类型不同构成重载,不是形参名。
(1)Add(int ,double)和Add(double,int)构成函数重载,这就是参数类型不同里的顺序不一致
其它函数参数类型不同的情况都很好区分,比如个数还有形参的类型
int Add(int x, int y)
{
return x + y;
}
double Add(double x, double y)
{
return x + y;
}
int main()
{
//缺省参数尝试
test1();
test1(3);
//半缺省函数
test2(6);
//Add函数重载
cout << Add(1.1,2.2) << endl;
cout << Add(1, 2) << endl;
2. 如果是函数重载遇上缺省参数呢?
void func(int day=6, int month = 5, int year = 2023)
{
cout << day << " " << month << " " << year << endl;
}
void func()
{
cout <<"func"<< endl;
}
int main()
{
func();
return 0;
}
首先会构成重载,因为两个func虽然同名,但是他们参数个数是不一样的。但是全缺省函数调用会和无参函数调用有歧义,函数调用首先是采用参数匹配的规则,然后是找模板,最后才是函数名查找用重载函数,所以在第一步参数匹配上出现了歧义。
三 函数名修饰规则
接下来我们看看在c++下两个同名的Add函数是如何区分的
double fun(double x, double y)
{
return x + y;
}
int fun(int x, int y)
{
return x + y;
}
在linux下,用g++编译后,再用objdump -S a.out(对应生成的可执行文件)查看汇编代码,我们可以发现,参数为两个double类型的,参数名会被用两个d修饰,
而参数为两个int类型的,函数名会被用两个i修饰,这就是c++针对识别重载函数,而制定出的函数名修饰规则,编译器看到的函数名是经过修饰的,而这个修饰成分与参数类型相关,c语言无法识别重载函数,就是因为c语言的函数名并未经过参数修饰。但是我们还发现上面两个代码的返回值不一样,那返回值是否也可以加入函数名修饰呢?我们假设可以加上,那我们调用函数的时候该咋办,按道理说得加上返回值这样才能区别调用哪个函数,那之前的代码调用函数都没有加返回值,这样几乎所有涉及到函数调用的代码在这新规则下的编译器都无法运行,这简直是一场灾难!