c語(yǔ)言中default的用法
c語(yǔ)言中default的用法
C語(yǔ)言是一門(mén)實(shí)踐性和動(dòng)手能力要求很高的大學(xué)主干課程,但是C語(yǔ)言實(shí)驗(yàn)課的教學(xué)一直不受重視,教學(xué)效果也不太理想。下面小編就跟你們?cè)敿?xì)介紹下c語(yǔ)言中default的用法,希望對(duì)你們有用。
C語(yǔ)言中的switch和default的意思
1.用于多分支選擇的switch語(yǔ)句, 其一般形式為: switch(表達(dá)式){ case 常量表達(dá)式1: 語(yǔ)句1; case 常量表達(dá)式2: 語(yǔ)句2; … case 常量表達(dá)式n: 語(yǔ)句n; default: 語(yǔ)句n+1;}
2.switch 是分支語(yǔ)句,就是比較強(qiáng)大的if集;default為不滿(mǎn)足所有的switch條件則后面的句子被執(zhí)行。一般將default寫(xiě)在switch中的最后
3.是否要使用deafult
不!但是為了進(jìn)行錯(cuò)誤檢查或邏輯檢查,還是應(yīng)該在switch語(yǔ)句中加入default分支。例如,下述switch語(yǔ)句完全合法:switch (char_code){ case tyt: case 'y': printf ( " You answered YES ! \n" ) break case 'N': case 'n': printf ("You answered NO!\n"); break}但是,如果一個(gè)未知字符被傳遞給這條switch語(yǔ)句,會(huì)出現(xiàn)什么情況呢?這時(shí),程序?qū)](méi)有任何輸出。因此,最好還是加入一個(gè)default分支,以處理這種情況:......default: printf ("Unknown response : %d\n", char_code); break......此外,default分支能給邏輯檢查帶來(lái)很多方便。例如,如果用switch語(yǔ)句來(lái)處理數(shù)目固定的條件,而且認(rèn)為這些條件之外的值都屬于邏輯錯(cuò)誤,那么可以加入一個(gè)default分支來(lái)辨識(shí)邏輯錯(cuò)誤。
c語(yǔ)言中default的用法:類(lèi)中的默認(rèn)函數(shù)
a.類(lèi)中默認(rèn)的成員函數(shù)
1.默認(rèn)構(gòu)造函數(shù)
2.默認(rèn)析構(gòu)函數(shù)
3.拷貝構(gòu)造函數(shù)
4.拷貝賦值函數(shù)
5.移動(dòng)構(gòu)造函數(shù)
6.移動(dòng)拷貝函數(shù)
b.類(lèi)中自定義的操作符函數(shù)
1.operator
2.operator&
3.operator&&
4.operator*
5.operator->
6.operator->*
7.operator new
8.operator delete
同時(shí)C++規(guī)定,一旦程序員實(shí)現(xiàn)了這些函數(shù)的自定義版本,則編譯器不會(huì)再自動(dòng)生產(chǎn)默認(rèn)版本。注意只是不自動(dòng)生成默認(rèn)版本,當(dāng)然還是可手動(dòng)生成默認(rèn)版本的。當(dāng)我們自己定義了待參數(shù)的構(gòu)造函數(shù)時(shí),我們最好是聲明不帶參數(shù)的版本以完成無(wú)參的變量初始化,此時(shí)編譯是不會(huì)再自動(dòng)提供默認(rèn)的無(wú)參版本了。我們可以通過(guò)使用關(guān)鍵字default來(lái)控制默認(rèn)構(gòu)造函數(shù)的生成,顯式地指示編譯器生成該函數(shù)的默認(rèn)版本。比如:
classMyClass
{
public:
MyClass()=default; //同時(shí)提供默認(rèn)版本和帶參版本,類(lèi)型是POD的
MyClass(inti):data(i){}
private:
int data;
};
有些時(shí)候我們希望限制默認(rèn)函數(shù)的生成。典型的是禁止使用拷貝構(gòu)造函數(shù),以往的做法是將拷貝構(gòu)造函數(shù)聲明為private的并不提供實(shí)現(xiàn),這樣當(dāng)拷貝構(gòu)造對(duì)象時(shí)編譯不能通過(guò),C++11則使用delete關(guān)鍵字顯式指示編譯器不生成函數(shù)的默認(rèn)版本。比如:
classMyClass
{
public:
MyClass()=default;
MyClass(constMyClass& )=delete;
......
}
當(dāng)然,一旦函數(shù)被delete過(guò)了,那么重載該函數(shù)也是非法的,該函數(shù)我們習(xí)慣上稱(chēng)為刪除函數(shù)。
c語(yǔ)言中default和delete的其他用途
上面我們已經(jīng)看到在類(lèi)中我們可用default和delete修飾成員函數(shù),使之成為缺省函數(shù)或者刪除函數(shù),在類(lèi)的外面,default可以在類(lèi)定義之外修飾成員函數(shù),比如:
classMyClass
{
public:
MyClass()=default;
MyClass() &operator=(constMyClass& );
);
//在類(lèi)的定義外用default來(lái)指明缺省函數(shù)版本
inlineMyClass&MyClass::operator=(constMyClass& )=default;
還可以MyClass&MyClass::operator=(constMyClass& )=default;但是這種類(lèi)外定義合成的成員就不是內(nèi)聯(lián)函數(shù)。
與=default 不同,=delete必須出現(xiàn)在函數(shù)的第一次聲明中。因?yàn)橐粋€(gè)默認(rèn)的成員只影響為這個(gè)成員生成的代碼,因此=default 直到編譯生成代碼時(shí)才需要,而編譯器必須早早知道一個(gè)函數(shù)是否是刪除的,以便禁止試圖使用它的操作。
一般情況下,析構(gòu)函數(shù)不能定義為刪除的,因?yàn)槿绻鰳?gòu)函數(shù)被刪除,就無(wú)法刪除此類(lèi)型的對(duì)象了。對(duì)于一個(gè)刪除了析構(gòu)函數(shù)的類(lèi)型,編譯器將不允許定義該類(lèi)型的變量或創(chuàng)建該類(lèi)型的臨時(shí)對(duì)象,而且如果一個(gè)類(lèi)有某個(gè)成員的類(lèi)型刪除了析構(gòu)函數(shù),也不能定義該類(lèi)的變量或臨時(shí)對(duì)象,因?yàn)橐粋€(gè)成員的析構(gòu)函數(shù)是刪除的,則該成員無(wú)法銷(xiāo)毀,包含它的類(lèi)也就沒(méi)法銷(xiāo)毀。雖然對(duì)于刪除了析構(gòu)函數(shù)的類(lèi)型,我們不能定義這種類(lèi)型的變量或成員但可以動(dòng)態(tài)分配這種類(lèi)型的對(duì)象,比如:
StructNoDtor{
NoDtor()=default;
~NoDtor()=default;
};
NoDtor *P=new NoDtor();//正確,但是我能delete P
但是有時(shí)析構(gòu)函數(shù)也是可以delete的,這樣做的目的是我們?cè)谥付▋?nèi)存位置進(jìn)行內(nèi)存分配時(shí)并不需要析構(gòu)函數(shù)來(lái)完成對(duì)象級(jí)別的清理,這時(shí)我們可顯示刪除析構(gòu)函數(shù)來(lái)限制自定義類(lèi)型在棧上或者靜態(tài)的構(gòu)造。
關(guān)于delete的顯式刪除,并非局限于成員函數(shù),比如:
voidFunc(inti){};
void Func(char c)=delete; //顯式刪除char版本
int main()
{
Func(3);
Func('c’); //無(wú)法編譯通過(guò)
return 0;
}
這里因?yàn)镕unc的char版本已經(jīng)被刪除,故Func('c')會(huì)編譯失敗。由此我們也知default是只局限作用于類(lèi)的部分成員函數(shù)的。于是我們還可用delete來(lái)避免不必要的隱式數(shù)據(jù)類(lèi)型轉(zhuǎn)換。比如:
classMyClass
{
public:
MyClass(inti){};
MyClsss(char c)=delete; //刪除char版本的構(gòu)造函數(shù)
};
void Fun(MyClass m){}
int main()
{
Func(3);
Func('a'); //編譯不能通過(guò)
MyClassm1(3);
MyClass m2('a'); //編譯不能通過(guò)
}
這是因?yàn)閏har版本的構(gòu)造函數(shù)被刪除后,試圖從char構(gòu)造MyClass對(duì)象的方式是不允許的了。但去掉這句的函數(shù)刪除后,編譯器會(huì)隱式的將a轉(zhuǎn)換為整型使得編譯通過(guò),調(diào)用的是整型構(gòu)造函數(shù),這可能并不是你所想要的。
但是如果這樣:
classMyClass
{
public:
MyClass(inti){};
explicit MyClsss(char c)=delete; //刪除explicit的char版本的構(gòu)造函數(shù)
};
void Fun(MyClass m){}
int main()
{
Func(3);
Func('a'); //編譯可通過(guò)
MyClassm1(3);
MyClass m2('a'); //編譯不能通過(guò)
}
將構(gòu)造函數(shù)explicit后,構(gòu)造函數(shù)一樣的還是不能發(fā)生char的構(gòu)造,因?yàn)閏har構(gòu)造版本被刪除了,但在Func的調(diào)用中,編譯器會(huì)嘗試將c轉(zhuǎn)換為int,即Func(\a')會(huì)調(diào)用一次MyClass(int )構(gòu)造,順利通過(guò)編譯。于是我們不提倡explicit和delete混用。對(duì)與普通函數(shù)delete也有類(lèi)型的效果。
delete的用法還包括刪除operator new操作符,編碼在堆上分配該類(lèi)的對(duì)象
如:void* operator new(std::size_t)=delete;
合成的拷貝控制成員可能是刪除的,如果一個(gè)類(lèi)有數(shù)據(jù)成員不能默認(rèn)構(gòu)造、拷貝、復(fù)制或銷(xiāo)毀,則對(duì)應(yīng)的成員函數(shù)將被定義為刪除的。因此:
如果類(lèi)的某個(gè)成員的析構(gòu)函數(shù)是刪除的或不可訪問(wèn)的,那么類(lèi)的合成析構(gòu)函數(shù)被定義為刪除的。
如果類(lèi)的某個(gè)成員的拷貝構(gòu)造函數(shù)是刪除的或不可訪問(wèn)的,則類(lèi)的合成拷貝構(gòu)造函數(shù)也被定義為刪除的。
如果類(lèi)的某個(gè)成員的拷貝賦值運(yùn)算符是刪除的或不可訪問(wèn)的,或是類(lèi)有一個(gè)const的或引用成員,則類(lèi)的合成拷貝賦值運(yùn)算符被定義為刪除的。
如果類(lèi)的某個(gè)成員的析構(gòu)函數(shù)是刪除的或不可訪問(wèn)的,或是類(lèi)有一個(gè)引用成員,它沒(méi)有類(lèi)內(nèi)初始化器,或是類(lèi)有一個(gè)const成員,它沒(méi)有類(lèi)內(nèi)初始化器且其類(lèi)型未顯示定義默認(rèn)構(gòu)造函數(shù),則該類(lèi)的默認(rèn)構(gòu)造函數(shù)被定義為刪除的
猜你喜歡:
3.c中for的用法