關(guān)于Explicit還是Implicit一直是編程語言中能讓程序員們干起架的爭議。那些聰明的老鳥總是覺得Implicit的規(guī)則讓他們能夠一目十行,減少樣板代碼的羈絆。而很多時候,Implicit的很多規(guī)則會讓新手或者是合作開發(fā)的搭檔痛苦不堪。文章的標題也寫明了筆者的態(tài)度,顯式的在代碼之中指明自己的意圖,會讓程序更加明晰。所以也借今天這篇文章,我們來聊聊Explicit關(guān)鍵字。
1.隱式類類型轉(zhuǎn)換
好吧,先看一段代碼:
(為了簡單起見,我這里就沒有重載<<操作符了)
class A {
public:
A(int s) {};
};
void printA(A a) {
cout << "hello" << endl;
}
int main() {
printA(10);
}
上面這段代碼是可以通過編譯運行的,可能有些小伙伴會比較困惑,為蝦米這里printA函數(shù)明明需要接受的是一個A類型,但是傳入的一個int類型仍然能夠編譯通過。
這就被稱之為隱式類類型轉(zhuǎn)換,它存在于自定義的類構(gòu)造函數(shù)中。C++的編譯器會對只有一個參數(shù)的構(gòu)造函數(shù)也定義了一個隱式轉(zhuǎn)換,將該構(gòu)造函數(shù)對應(yīng)數(shù)據(jù)類型的數(shù)據(jù)轉(zhuǎn)換為該類對象。也就是說,上段代碼其實可以翻譯成下面的代碼:
class A {
public:
A(int s) {};
};
void printA(A a) {
cout << "hello" << endl;
}
int main() {
printA(A(10));
}
這里10作為int類型的參數(shù),通過隱式的類類型轉(zhuǎn)換,被默認構(gòu)造了一個A類型的匿名對象,傳入了函數(shù)printA,所以代碼能夠正常的編譯運行。顯然,這種類型的代碼是十分Confused。所以我們來看看這么解決這個問題的。
有一個折衷的解決方案,將代碼做下面的修改:
void printA(A &a) {
cout << "hello" << endl;
}
這里通過引用類型就可以避開這個陷阱,因為編譯器不會構(gòu)造這個匿名對象的引用,所以此時的代碼是無法通過編譯的。
顯然,這個方案改變了我們不使用引用類型的初衷,我們看看C++有木有更加優(yōu)雅的解決方案。
2.Explicit關(guān)鍵字
explicit主要用于"修飾"構(gòu)造函數(shù),使得它不用于程序中需要通過此構(gòu)造函數(shù)進行"隱式"轉(zhuǎn)換的情況。指定此關(guān)鍵字,需要隱式轉(zhuǎn)換方可進行的程序?qū)⒉荒芫幾g通過。
class A {
public:
explicit A(int s) {};
};
void printA(A a) {
cout << "hello" << endl;
}
int main() {
printA(10); //無法通過編譯
}
這里我們添加了explicit關(guān)鍵字,阻止了編譯器的隱式類類型轉(zhuǎn)換,讓代碼更加明晰了。當然,我們這里是可以使用static_cast關(guān)鍵字可以顯式的類型轉(zhuǎn)換,通過代碼的編譯。
int main() {
printA(static_cast<A>(32));
}
explicit關(guān)鍵字只對一個參數(shù)的構(gòu)造函數(shù)有效,需要多個實參的構(gòu)造函數(shù)不能用于隱式類型轉(zhuǎn)換。
3.討論一下
Scala
類型系統(tǒng)幾乎是Scala之中最復(fù)雜的內(nèi)容,Scala設(shè)計的討巧之處,是通過implicit關(guān)鍵字,顯式的指定了隱式類類型轉(zhuǎn)換。雖然隱式類類型轉(zhuǎn)換減少了很多冗余的代碼,但是這樣的設(shè)計會降低代碼的可讀性。Scala也一直因為可讀性被詬病,所以這樣的設(shè)計,見仁見智。Golang
如果是接口interface與Python是類似的鴨子類型,不需要什么隱式轉(zhuǎn)換了。
而如果是struct類的話,那Golang就十分嚴格的執(zhí)行強類型的判斷。不符合是不行的。Java
Java一直是拒絕這種Confuse做法的語言,所以通過一大堆繁瑣的樣板代碼規(guī)避這樣的問題。
“Explicit's better than implicit”。Explicit保證了代碼的可讀性和維護性。這點對于一個系統(tǒng)的工程性是很有幫助的。Implicit的轉(zhuǎn)換容易帶來那種“看上去很美,但是非常容易出錯”的 feature 。希望我們能夠告別對它的依賴。