再上一篇:5.4 作用域和存储类
上一篇:5.5 内联函数
主页
下一篇:5.7 函数的重载
再下一篇:5.8 编译预处理
文章列表

5.6 具有缺省参数值和参数个数可变的函数

《VC++程序设计基础》,讲述C++语言的语法和标准库,以及Visual C++ 函数库和MFC类库的使用,并附相关代码示例。

在C++中定义函数时,允许给参数指定一个缺省的值。在调用函数时,若明确给出了这种实参的值,则使用相应实参的值;若没有给出相应的实参,则使用缺省的值。这种函数称为具有缺省参数的函数。另外,在定义函数时,可以不明确指定参数的个数,在调用函数时,允许给出的实参个数是可变的。我们把这种函数称为参数个数可变的函数。提供这二种函数的目的是为了用户更方便地使用函数。

5.6.1 具有缺省参数的函数

我们先通过一个例子来说明具有缺省参数的函数的定义及调用。

例 5.12 具有缺省参数值的延时函数。

#include

void deleay (int n =1000)

{

for ( ; n> 0 ; n--);

}

void main(void )

{

cout << " 延时500 个单位时间 ...\n";

deleay(500);

cout << " 延时1000 个单位时间...\n";

delay(); //A

}

例中的deleay()函数是一个具有缺省参数值的函数,参数n为要延时的时间单位(长度),n的缺省值为1000。第一次调用deleay()时,给定了实参,其值为500,这时,deleay()函数中n的取值为500;而第二次调用时,没有给出实参,则n取缺省的值,其值为1000。因此,程序中的A行等同于:

delay(1000);

使用具有缺省参数的函数时,应注意以下几点:

1、缺省参数的说明必须出现在函数调用之前。方法可有二种:第一种方法是函数的定义放在最前面,如上例所示;第二种方法是先给出函数的原型说明,并在原型说明中依次列出参数的缺省值,而在后面定义函数时,不能重复指定缺省参数的值。

例 5.13 输入长方体的长度,宽度和高度,求出长方体的体积。

#include

float v(float a, float b=10, float c=20); //A

void main(void)

{

float x,y,z;

cout<<"输入第一个长方体的长度、宽度和高度:";

cin>>x>>y>>z;

cout<<"第一个长方体的体积为:"<

cout<<"输入第二个长方体的长度和宽度:";

cin>>x>>y;

cout<<"第二个长方体的体积为:"<

cout<<"输入第三个长方体的长度:";

cin>>x;

cout<<"第三个长方体的体积为:"<

}

float v(float a, float b, float c) //B

{

return a*b*c;

}

在A行中,指定了第二和第三参数的缺省值,而在B行中就不能再指定b和c的缺省值。A行也可以简写为:

float v(float a, float =10, float =20);

2、参数的缺省值可以是表达式,但表达式所用到的量必须有确定的值。

3、在定义函数时,具有缺省值的参数可有多个,但在函数定义时,缺省参数必须位于参数表中的最右边。如上例中有A行不能写为:

float v(float a, float a=10, float b);

A行也不能定义为:

float v(float a=20, float b, float =20);

这种规定的原因是,C++语言在处理函数调用时,参数是自右向左依次入栈的。并且只有这样规定后,在函数调用时,才不可能产生二义性。

4、同一个函数在不同的作用域内,可提供不同的缺省参数值。例如:void deleay (int n =100) ;

......

void b()

{

void deleay (int =200) ;

......

deleay ( ); //缺省值为200

......

}

float cc()

{

void deleay (int =300) ;

......

deleay ( ); //缺省值为300

......

}

float dd()

{

......

deleay ( ) ; //缺省值为100

......

}

void deleay (int n )

{

for ( ; n> 0 ; n--);

}

5.6.2 参数个数可变的函数

到目前为止,在定义函数时,都明确规定了函数的参数个数及类型。在调用函数时,实参的个数必须与形参相同。在调用具有缺省参数值的函数时,本质上,实参的个数与形参的个数仍是相同的,由于参数具有缺省值,因此,在调用时可省略。在某些应用中,在定义函数时,并不能确定函数的参数个数,参数的个数在调时才能确定。在C++中允许定义参数个数可变的函数。我们用一个例子来说明这种函数的定义方法及使用方法。

