在解决工作中遇到一个问题时,我定义了一个类c(如下所示),包含两个功能类似的公共查询接口Rate()和Rate(char bs_flag, char sh_flag),二者的区别是,在实例化对象的时候,会包含bs_flag和sh_flag,因此我希望有一个不用指定查询条件的Rate函数,用来反映默认情形;但有时又需要变更查询条件查询,如第二个指定查询条件的Rate函数,那么能否将这两个函数合并呢?
class CFeeSettings
{
public:
CFeeSettings(const CFeesParas &s);
double Rate();
double Rate(char bs_flag, char sh_flag);
private:
// ...
};
我想到三个办法:
第一,定义一个设置查询条件的函数SetCond(char bs_flag, char sh_flag),然后将带参数的查询接口Rate去掉,如下面所示:
class CFeeSettings
{
public:
CFeeSettings(const CFeesParas &s);
double Rate();
void Set(char bs_flag, char sh_flag);
private:
// ...
};
但是这样做会很麻烦,每次查询条件有变化之时,在调用Rate之前,都要调用Set,代码将不清晰且冗余;
第二,去掉无参查询接口Rate:
class CFeeSettings
{
public:
CFeeSettings(const CFeesParas &s);
double Rate(char bs_flag, char sh_flag);
private:
// ...
};
这样的话,即使查询条件不变更,也必须输入条件,仍然不简洁;
第三,使用默认参数:
class CFeeSettings
{
public:
CFeeSettings(const CFeesParas ¶s);
double Rate(char bs_flag=m_bs_flag, char sh_flag=m_sh_flag);
private:
// ...
char m_bs_flag;
char m_sh_flag;
};
本以为这样可以了,但竟然报了编译错误,苦思无解之余,不得已求助于网络,在stackoverflow上搜索一通之后,终于在 此处找到了答案:
原来,如果要在成员函数中使用成员变量作为默认参数时违反C++标准的:
Default arguments are evaluated each time the function is called.
The order of evaluation of function arguments is unspecified.
Consequently, parameters of a function shall not be used in default argument expressions, even if they are not evaluated.
此时我们关注第二行的内容:函数参数解析顺序是未指定的。
对于我们的成员函数来讲,如果定义为void f(int a=m_a);那么实际上f的实现为void f(X* this, int a=this->m_a);由于标准未规定a先初始化还是this先初始化,所以这样做是不允许的。
--
后记:虽然问题的解决办法还没找到,但至少堵上了一条不可行之路。