c++11?類中關(guān)于default、explict、implicit、noexcept、final的詳解
default
default是c++11的標(biāo)準(zhǔn),它的作用是告訴編譯器聲明一個(gè)無參的默認(rèn)構(gòu)造函數(shù)。
最初的時(shí)候我們聲明類是這樣的:
class test{
public:
int add(){}
};
由于我們沒有給默認(rèn)構(gòu)造函數(shù),c++編譯器隱式的幫我們增加了一個(gè)默認(rèn)的無參構(gòu)造函數(shù),注意這一點(diǎn)取決于編譯,有的編譯器不會(huì)增加,但大多數(shù)都會(huì),如GCC、MSVC。
但是一旦我們聲明了一個(gè)有參的構(gòu)造函數(shù):
class test{
public:
test(int a){}
int add(){}
};
那么編譯器就不會(huì)為我們提供默認(rèn)的無參構(gòu)造函數(shù)了,就會(huì)在聲明變量時(shí)必須傳入?yún)?shù)了。
所以誕生了default關(guān)鍵字,只需要在無參的構(gòu)造函數(shù)后面加上它就可以了
class test{
public:
test() = default;
test(int a){}
int add(){}
};
那么問題來了,它和我們手動(dòng)聲明無參構(gòu)造函數(shù)有什么區(qū)別?
區(qū)別一:當(dāng)使用多文件編程時(shí),使用default聲明的構(gòu)造函數(shù)不需要在寫實(shí)現(xiàn)
區(qū)別二:代碼執(zhí)行效率,當(dāng)我們使用這個(gè)關(guān)鍵字定義的構(gòu)造函數(shù),在聲明變量時(shí),編譯器不會(huì)去調(diào)用構(gòu)造函數(shù),也不會(huì)生成構(gòu)造函數(shù)的代碼,這點(diǎn)是重點(diǎn),高效率提高聲明變量的時(shí)間,如果用戶自己聲明了構(gòu)造函數(shù)會(huì)造成編譯器開辟完內(nèi)存后會(huì)去調(diào)用一次構(gòu)造函數(shù)。
explict
這個(gè)關(guān)鍵字的作用是用于修飾只有一個(gè)參數(shù)的構(gòu)造函數(shù),并要求為顯示的
那么顯示的是什么意思呢?為什么只能修飾一個(gè)構(gòu)造函數(shù)呢?
首先我們來看這段代碼
class test{
public:
test(int a){}
};
int main(){
test a(0);
test b = 2;
}
大家可以看到上面用了兩種方式的初始化,一種是(),還有一種是=號,注意這里講一下區(qū)別在哪,()構(gòu)造會(huì)直接調(diào)用最匹配的構(gòu)造函數(shù),并且不會(huì)發(fā)送隱式轉(zhuǎn)換,如果用=號則編譯器需要推導(dǎo),推導(dǎo)=號右邊是一個(gè)什么類型,然后去選擇與這個(gè)類型匹配的構(gòu)造函數(shù)
但是也可能產(chǎn)生一種問題:
class test{
public:
test(int a){}
test(char a){}
};
int main(){
test a(0);
test b = 2;
}
這里增加了一個(gè)參數(shù)char的構(gòu)造函數(shù),那么這個(gè)時(shí)候可能產(chǎn)生一種問題,就是char是可以用來表示整數(shù)的,而2又符合char能表示的范圍,所以這里就可能產(chǎn)生了隱式轉(zhuǎn)換,將2轉(zhuǎn)換為了char類型,我們用戶甚至可以手動(dòng)強(qiáng)轉(zhuǎn),如果編譯器夠聰明的話會(huì)選擇正確的構(gòu)造函數(shù),如果不夠聰明呢?
所以為了解決可能產(chǎn)生的這種問題就推出了:explict關(guān)鍵字,用這個(gè)關(guān)鍵字聲明的構(gòu)造函數(shù)是不允許用戶去做可能產(chǎn)生隱式轉(zhuǎn)換的事情
class test{
public:
explict test(int a){}
test(char a){}
};
int main(){
test a(0);
test b = 2; //這一行會(huì)報(bào)錯(cuò),因?yàn)榭赡軙?huì)發(fā)生隱式轉(zhuǎn)換
//test b = '2' //這樣也不行的,因?yàn)闀?huì)優(yōu)先匹配具有explict的構(gòu)造函數(shù),那么這樣就產(chǎn)生了隱式轉(zhuǎn)換,因?yàn)?2'可以被轉(zhuǎn)換成ascii碼
}
因?yàn)橛辛薳xplict關(guān)鍵字的存在任何可能發(fā)生隱式轉(zhuǎn)換的動(dòng)作都會(huì)被編譯器報(bào)錯(cuò),但是如果你用()來調(diào)用就沒事的
test b('c') ;
因?yàn)?)會(huì)明確表示入?yún)㈩愋停?號的話編譯器是需要推導(dǎo)=號左右兩邊類型,在去調(diào)用最合適的構(gòu)造函數(shù),那么這個(gè)時(shí)候就產(chǎn)生了可能發(fā)生隱式轉(zhuǎn)換的問題。
同時(shí)=號初始化也會(huì)拖累編譯速度,最后明確一點(diǎn),就是順序,當(dāng)調(diào)用時(shí)編譯器會(huì)優(yōu)先匹配explict的構(gòu)造函數(shù),就如剛剛的test b = '2',已經(jīng)明確是char符號了,但是編譯器仍然認(rèn)為它可能會(huì)出現(xiàn)隱式轉(zhuǎn)換,因?yàn)槭褂胑xplict關(guān)鍵字后你做的任何可能產(chǎn)生類型轉(zhuǎn)換的操作都會(huì)被編譯器優(yōu)先裁決。
最后在說明一點(diǎn)就是為什么只能用于只有一個(gè)參數(shù)的構(gòu)造函數(shù),為什么不能是多個(gè)?
答:因?yàn)槎鄠€(gè)的情況下是無法明確類型的,如果參數(shù)有兩個(gè)或兩個(gè)以上的情況下,編譯器這樣是不好推斷的,因?yàn)閮蓚€(gè)變量可能是不同的類型,如果是兩個(gè)不同的類型,那就不能做類型限定,其次類型較多的情況下對于編譯器來說也是一種負(fù)擔(dān)。
explict的意義就是在于針對一個(gè)變量的構(gòu)造函數(shù)時(shí)方式那一個(gè)參數(shù)類型出現(xiàn)隱式轉(zhuǎn)換,這個(gè)是與開發(fā)者們有關(guān),最初開發(fā)者們寫了多個(gè)只有一個(gè)參數(shù)的構(gòu)造函數(shù)時(shí),有時(shí)會(huì)發(fā)生隱式轉(zhuǎn)換導(dǎo)致調(diào)不到理想的構(gòu)造函數(shù),但是多個(gè)參數(shù)的構(gòu)造函數(shù)因?yàn)轭愋蜁?huì)更明確一點(diǎn),所以不會(huì)出現(xiàn)這樣的問題。
implicit
這個(gè)關(guān)鍵字其實(shí)根explict是相反的,它其實(shí)不存在于c++,只在java和c#這樣繼承c++特性的語言里存在,它表明的是隱藏的,就是表明構(gòu)造函數(shù)可以被隱式轉(zhuǎn)換,只是后來人們把沒有使用explict聲明的只有一個(gè)參數(shù)的構(gòu)造函數(shù)都認(rèn)為隱式帶了一個(gè)implicit,不知道是誰提的,就挺離譜的,java和c#明明是繼承c++,但是后來人們?nèi)堰@個(gè)類型隱式加到c++中。
noexcept
這是c++11增加的函數(shù),目的是為了提升函數(shù)效率,即告訴編譯器這個(gè)函數(shù)不會(huì)產(chǎn)生異常。
首先開發(fā)者們在給函數(shù)加上這個(gè)關(guān)鍵字時(shí)應(yīng)明確,你的這個(gè)函數(shù)不會(huì)出現(xiàn)任何問題
class test{
public:
explict test(int a)noexcept {}
};
這里異常的意思是指:段錯(cuò)誤和任何可能引起程序崩潰的代碼。
c++里有一套機(jī)制,就是c++好像對系統(tǒng)層的某些異常做了捕獲,當(dāng)我們使用std::string,在初始化時(shí)傳入一個(gè)NULL時(shí)會(huì)導(dǎo)致段錯(cuò)誤,然后系統(tǒng)會(huì)殺死程序,但我發(fā)現(xiàn)在殺死之前會(huì)先去調(diào)用c++的std::terminate(),然后這個(gè)函數(shù)內(nèi)部調(diào)用std::abort()來殺死我們的程序,在Linux中有消息事件可以完成這個(gè)操作。
所以我認(rèn)為這個(gè)關(guān)鍵字的作用就是告訴編譯器不要對這個(gè)函數(shù)做監(jiān)聽,這樣就可以提升函數(shù)的執(zhí)行效率,否則當(dāng)調(diào)用這個(gè)函數(shù)時(shí)c++還要去做一些事件監(jiān)聽的注冊功能,因?yàn)槿绻婚_始全都監(jiān)聽的話c++也不知道你什么時(shí)候才會(huì)調(diào)用,所以最合適的是調(diào)用的時(shí)候監(jiān)聽。
那么這樣的話就提升了函數(shù)調(diào)用時(shí)的一個(gè)速度。
final
這個(gè)關(guān)鍵字很容易理解,它就是聲明這個(gè)類不能被繼承。
class test final{
};
//這行會(huì)報(bào)錯(cuò),因?yàn)閠est不能被繼承
class test_son : public test{
}
那么還有一個(gè)用處,就是用在虛函數(shù)上,表示不能被重寫
class test{
public:
vritual int add(int a) final{}
};
子類繼承以后就不能重寫test虛函數(shù)add了,用來限定一些方法,如基類指向子類指針時(shí),如果子類重寫了(即同名函數(shù))該方法,那么父類會(huì)優(yōu)先調(diào)用子類,這樣的話就是限定子類的某些行為,達(dá)到使用父類指針指向子類這樣的多態(tài)性寫法時(shí),永遠(yuǎn)只能調(diào)用父類的這個(gè)方法。
到此這篇關(guān)于c++11 類中關(guān)于default、explict、implicit、noexcept、final的詳解的文章就介紹到這了,更多相關(guān)c++11 類default、explict、implicit、noexcept、final內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
C++ 虛函數(shù)和純虛函數(shù)的區(qū)別分析
這篇文章主要介紹了C++ 虛函數(shù)和純虛函數(shù)的區(qū)別,幫助大家更好的理解和學(xué)習(xí)c++的相關(guān)知識,感興趣的朋友可以了解下2020-10-10
QT Creator+OpenCV實(shí)現(xiàn)圖像灰度化的示例代碼
這篇文章主要為大家詳細(xì)介紹了QT如何利用Creator和OpenCV實(shí)現(xiàn)圖像灰度化效果,文中的示例代碼講解詳細(xì),感興趣的小伙伴可以嘗試一下2022-12-12
可能是全網(wǎng)最詳細(xì)的Qt連接MySQL數(shù)據(jù)庫教程
QT眾所周知是一個(gè)開源的,以C++為底層的可視化工具庫,下面這篇文章主要給大家介紹了關(guān)于最詳細(xì)的Qt連接MySQL數(shù)據(jù)庫教程的相關(guān)資料,文中通過圖文介紹的非常詳細(xì),需要的朋友可以參考下2023-04-04
C語言實(shí)現(xiàn)奇數(shù)階魔方陣的方法
這篇文章主要介紹了C語言實(shí)現(xiàn)奇數(shù)階魔方陣的方法,涉及數(shù)組及相關(guān)數(shù)學(xué)函數(shù)的使用技巧,具有一定參考借鑒價(jià)值,需要的朋友可以參考下2015-02-02
linux c++ 服務(wù)器端開發(fā)面試必看書籍整理
這篇文章主要介紹了linux c++ 服務(wù)器端開發(fā)面試必看書籍整理,需要的朋友可以參考下2020-02-02
C++ using namespace std 用法深入解析
以下是對C++中using namespace std的用法進(jìn)行了詳細(xì)的分析介紹,需要的朋友可以過來參考下2013-07-07
C語言 數(shù)據(jù)結(jié)構(gòu)鏈表的實(shí)例(十九種操作)
這篇文章主要介紹了C語言 數(shù)據(jù)結(jié)構(gòu)鏈表的實(shí)例(十九種操作)的相關(guān)資料,需要的朋友可以參考下2017-07-07

