1. 定义
在 C++中,定义函数时可以给形参指定一个默认的值,这样调用函数时如果没有给这个形参赋值(没有对应的实参),那么就使用这个默认的值。
也就是说,调用函数时可以省略有默认值的参数。如果用户指定了参数的值,那么就使用用户指定的值,否则使用参数的默认值。
#include<iostream>
using namespace std;
//带默认参数的函数
void func(int n, float b=1.2, char c=‘@‘){
cout<<n<<", "<<b<<", "<<c<<endl;
}
int main(){
//为所有参数传值
func(10, 3.5, ‘#‘);
//为 n、b 传值,相当于调用 func(20, 9.8, ‘@‘)
func(20, 9.8);
//只为 n 传值,相当于调用 func(30, 1.2, ‘@‘)
func(30);
return 0;
}
默认参数只能放在形参列表的最后,而且一旦为某个形参指定了默认值,那么它后面的所有形参都必须有默认值。
void func(int a, int b=10, int c=20){ }
void func(int a, int b, int c=20){ }
2. 默认实参函数声明与定义
除了函数定义处,也可以在函数声明处指定默认参数。不过在给定的作用域中一个形参只能被赋予一次默认实参。
#include <iostream>
using namespace std;
void func(int a, int b = 10, int c = 36);
int main(){
func(99);
return 0;
}
void func(int a, int b = 10, int c = 36){
cout<<a<<", "<<b<<", "<<c<<endl;
}
编译报错,不能在函数定义和函数声明中同时指定默认参数。
// main.cc
#include <iostream>
using namespace std;
void func(int a, int b = 10, int c = 36);
int main(){
func(99);
return 0;
}
// module.cc
#include <iostream>
using namespace std;
void func(int a, int b = 10, int c = 36){
cout<<a<<", "<<b<<", "<<c<<endl;
}
此时可以编译通过,func() 的声明位于 main.cc,作用域也是 main.cc,而 func() 的定义位于 module.cc,作用域也是 module.cc,func() 的声明和定义位于不同的作用域,相互之间不影响。
// 将 func() 定义处 b、c 的默认值分别设置为 5、57,而声明处 b、c 的默认值不变,依然为 10、36。
// module.cc
#include <iostream>
using namespace std;
void func(int a, int b = 5, int c = 57){
cout<<a<<", "<<b<<", "<<c<<endl;
}
发现当前定义处的默认值修改未生效,依旧输出原来结果。编译器不管当前作用域中是函数声明还是函数定义,只要有默认参数就可以使用。它使用的是当前作用域的默认参数。
3. 多次声明同一函数
在多文件编程时,我们通常的做法是将函数声明放在头文件中,并且一个函数只声明一次,但是多次声明同一函数也是合法的。
不过有一点需要注意,在给定的作用域中一个形参只能被赋予一次默认参数。也就是说,,函数的后续声明只能为之前那些没有默认值的形参添加默认值,而且该形参右侧的所有形参必须都有默认值。
// 多次声明同一个函数
string screen(int a, int b, int c=36);
string screen(int a, int b, int c=35); // 错误
string screen(int a, int b=35, int c); // 准确
通常应该在函数声明中指定默认参数,并将该声明放在合适的头文件中。
4. 默认实参初始值
局部变量不能作为默认实参。除此之外,只要表达式的类型能转换成形参所需要的类型,该表达式就能作为默认实参。
int a = 80;
char def = ‘ ‘;
int b = 100;
string screen(int x=a, int y =b, char c=def);
string windows = screen(); // 调用 screen(80,100,‘ ‘);
void f2()
{
def = ‘*‘; // 改变默认实参的值
int a = 100; // 隐藏了外层定义的 width,但没有改变默认实参值
window = screen(); // 调用 screen(80,100,‘*‘)
}