單引數的建構函式帶來的隱式轉換
阿新 • • 發佈:2019-01-28
建構函式會引起一個不引人注意的問題:
用單個實參來呼叫的建構函式定義了從從形參型別到類型別的一個隱式轉換。
舉個例子說:
class Sales_item { public: std::istream& input(std::istream& in); std::ostream& output(std::ostream& out); inline double avg_price() const; bool same_isbn(const Sales_item &rbs) const { return isbn == rbs.isbn; } Sales_item add(Sales_item& other); Sales_item(const std::string &book = "7115145547"):isbn(book),units_sold(0),revenue(0.0){} private: std::string isbn; unsigned units_sold; double revenue; };
這個類的same_isbn函式的輸入引數是這個類的型別,但是我們卻可以這樣呼叫這個函式:
Sales_item trans1;
string null_book = "9-999-99999-9";
trans1.same_isbn(null_book);
這是因為Sales_item的建構函式可以是帶單個實參的(也可以不帶實參,因為我定義了預設實參7115145547),這時在呼叫trans1.same_isbn(null_book);時,就會發生型別轉化:從string轉換為Sales_item。建立一個臨時的類的物件(一旦函式呼叫結束,就不能再放這個物件了)。
為了避免這個情況的發生,可以將類的建構函式宣告為explicit:
explicit Sales_item(const std::string &book = "7115145547"):isbn(book),units_sold(0),revenue(0.0){}
這樣,前面的預設型別轉化就不起作用了。所以對於單形參建構函式,除非有非常明顯的理由讓他發生隱式型別轉換,否者我們應該把它設計為explicit,防止隱式轉化的發生。
當然我們總可以為轉化而顯示的使用建構函式:
trans1.same_isbn(Sales_item(null_book));