例 5.14 求输入若干个数中的最大数。

#include

#include

int max(int num, int b ...)

{

va_list ap;

int maxf,temp;

va_start(ap, b); //A

maxf=b; //B 把b作为最大值

for(int i=1;i< num;i++){

temp=va_arg(ap,int); //C

cout<<"temp="<

if(maxf < temp) maxf=temp;

}

va_end(ap); //D

return maxf;

}

void main(void)

{

int x,y,z,u,v;

cout<

cout<<"输入三个整数:";

cin>>x>>y>>z;

cout<<"这三个整数中的最大数为:"<

cout<<"输入四个整数:";

cin>>x>>y>>z>>u;

cout<<"这四个整数中的最大数为:"<

cout<<"输入五个整数:";

cin>>x>>y>>z>>u>>v;

cout<<"这五个整数中的最大数为:"<

}

上例中定义了一个参数个数可变的函数max(),形参表中在b后的省略号“...”表示在它的后面可以没有参数,也可以有若干个参数。

在定义参数个数可变的函数时,必定要用到三个库函数va_start()、va_arg()和va_end(),如例中所示。使用这三个函数时,必须包含头文件“stdarg.h”。首先,要说明一个va_list类型的变量,如例中的ap变量。va_list与int,float类同,它是C++系统预定义的一个数据类型,只有通过这种类型的变量才能从实际参数表中取出可变有参数。va_start()函数具有二个参数,第一个参数是va_list类型的变量,第二个参数必定是参数个数可变函数的形参表中最后一个固定参数的变量名,即在省略号“...”前的变量名。该函数的作用是,初始化参数个数可变的函数,使va_start()中的第一个实参(如例中的ap)指向参数个数可变函数的实参中的第一个可变的参数,并为取第一个可变的参数作好准备。因此,在参数个数可变的函数中在取可变的实数之前必须调用这个函数。程序中A行就是使变量ap指向参数b后的第一个可变的参数。函数va_arg()也具有二个参数,第一个参数必须与函数 va_start()的第一个参数相同,第二个参数应该是一个C++中预定义的数据类型名,如例中的int。该函数的作用是将第一个参数所指向的可变参数转换成由第二个参数所指定的类型的数据,并将该数据作为函数va_arg()的返回值;同时,使va_arg()的第一个参数指向下一个可变的参数,即为取下一个可变的参数作好准备。在上例中,执行C行语句时,先将ap所指向的实参变换成实数后,赋组变量temp,并使ap指向下一个可变的实参。函数va_end()只有一个参数,该参数必须与函数va_start()的第一个参数相同。该函数的作用是做好取可变实参的收尾工作,以便参数个数可变的函数能正常返回。程序中的D行就是完成收尾工作的。注意,在定义参数个数可变的函数过程中,在return语句之前,或在结束该函数之前,必须调用函数va_end()一次,做好结束工作;否则,在执行程序时,会出现不可预测的错误(典型的现象就是死机)。

使用参数数目可变的函数时要注意以下几点:

1、在定义函数时,固定参数部分必须放在参数表的前面,可变参数在后面,并用省略号“...”表示可变参数。在函数调用时,可以没有可变的参数,如上例中的E行。

2、必须使用函数va_start()来初始化可变参数,为取第一个可变的参数作好准备工作;使用函数va_arg()依次取各个可变的参数值;最后用函数va_end()做好结束工作,以便能正确地返回。

3、在调用参数个数可变的函数时,必定有一个参数指明可变参数的个数或总的实参个数。上例中的第一个参数值为总的实际参数的个数。另一种方法是在省略号“...”前的参数值为可变参数的个数。如上例中的函数 max()可改写为:

#include

int max(int num...)

{

va_list ap;

int maxf,temp;

if( num == 0) {

cout<<"参数个数不对!\n";

exit(2);

}

va_start(ap, num); //A

maxf=va_arg(ap,int); //B

for(int i=2;i<= num;i++){

temp=va_arg(ap,int); //C

if(maxf < temp) maxf=temp;

}

va_end(ap); //D

return maxf;

}

在该函数中,num的值为可变参数的个数。当其值为0时,表示没有可变参数,因此,不能求出最大值,终止程序的执行。