隐式的类类型转化
隱式的類類型轉(zhuǎn)換
如果構(gòu)造函數(shù)只接受一個實參,則它實際上定義了轉(zhuǎn)換為此類類型的隱式轉(zhuǎn)換機制,有時我們把這種構(gòu)造函數(shù)稱作轉(zhuǎn)換構(gòu)造函數(shù)
能通過一個實參調(diào)用的構(gòu)造函數(shù)定義了一條從構(gòu)造函數(shù)的參數(shù)類型向類類型隱式轉(zhuǎn)換的規(guī)則。
在Sales_data類中,接受string的構(gòu)造函數(shù)和接受istream&的構(gòu)造函數(shù)分別定義了從這兩種類型向Sales_data隱式轉(zhuǎn)換的規(guī)則。也就是說,在需要使用Sales_data的地方,我們可以使用string或者istream&作為代替:
string null_book="9-999-99999-9";
//構(gòu)造一個臨時的Sales_data對象
//該對象的units_sold和revenue等于0,bookNo等于null_book
item.combine(null_book);
在這里我們用一個string實參調(diào)用了Sales_data的combine成員。該調(diào)用是合法的,編譯器用給定的string自動創(chuàng)建了一個Sales_data對象。新生成的這個(臨時)Sales_data對象被傳遞給combine。因為combine 的參數(shù)是一個常量引用,所以我們可以給該參數(shù)傳遞一個臨時量。
只允許一步類類型轉(zhuǎn)換
編譯器只會自動地執(zhí)行一步類型轉(zhuǎn)換。例如,因為下面的代碼隱式地使用了兩種轉(zhuǎn)換規(guī)則,所以它是錯誤的:
//錯誤:需要用戶定義的兩種轉(zhuǎn)換:
//(1)把"9-999-99999-9"轉(zhuǎn)換成string
//(2)再把這個(臨時的)string轉(zhuǎn)換成Sales_data
item.combine("9-999-99999-9");
如果我們想完成上述調(diào)用,可以顯式地把字符串轉(zhuǎn)換成string或者Sales_data對象:
//正確:顯式地轉(zhuǎn)換成string,隱式地轉(zhuǎn)換成Sales_data
item.combine(string("9-999-99999-9"));
//正確:隱式地轉(zhuǎn)換成string,顯式地轉(zhuǎn)換成Sales_data
item.combine(Sales_data("9-999-99999-9"));
類類型轉(zhuǎn)換不總是有效
是否需要從string到Sales_data的轉(zhuǎn)換依賴于我們對用戶使用該轉(zhuǎn)換的看法:
//使用istream構(gòu)造函數(shù)創(chuàng)建一個函數(shù)傳遞給combine
item.combine(cin);
這段代碼隱式地把cin轉(zhuǎn)換成Sales_data,這個轉(zhuǎn)換執(zhí)行了接受一個istream的Sales_data構(gòu)造函數(shù)。該構(gòu)造函數(shù)通過讀取標(biāo)準(zhǔn)輸入創(chuàng)建了一個(臨時的)Sales_data對象,隨后將得到的對象傳遞給combine。
Sale_data對象是個臨時量,一旦combine完成我們就不能再訪問它了。實際上,我們構(gòu)建了一個對象,先將它的值加到item中,隨后將其丟棄。
抑制構(gòu)造函數(shù)定義的隱式轉(zhuǎn)換
在要求隱式轉(zhuǎn)換的程序上下文中,我們可以通過將構(gòu)造函數(shù)聲明為explicit加以阻止:
class Sales_data{
public :
Sales_data()=default;
Sales_data(const std::string &s,unsigned n,double p):bookNo(s),units_sold(n),revenue(n*p){}
explicit Sales_data(const std::string &s):bookNo(s){}
explicit Sales_data(std::istream&);
//其他成員與之前的版本一致
};
此時,沒有任何構(gòu)造函數(shù)能用于隱式地創(chuàng)建Sales_data對象,之前的兩種用法都無法通過編譯:
item.combine(null_book); //錯誤:string構(gòu)造函數(shù)是explicit的
item.combine(cin); //錯誤:istream構(gòu)造函數(shù)是explicit的
關(guān)鍵字explicit只對一個實參的構(gòu)造函數(shù)有效。需要多個實參的構(gòu)造函數(shù)不能用于執(zhí)行隱式轉(zhuǎn)換,所以無須將這些構(gòu)造函數(shù)指定為explicit的。只能在類內(nèi)聲明構(gòu)造函數(shù)時使用explicit關(guān)鍵字,在類外部定義時不應(yīng)重復(fù):
//錯誤:explicit關(guān)鍵字只允許出現(xiàn)在類內(nèi)的構(gòu)造函數(shù)聲明處
explicit Sales_data::Sales_data(istream& is){
read(is,*this);
}
explicit構(gòu)造函數(shù)只能用于直接初始化
發(fā)生隱式轉(zhuǎn)換的一種情況是當(dāng)我們執(zhí)行拷貝形式的初始化時(使用=)。此時,我們只能使用直接初始化而不能使用explicit構(gòu)造函數(shù):
//正確:實參是一個顯式構(gòu)造的Sales_data對象
item.combine(Sales_data(null_book));
//正確:static_cast可以使用explicit的構(gòu)造函數(shù)
item.combine(static_cast<Sales_data>(cin));
在第一個調(diào)用中,我們直接使用Sales_data的構(gòu)造函數(shù),該調(diào)用通過接受string的構(gòu)造函數(shù)創(chuàng)建了一個臨時的Sales_data對象。在第二個調(diào)用中,我們使用static_cast執(zhí)行了顯式的而非隱式的轉(zhuǎn)換。其中,static_cast使用istream構(gòu)造函數(shù)創(chuàng)建了一個臨時的Sales_data對象。
標(biāo)準(zhǔn)庫中含有顯式構(gòu)造后函數(shù)的類
我們用過的一些標(biāo)準(zhǔn)庫的類含有單參數(shù)的構(gòu)造函數(shù):
·接受一個單參數(shù)的const char*的string構(gòu)造函數(shù)不是explicit的。
·接受一個容量參數(shù)的vector構(gòu)造函數(shù)是explicit的。
轉(zhuǎn)載于:https://www.cnblogs.com/CharlesNels/p/9555807.html
總結(jié)
- 上一篇: 杭州3月14日可领结婚证 每时段开放8
- 下一篇: 【LOJ】#2084. 「NOI2016