c++学习笔记(三)enum
http://www.learncpp.com/cpp-tutorial/45-enumerated-types/学习笔记基于此
枚举的使用
枚举隶属于自定义变量类型的一种,他是将一系列相关的量集合到一起,但是使用这种自定义类型定义变量时只能去这枚举中的一个量对该变量进行赋值,枚举元素都是相当于一个以字符串为代表的常量,且在定义枚举类型时,编译器不会马上就给其分配内存,只有在利用该类型定义变量时才进行内存的分配。
enum Color
{
//here begins to define the the enumerations
//These define all the possible values this type can hold
//Each enumeration is separated by a comma,not a semicolon
COLOR_BALCK,
COLOR_RED,
COLOR_BLUE,
COLOR_GREEN,
COLOR_WHITE,
COLOR_CYAN,
COLOR_YELLOW,
COLOR_MAGENTA
};
声明以上枚举类型时编译器不会为该类型分配内存,这个是很正常的,枚举是一种变量类型,就和int和float类型一样,也都是在变量定义时才进行内存的分配,声明这种类型就相当于是给未来要定义的该类型的变量造好了一个模板,相当于int是整数的模板等,是相同的,所以在定义时不会去分配,这只是一种类型,所以是没有内存分配的,内存分配只是为了变量或者常量。
枚举元素在定义完成后,编译器从将枚举元素从前到后依次从0开始等同,并且依次加1,例如
enum ItemType
{
ITEMTYPE_SWORD, //编译器将该字符串等同为0
ITEMTYPE_TORCH, // <span style="font-family: Arial, Helvetica, sans-serif;">编译器将该字符串等同为1</span>
ITEMTYPE_POTION <span style="font-family: Arial, Helvetica, sans-serif;">// </span><span style="font-family: Arial, Helvetica, sans-serif;">编译器将该字符串等同为2</span>
};
注意编译器的行为是等同于一个int值,但是不是赋值,这也是为什么定义enum类型时不会分配内存的原因之一吧?个人观点,不足为信。
但是枚举元素可以强行赋值,可以是正可以是负,但是一定要是int型的数字,不能是浮点数,在某个元素被赋值后,其后元素在此值基础上进行加1等同,例如
enum Example
{
ELEMENT_1 = 5,
ELEMENT_2, //等同于6
ELEMENT_3 = 1,
ELEMENT_4 //等同2
}
枚举元素可以被强制赋值成相同的整形量,但是不推荐这么做
枚举元素的使用就是构造一系列相关量,且每次只会使用这其中的一个,比如这个
#include<iostream>
#include<string>
enum ItemType
{
ITEMTYPE_SWORD,
ITEMTYPE_TORCH,
ITEMTYPE_POTION
};
std::string getItemName(ItemType itemType)
{
switch(itemType)
{
case ITEMTYPE_SWORD:
return std::string("sword");
break;
case ITEMTYPE_TORCH:
return std::string("Torch");
break;
case ITEMTYPE_POTION:
return std::string("Potion");
break;
}
}
int main()
{
ItemType itemType(ITEMTYPE_POTION);
std::cout << "you are carrying a " << getItemName(itemType) << std::endl;
return 0;
}
关于enum class
在C++11中可以使用enum class来定义枚举,这样做的好处是代码的安全性加强,在普通的标准enum定义时
#include <iostream>
int main()
{
enum Color
{
RED, // RED is placed in the same scope as Color
BLUE
};
enum Fruit
{
BANANA, // BANANA is placed in the same scope as Fruit
APPLE
};
Color color = RED; // Color and RED can be accessed in the same scope (no prefix needed)
Fruit fruit = BANANA; // Fruit and BANANA can be accessed in the same scope (no prefix needed)
if (color == fruit) // The compiler will compare a and b as integers
std::cout << "color and fruit are equal\n"; // and find they are equal!
else
std::cout << "color and fruit are not equal\n";
return 0;
}
以上代码输出结果是
color and fruit are equal
原因就在与编译器在编译时将color 和ruit隐式转换成为整数进行比较,枚举定义时没有显示指明枚举元素值,那么都是默认从0开始,因此枚举变量都被隐式转换成整数0来进行比较。
如果使用enum class来定义就不会出现上述问题,使用enum class定义时
#include <iostream>
int main()
{
enum class Color // "enum class" defines this as an scoped enumeration instead of a standard enumeration
{
RED, // RED is inside the scope of Color
BLUE
};
enum class Fruit
{
BANANA, // BANANA is inside the scope of Fruit
APPLE
};
Color color = Color::RED; // note: RED is not directly accessible any more, we have to use Color::RED
Fruit fruit = Fruit::BANANA; // note: BANANA is not directly accessible any more, we have to use Fruit::BANANA
if (color == fruit) // compile error here, as the compiler doesn't know how to compare different types Color and Fruit
std::cout << "color and fruit are equal\n";
else
std::cout << "color and fruit are not equal\n";
return 0;
}
执行代码是编译器直接报错,
||=== Build: Debug in enumclass (compiler: GNU GCC Compiler) ===|
E:\sourcecode\enumclass\main.cpp||In function 'int main()':|
E:\sourcecode\enumclass\main.cpp|19|error: no match for 'operator==' in 'color == fruit'|
E:\sourcecode\enumclass\main.cpp|19|note: candidates are:|
E:\sourcecode\enumclass\main.cpp|19|note: operator==(main()::Fruit, main()::Fruit) <built-in>|
E:\sourcecode\enumclass\main.cpp|19|note: no known conversion for argument 1 from 'main()::Color' to 'main()::Fruit'|
E:\sourcecode\enumclass\main.cpp|19|note: operator==(main()::Color, main()::Color) <built-in>|
E:\sourcecode\enumclass\main.cpp|19|note: no known conversion for argument 2 from 'main()::Fruit' to 'main()::Color'|
||=== Build failed: 1 error(s), 0 warning(s) (0 minute(s), 0 second(s)) ===|
此时fruit和color被作为两种不同的变量时不能进行比较的,这样就避免了出错,同时枚举量的使用范围也被限制到了每一个的枚举内部,枚举的外部是无法访问到的,在枚举变量赋值时需要加上使用空间运算符。