缺省参数是声明或定义函数时为函数的 参数指定一个缺省值。 在调用该函数时,如果没有指定实参采用该形参的缺省值,否则使用指定的实参。
#include
using namespace std;
//缺省参数
void Func(int a = 10)
{
cout << a << endl;
}
int main()
{
Func();//形参使用默认缺省
Func(20);//使用指定实参
return 0;
}
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语言不支持(编译器不支持);
自然语言中,一个词可以有多重含义,人们可以通过上下文来判断该词真实的含义,即该词被重载了;
函数重载: 是函数的一种特殊情况,C++允许在同一作用域中声明几个功能类似的同名函数,这些同名函数的形参列表(参数个数 或 类型 或 类型顺序)不同,常用来处理实现功能类似数据类型不同的问题;
#include
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码来传参,否则会导致二义性;
先看看下面这段代码中的函数构不构成函数重载,如果构成,那是否可以调用?
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;
}
当运行程序后,可以发现:第二个函数调用失败了,但它的错误却并不是不构成函数重载(上述两个函数构成函数重载);其失败原因刚才也提到过:二义性;因为第二个函数调用既可以调用无参的那个函数,也可以调用全缺省的那个函数,这就导致编译器也不知道你要调用的是哪一个函数了!
结论:
哪怕你的函数构成函数重载,也应该避免出现二义性的情况,否则调用也会失败;
为什么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编译在编译时,则缺少这样的处理,其符号名与函数名是相同的,导致了同名函数无法共存;
我们现在已经知道了:函数重载与函数的参数(参数类型 或 参数的个数 或 参数类型的顺序)有关,这也是因为函数的参数与函数名修饰规则关联;
既然函数参数可以进行函数名修饰,为什么返回值没有一同进行修饰呢?
答案是:因为在调用重载函数时,编译器只能根据函数参数来确定你要调用的是哪一个函数,而无法根据返回值来确定;比如:
//错误示范
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函数到底是哪一个,因为其调用参数都相同;
结论:
返回值不同,不构成重载的原因,并不是因为函数名修饰规则;真正的原因是调用时的二义性,编译器无法区分你要调用的究竟是哪个函数,因为调用时并不指定返回值类型;