為什麼不能使用成員變數的值作為成員函式的預設引數?
阿新 • • 發佈:2019-02-10
在解決工作中遇到一個問題時,我定義了一個類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先初始化,所以這樣做是不允許的。
--
後記:雖然問題的解決辦法還沒找到,但至少堵上了一條不可行之路。