概念:
在函数声明或定义的时候给形参一个默认的参数。这样在调用该函数,如果没有给实参,函数的这个形参就默认为这个值。
使用规则:
1、缺省值必须从右往左给值
<span style="color:#33cc00;">//举例:
void display(int a ,int b= 1,int c = 0); </span>
2、缺省值必须为常量或全局变量 (const/static/普通的 全局变量 也可以作为缺省参数)
<span style="color:#33cc00;">//举例:</span>
<span style="color:#009900;">static int a = 0;
int b = 1;
void display(int data0 =b ,int data1 = a)
{
std::cout << data0<<" "<<data1 << std::endl;
}
int main()
{
display();
return 0;
}</span>
3、缺省参数只能出现在声明或者定义的一处
4、不能把 const的全局变量 作为缺省值
5、缺省值不构成函数重载,缺省值并没有赋予函数新的功能
特点:
缺省值可能提高函数的易用性,但是也可能会降低函数的可理解性。所以要适当使用缺省值。
缺省参数的使用
举例:
<span style="color:#3366ff;">String(char* str = "")//把""作为缺省参数给str
:_str(new char[strlen(str)+1])
{
strcpy(_str, str);
}</span>
使用误区:
1.滥用缺省参数,损害代码的结构和可读性。
void f(bool b=false)
{
if (b)
{
// file://code of open file
}
else
{
// file://code of close file
}
}
这个函数 f (false) 、f() 都能关闭文件,如果这样混合使用,会使维护工作增加困难。语气这样写还不如把这个函数分开写成两个函数。void Open()
{
// file://code of open file
}
void Close()
{
// file://code of close file
}
同样,在学习自己实现一个string类的时候,不该把构造函数的缺省参数给 为NULL。 class CString
{
private:
char * pcData;
public:
<span style="color:#ff0000;"> CString(char * pc=NULL);</span>
};
CString::CString(char * pc)
{
if (pc==NULL)
{
pcData=new char[1];
//...
}
else
{
pcData=new char[strlen(pc)+1];
//...
}
}
给一个NULL作为缺省参数,没有什么意义,起不到任何作用。所以修改成如下:
class CString
{
private:
char * pcData;
public:
<span style="color:#ff0000;"> CString();</span>
CString(char * pc);
};
<span style="color:#ff0000;"> CString::CString()
{
pcData=new char[1];
//...
}</span>
CString::CString(char * pc)
{
pcData=new char[strlen(pc)+1];
//...
}
总结: (1)凡是出现利用缺省参数值作if判断,并且判断后实现代码完全不同的,都应该分拆成两个独立的函数。
(2)只有缺省参数值在函数体中被无歧视的对待,也就是函数对于任何参数的实现机制都相同时,才可能是合理的。
2.多个缺省参数,可能引入逻辑含混的调用方式
举例:
class CPoint
{
public:
int x;
int y;
CPoint(int x=0,int y=0)
{
this->x=x;
this->y=y;
}
};
这样的类,本来没什么问题 ,但是当我创建一个对象 CPoint point(10) 的时候会发现创建的地点在(10,0)这个位置,本来的这样输入坐标是有误的。(除非你所需要的就是这样的效果)经过修改后:
class CPoint
{
public:
int x;
int y;
<span style="color:#ff0000;"> CPoint()
{
x=0;
y=0;
}</span>
CPoint(int x,int y)
{
this->x=x;
this->y=y;
}
};
这样对于刚才的情况就能很好的处理了。 3.重载时可能出现二义性
举例:
<span style="font-size:18px;">void fun(int a ,int b = 0)
{
//Do something
}
void fun1(int a )
{
//Do something
}</span>
函数在使用的时候,会调用不明确。4.派生类改写了基类虚函数的缺省参数值
class CBase
{
public:
virtual void fun(int i=0)
{
cout<<"in CBase "<<i<<endl;
}
};
class CDerive : public CBase
{
public:
virtual void fun(int i=100)
{
cout<<"CDerive "<<i<<endl;
}
};
int main()
{
CDerive d;
CBase * pb=&d;
pb->fun();
return 0;
}
记住:
缺省参数是静态绑定,而虚函数是动态绑定,所以 pb->fun(); 运行的是CDerive::f()的函数体,而使用的缺省值是CBase的0。