詳解C++11強(qiáng)類型枚舉
1.傳統(tǒng)枚舉類型的缺陷
枚舉類型是C/C++中用戶自定義的構(gòu)造類型,它是由用戶定義的若干枚舉常量的集合。枚舉值對(duì)應(yīng)整型數(shù)值,默認(rèn)從0開(kāi)始。比如定義一個(gè)描述性別的枚舉類型。
enum Gender{Male,Female};
其中枚舉值Male被編譯器默認(rèn)賦值為0,F(xiàn)emale賦值為1。傳統(tǒng)枚舉類型在設(shè)計(jì)上會(huì)存在以下幾個(gè)問(wèn)題。
(1)同作用域同名枚舉值會(huì)報(bào)重定義錯(cuò)誤。傳統(tǒng)C++中枚舉常量被暴漏在同一層作用域中,如果同一作用域下有兩個(gè)不同的枚舉類型,但含有同名的枚舉常量也是會(huì)報(bào)編譯錯(cuò)誤的,比如:
enum Fruits{Apple,Tomato,Orange}; enum Vegetables{Cucumber,Tomato,Pepper}; //編譯報(bào)Tomato重定義錯(cuò)誤
其中水果和蔬菜兩個(gè)枚舉類型中包含同名的Tomato枚舉常量會(huì)導(dǎo)致編譯錯(cuò)誤。因?yàn)閑num則是非強(qiáng)作用域類型,枚舉常量可以直接訪問(wèn),這種訪問(wèn)方式與C++中具名的namespace、class/struct以及union必須通過(guò)"名字::成員名"的訪問(wèn)方式大相徑庭。
(2)由于枚舉類型被設(shè)計(jì)為常量數(shù)值的“別名”,所以枚舉常量總是可以被隱式轉(zhuǎn)換為整型,且用戶無(wú)法為枚舉常量定義類型。
(3)枚舉常量占用存儲(chǔ)空間以及符號(hào)性不確定。C++標(biāo)準(zhǔn)規(guī)定C++枚舉所基于的“基礎(chǔ)類型”是由編譯器來(lái)具體實(shí)現(xiàn),這會(huì)導(dǎo)致枚舉類型成員的基本類型存在不確定性問(wèn)題,尤其是符號(hào)性問(wèn)題,即??疾烊缦率纠?/p>
enum A{A1=1,A2=2,ABig=0xFFFFFFFFU}; enum B{B1=1,B2=2,BBig=0xFFFFFFFFFUL}; int main() { cout<<sizeof(A1)<<endl; //4 cout<<ABig<<endl; //4294967295 cout<<sizeof(B1)<<endl; //8 cout<<BBig<<endl; //68719476735 }
以上輸出結(jié)果是在Linux平臺(tái)下使用g++編譯輸出的結(jié)果,在VC++(VS2017)中的輸出結(jié)果分別是4、-1、4和-1??梢?jiàn)不同編譯器對(duì)枚舉常量的整型類型的寬度和符號(hào)有著不同的實(shí)現(xiàn)。GNU C++會(huì)根據(jù)枚舉數(shù)值的類型使用不同寬度和符號(hào)的整型,VC++則始終以有符號(hào)int來(lái)表示枚舉常量。
為了解決以上傳統(tǒng)枚舉類型的缺陷,C++11引入了強(qiáng)類型枚舉解決了這些問(wèn)題。
2.強(qiáng)類型枚舉
非強(qiáng)作用域類型,允許隱式轉(zhuǎn)換為整型,枚舉常量占用存儲(chǔ)空間以及符號(hào)性的不確定,都是枚舉類缺點(diǎn)。針對(duì)這些缺點(diǎn),C++11引入了一種新的枚舉類型——強(qiáng)類型枚舉(strong-typed enum)。
強(qiáng)類型枚舉使用enum class語(yǔ)法來(lái)聲明:
enum class Enumeration{VAL1,VAL2,VAL3=100,VAL4};
強(qiáng)類型枚舉具有如下幾個(gè)優(yōu)點(diǎn):
(1)強(qiáng)作用域,強(qiáng)類型枚舉成員的名稱不會(huì)被輸出到其父作用域,所以不同枚舉類型定義同名枚舉成員編譯不會(huì)報(bào)重定義錯(cuò)誤。進(jìn)而使用枚舉類型的枚舉成員時(shí),必須指明所屬范圍,比如Enum::VAL1,而單獨(dú)的VAL1則不再具有意義;
(2)轉(zhuǎn)換限制,強(qiáng)類型枚舉成員的值不可以與整型發(fā)生隱式相互轉(zhuǎn)換。比如比如Enumeration::VAL4==10;會(huì)觸發(fā)編譯錯(cuò)誤;
(3)可以指定底層類型。強(qiáng)類型枚舉默認(rèn)的底層類型是int,但也可以顯示地指定底層類型。具體方法是在枚舉名稱后面加上":type",其中type可以是除wchar_t以外的任何整型。比如:
enum class Type:char{Low,Middle,High};
注意:
(1)聲明強(qiáng)類型枚舉的時(shí)候,既可以使用關(guān)鍵字enum class,也可以使用enum struct。事實(shí)上,enum struct與enum class在語(yǔ)法上沒(méi)有任何區(qū)別。
(2)由于強(qiáng)類型枚舉是強(qiáng)類型作用域的,故匿名的enum class可能什么都做不了,如下代碼會(huì)報(bào)編譯錯(cuò)誤:
enum class{General,Light,Medium,Heavy}weapon; int main() { weapon=Medium; //編譯出錯(cuò) bool b=weapon == weapon::Medium; //編譯出錯(cuò) return 0; }
當(dāng)然對(duì)于匿名強(qiáng)類型枚舉我們還是可以使用decltype來(lái)獲得其類型并進(jìn)而使用,但是這樣做可能違背強(qiáng)類型枚舉進(jìn)行匿名的初衷。
3.C++11對(duì)傳統(tǒng)枚舉類型的擴(kuò)展
傳統(tǒng)枚舉類型為了配合C++11引入的強(qiáng)類型枚舉,C++11對(duì)傳統(tǒng)枚舉類型進(jìn)行了擴(kuò)展。
(1)底層的基本類型可以在枚舉名稱后加上":type",其中type可以是除wchar_t以外的任何整型,比如:
enum Type:char{Low,Middle,High};
(2)C++11中,枚舉類型的成員可以在枚舉類型的作用域內(nèi)有效。比如:
enum Type{Low, Middle, High }; Type type1 = Middle; Type type2 = Type::Middle;
其中Middle與Type::Middle都是合法的使用形式。
以上就是詳解C++11強(qiáng)類型枚舉的詳細(xì)內(nèi)容,更多關(guān)于c++ 枚舉的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
深入學(xué)習(xí)C++智能指針之shared_ptr與右值引用的方法
智能指針的核心實(shí)現(xiàn)技術(shù)是引用計(jì)數(shù),每使用它一次,內(nèi)部引用計(jì)數(shù)加1,每析構(gòu)一次內(nèi)部的引用計(jì)數(shù)減1,減為0時(shí),刪除所指向的堆內(nèi)存,今天通過(guò)本文給大家分享C++智能指針之shared_ptr與右值引用的方法,需要的朋友跟隨小編一起看看吧2021-07-07C++?QT實(shí)現(xiàn)獲取本機(jī)網(wǎng)卡信息
這篇文章主要為大家詳細(xì)介紹了如何利用qt自帶的QNetworkInterface接口以及c++Iphlpapi庫(kù),獲取當(dāng)前windows電腦下的網(wǎng)卡信息,需要的可以參考下2024-01-01數(shù)據(jù)結(jié)構(gòu) 棧的操作實(shí)例詳解
這篇文章主要介紹了數(shù)據(jù)結(jié)構(gòu) 順序棧的定義、初始化、空棧判斷、入棧、出棧操作的相關(guān)資料,需要的朋友可以參考下2017-06-06如何用C寫(xiě)一個(gè)web服務(wù)器之GCC項(xiàng)目編譯
本文主要介紹了,如何用C寫(xiě)一個(gè)web服務(wù)器,Linux下用GCC進(jìn)行項(xiàng)目編譯,對(duì)此感興趣的同學(xué),可以參考下。2021-05-05