首页 > 代码库 > C++之枚举

C++之枚举

1. 声明枚举类型格式

enum Day{ Mon,Tue=5,Wed};//Mon=0;Tue=5;Wed=6
enumDay1{Mon1,Tue1,Wed1};//Mon1=0;Tue1=1;Wed1=2
enum {_Mon=2,_Tue,_Wed};//_Mon=2;_Tue=3;_Wed=4
enumDay2{Mo,Tu=3,We,Fr=4};//Mo=0,Tu=3,We=4,Fr=4

说说枚举类型中的常量。

(1) 默认的枚举中第一个为0,此后每个加1。如果遇到给定值的,后面的都是给定值加1。

(2) 允许重复值的出现。

(3) 这些值都为常量,不可修改。

(4) 可以通过“枚举名::常量名”来访问,也可以直接“常量名”来访问(注意多个枚举的重名问题)。

(5) 这些常量都会在编译时,使用常数替换掉。

 

说说枚举名。

(1) 和类名很像,属于用户自定义的数据类型。Enum就相当于class,枚举名就相当于类名。

(2)sizeof(枚举名),一般情况下等于int的size==4.

 

说说枚举变量

(1) 可以通过枚举名定义枚举变量,注意枚举变量只能使用两种方式赋值:

enum Day{ Mon,Tue=5,Wed};//Mon=0;Tue=5;Wed=6
int _tmain(int argc, _TCHAR* argv[])
{
       Dayd=Mon;//OK
       d=Day(10);//OK
       d=12;//ERROR
       const int j=2;
       d=j;//ERROR
       return 0;
}

要么是枚举常量中的值,要么是通过该枚举构造出来的值。

可以看出这些变量是可变的。

(2) 注意枚举变量和类对象的不同。它们完全不同。

枚举变量就相当于一个整型。它不拥有该枚举定义好的常量,更不能“枚举变量.枚举常量”这么使用。而类对象可以。

(3) 注意枚举变量不可被赋值为其他枚举的常量

enum Day{ Mon,Tue=5,Wed};
enum D{a};
int _tmain(int argc, _TCHAR* argv[])
{
       Daye=D::a;//ERROR
       return 0;
}

2. 说说类中的枚举

class A
{
public:enum as{a,b,c,d,e};
          void foo(){int * a=newint[d];}//OK
};
int _tmain(int argc, _TCHAR* argv[])
{
       A a;
       A::asd=A::as::a;
       cout<<sizeof(A)<<endl;//1
       cout<<A::as::a<<endl;//0
       return 0;
}

 (1) 当枚举在类中时,注意此时as只是一个数据类型,地位和A差不多,而a,b,c,d,e是枚举常量。

(2) 该枚举不占内存,sizeof(A)=1.因为此时还没有定义枚举变量。如果定义枚举变量就相当定义int变量:

class A
{
public:enum as{a,b,c,d,e};
          as s;
          as s1;
};
int _tmain(int argc, _TCHAR* argv[])
{
       cout<<sizeof(A)<<endl;//8
       return 0;
}

(3) 可以通过“类名::枚举名”来获得这个枚举类型。可以通过“类名::枚举常量”来获得该常量的值。

(4) 枚举常量可以当作[]内的值,说明它的值在编译期就被固定了。

 

总之:在类中的枚举,有点像内部类的感觉,类中的枚举常量,有点像类的conststatic常量。

 

枚举有点像类,枚举名有点像类名,而枚举变量是整型变量,完全不同于类对象。枚举常量就相当于const常量。

 

3. 枚举常量和const、#define的不同之处

(1) 取一个const常量地址是合法的,而取一个枚举常量的地址是不合法的。因为编译期会被替换为常数。同理取一个#define地址也是不合法的。

(2) 虽然枚举常量在编译期会被替换,但是会将枚举常量名保存在字符表中,如果后期有错误,编译器知道这个常数是枚举常量替换的。而#define也是在编译期被替换为常数,但是不保存宏名字,所以编译器后期只能知道这个常数,不知道这个常数是被哪个宏名称替换的。

 

4. 增加一些小知识

(1) 由于枚举名是一个类型名,所以可作为函数返回类型。

(2) 匿名定义一个枚举变量:

enum {a,b,c,d,e} as;
int _tmain(int argc, _TCHAR* argv[])
{
       as=b;
       cout<<as<<endl;//1
       return 0;
}

注意此时as是一个枚举变量,不是枚举名。

(3) 枚举变量未初始化

如果该未初始化的枚举变量定义在全局,则可以打印出其值为0.

如果该未初始化的枚举变量定义在主函数内部,则打印出错。

(4) 枚举变量不可以使用as++;这样的东西。就像类对象一样,是用户自定义类型,不可以使用。

(5)有问题的代码

enum  as{a=1,b};
void foo(as l)
{
       if(l==a){}do sth
       else{}do sth because l must be b if l !=a.
}

这段代码不能实习其本意。特别是这句话“lmust be b if l !=a.”因为枚举变量的值不一定必须是as枚举常量,因为还可以存在这样的语句“l=as(10);”。

总结:枚举变量不一定完全是枚举常量的值。

(6) cin>>枚举变量,是不合法的。cout<<枚举变量,是合法的。

 

5. C++11加入的一些有关枚举的东西

C++11中规定上面的以前的枚举被成为UnScoped枚举。而现在我们又有了Scoped枚举。

声明:enumclass/struct e_Name {…};

定义枚举变量没啥区别。e_Namee1;不需加class/struct

和以往的区别:

(1) 使用的UnScoped枚举常量时,前面必须加上枚举名。“枚举名::枚举常量”。

(2) UnScoped枚举常量不可以给int变量赋值。

 

C++之枚举