C++拾趣——类构造函数的隐式转换
? ? ? ? 之前看過一些批判C++的文章,大致意思是它包含了太多的“奇技淫巧”,并不是一門好的語言。我對(duì)這個(gè)“奇技淫巧”的描述頗感興趣,因?yàn)榘凑张姓叩恼f法,C++的一些特性恰巧可以讓一些炫耀技術(shù)的同學(xué)有了炫耀的資本——畢竟路人皆知的東西卻沒什么好炫耀的。這又讓我想起了《孔乙己》中關(guān)于“回”字有幾種寫法的描述。當(dāng)時(shí)老師在上此課時(shí),是抱著批判的態(tài)度去評(píng)價(jià)孔乙己的這種思想,而我卻感覺到這其中必有一些有意思的文化在里面——或許是“回”字演變的歷程能說明什么。所以“回”字相關(guān)的內(nèi)容讓我感覺孔乙己是個(gè)純粹和可愛的人。(轉(zhuǎn)載請(qǐng)指明出于breaksoftware的csdn博客)
? ? ? ? 寫這個(gè)系列的博文,并不是我想對(duì)C++進(jìn)行什么批判,也不是想對(duì)其進(jìn)行辯護(hù)。只是想羅列一些有意思的東西,故取名拾趣。
? ? ? ? 首先我們看下一種比較常見的技術(shù)——類構(gòu)造函數(shù)的隱式轉(zhuǎn)換。這兒先說明下,之后的例子中,我會(huì)為了盡量突出主要內(nèi)容,而忽略一些可以作為充分條件但非必要條件的東西,故設(shè)計(jì)的一些代碼存在“不完善”的嫌疑。因?yàn)闉榱硕伦∷新┒?#xff0c;往往會(huì)讓整個(gè)代碼讓人感覺其重心并非在我想介紹的技術(shù)上,而在“苦行僧”式的編程原則上。
? ? ? ? 我們知道C++是一個(gè)類型嚴(yán)格的語言,比如下面一個(gè)函數(shù)
void test_int_proxy(const int_proxy& v) {printf("%d", v.value());
}
? ? ? ? 調(diào)用者對(duì)其傳參也應(yīng)該是一個(gè)int_proxy的對(duì)象,但是實(shí)際情況并非如此。那該如何表述,我個(gè)人覺得應(yīng)該是:編譯器對(duì)其傳參應(yīng)該是一個(gè)int_proxy對(duì)象。這兩種表述的區(qū)別就是“調(diào)用者”和“編譯器”的區(qū)別。我們來看一個(gè)實(shí)際例子,我們先假定int_proxy類這么定義:
class int_proxy {
public:int_proxy(int n) : _m(n) {};
public:int value() const {return _m;}
private:int _m;
};
? ? ? ? 該類非常簡單,它有一個(gè)帶參數(shù)的構(gòu)造函數(shù),并使用參數(shù)列表形式初始化類的成員變量。
? ? ? ? 一般情況下我們都會(huì)這么調(diào)用test_int_proxy方法:
test_int_proxy(int_proxy(100));
? ? ? ? 這種寫法我想沒人會(huì)有異議,但是如果出現(xiàn)下面這種寫法,就可能讓人感覺不可接受了:
test_int_proxy(100);
? ? ? ? 然而,這種寫法對(duì)上述類的定義來說是合法的!其效果和使用int_proxy控制住是一樣的。這是為什么呢?這便是類構(gòu)造函數(shù)的隱式轉(zhuǎn)換技術(shù)。C++編譯器認(rèn)為test_int_proxy方法傳入的應(yīng)該是一個(gè)const類型的int_proxy對(duì)象,然而如果它發(fā)現(xiàn)參數(shù)不是該對(duì)象時(shí),就會(huì)使用該類中可以使用該參數(shù)進(jìn)行構(gòu)造對(duì)象的方法構(gòu)造出一個(gè)臨時(shí)的對(duì)象。我們例子中傳參100是個(gè)int型數(shù)據(jù),而int_proxy正好有一個(gè)攜帶int參數(shù)的構(gòu)造函數(shù)。稍微總結(jié)下類構(gòu)造函數(shù)隱式轉(zhuǎn)換的必要條件:
- 找不到傳參類型嚴(yán)格對(duì)應(yīng)的函數(shù)
- 找到傳參類型嚴(yán)格匹配的類的構(gòu)造函數(shù)
- 因?yàn)殡[式轉(zhuǎn)換構(gòu)造出的是臨時(shí)對(duì)象,所以不可修改,故觸發(fā)隱式轉(zhuǎn)換的函數(shù)的傳參類型必須要使用const修飾
? ? ? ? 但是個(gè)人覺得這種“奇巧淫技”還是不用為好。比如我們代碼中還有如下函數(shù):
void test_int_proxy(const int& v) {printf("%d", v + 100);
}
? ? ? ? 那么C++編譯器會(huì)針對(duì)傳100的調(diào)用上面這個(gè)過程。這樣一個(gè)函數(shù)調(diào)用有兩個(gè)匹配的調(diào)用方法就會(huì)產(chǎn)生不確定性——這兒指的不確定性并非是指編譯器調(diào)用哪個(gè)方法的不確定性,而是指維護(hù)這段代碼的人對(duì)上述代碼做調(diào)整時(shí)容易忽略一些問題而導(dǎo)致的“人禍”。
? ? ? ? 再比如,我們?cè)诖a中加入下面類和方法
class int_proxy_2 {
public:int_proxy_2(int n) : _m(n) {};
public:int value() const {return _m + 100;}
private:int _m;
};void test_int_proxy(const int_proxy_2& v) {printf("%d", v.value());
}
? ? ? ? 那么編譯器不能確定隱式轉(zhuǎn)換是要轉(zhuǎn)換哪個(gè)類,更不知道是調(diào)用哪個(gè)test_int_proxy方法了。
? ? ? ? 限制類構(gòu)造函數(shù)的隱式轉(zhuǎn)換的方法也很簡單,就是給對(duì)應(yīng)的構(gòu)造函數(shù)加上explict關(guān)鍵字
class int_proxy {
public:explicit int_proxy(int n) : _m(n) {};
? ? ? ? 這樣通過隱式轉(zhuǎn)換而構(gòu)造臨時(shí)對(duì)象的圖謀將會(huì)被察覺并禁止。
總結(jié)
以上是生活随笔為你收集整理的C++拾趣——类构造函数的隐式转换的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Redis源码解析——Zipmap
- 下一篇: 码农技术炒股之路——配置管理器、日志管理