当我学习C时我学会了enums并不时地让我自己提醒它并且大多数时候通过从某些来源重新阅读,我突然意识到这是因为我从来没有在我的编程中使用它,我的编程兴趣集中在算法问题解决上,所以我不确定在哪里可以使用枚举。
有人可以提出一些很好的例子,使用枚举可以让事情变得简单吗?
我很欣赏算法示例,但欢迎算法或非算法示例。
答案 0 :(得分:20)
想象一下,您正在编写深度优先搜索,并且您想要标记边缘是否为树,后,前或交叉。您可以使用四种可能性创建枚举EDGE_TYPE,并使用它来标记边缘。
答案 1 :(得分:19)
在描述/观察某个系统的某些属性时,您可能会发现该属性可以包含来自有限集的任何值。命名这些值,为每个值分配一个整数值(代码),在枚举中收集它们,并定义该属性的类型。考虑该属性的所有操作现在都可以使用此类型。
示例:对于某些系统,我们可以将其状态视为其属性之一。我们可以观察它并说它可以处于“未初始化”状态,“初始化”状态,“活动”或“空闲”状态(可以在这里添加更多状态......)。如果要在该系统上执行某些操作但取决于当前状态,您将如何将状态信息传递给该操作(函数)?您可以传递字符串'未初始化','初始化'...但是如果您只从集合中传递一个整数,那么更有效,更简单且更安全的错误:
enum State
{
Uninitialized,
Initialization,
Active,
Idle
};
该函数将State作为参数,在根据当前状态决定做什么时可以使用switch:
void foo(..., const State state,...)
{
...
switch(state)
{
case Uninitialized:
cout << "Uninitialized" << endl;
break;
case Initialization:
...
}
...
}
使用枚举类型来描述一组有限的属性值比使用一组#defines和整数变量更安全。例如。如果你有:
#define UNINITIALIZED 0
#define INITIALIZATION 1
#define ACTIVE 2
#define IDLE 3
和
int nState;
没有什么可以阻止你为nState分配任何整数值:
nState = 4; // What state is 4?
如果使用枚举:
State state;
你不能给它赋一个任意整数值但只能给它一个枚举器(虽然枚举的基础类型是整数! - 见this):
state = Active;
答案 2 :(得分:8)
我将它们用作函数的参数,而不是使用布尔值来提高代码的可读性。
答案 3 :(得分:4)
查看维基百科上的rationale about enum。
答案 4 :(得分:4)
枚举的一个用途是在呼叫站点使代码更清晰。比较:
//Usage: Kick(Dog);
enum PetType
{
Cat,
Dog
};
void Kick(PetType p)
{
switch(p)
{
case Cat:
//Kick Cat
break;
case Dog:
//Kick Dog
break;
default:
//Throw an exception.
break;
}
}
//Usage: Kick(false);
void Kick(bool isCat)
{
if (isCat)
{
//Kick Cat
}
else
{
//Kick Dog
}
}
即使布尔值也能正常工作,不熟悉函数的人需要更加努力地确定在使用布尔值的情况下它的作用。 Kick(Dog)
比Kick(false)
更清晰。
答案 5 :(得分:4)
所有关于使用枚举作为符号常量的说法,我想强调的是,在C ++中使用枚举在类中提供了一种非常好的,可读且方便的封装和暴露类功能的方法,例如
class BlockCipher {
public:
enum PaddingOptions { NO_PADDING, DEFAULT_PADDING, ZERO_PADDING /*...*/ }
void encrypt(const std::string& cleartext, std::string& ciphertext,
PaddingOptions pad=DEFAULT_PADDING);
};
int main()
{
std::string clear("hello, world");
std::string encrypted;
BlockCipher encryptor;
encryptor.encrypt(clear, encrypted, BlockCipher::NO_PADDING);
}
答案 6 :(得分:2)
enum
可以使代码更易于阅读,并且可以在编译期间提供更好的类型检查。
int
或。{
unsigned int
并分配到。{
因此,那些变量
在类型检查中创建一个洞
益处。enum
到
std::cout
会产生enum
转换为整数然后打印
出。大多数实现必须
执行表查找以进行转换
打印前enum
发送文字。 enum
的另一种替代方法是使用字符串。我曾在商店里工作,他们传递的是常量字符串而不是枚举字符串。一个优点是命名值始终可用,即使调试符号不可用。此外,打印时无需转换。
switch
声明中使用。答案 7 :(得分:2)
您可以在这些值之间拥有第一个值和最后一个值以及其他所有值。代码中的每个位置都会检查您的值是否在范围内。现在在第一个和最后一个之间为你的枚举添加新的值,并且不要改变所有这些检查!
typedef enum
{
First_value,
Uninitialized,
Initialization,
Active,
Idle,
Last_value
} my_type;
void function(my_type state)
{
if ((state > First_value) && (state < Last_value))
{
//Do stuff...
}
}
答案 8 :(得分:1)
Enums比#define
有一个优势,但它纯粹是一个实现细节:调试器通常可以显示/使用enum
值但#define
d值。
另一方面,#define
有几个基本优势,其中之一就是你可以用#ifdef
来测试存在。如果您需要支持多个版本的库,并且希望在可用的情况下选择使用新的类似枚举的选项,这将非常有用。
一些图书馆作者使用混合方法,首先使用enum
然后定义常量:
#define FOO FOO
#define BAR BAR
等
答案 9 :(得分:0)
我开始了一个个人项目,我想识别我的数据包ID,它看起来像这样:
enum{
//Client to server
//Connection
ID_KEEP_ALIVE = 0x00,
ID_LOGIN_REQUEST = 0x01,
ID_CONNECTING = 0x02,
ID_DISCONNECT = 0x03,
//Player actions
ID_PLAYER_INFO = 0x04,
ID_PLAYER_MOVE = 0x05,
ID_PLAYER_ATTACK = 0x06,
//Inventory
ID_LOOT_ITEM = 0x10,
ID_DESTROY_ITEM = 0x12,
ID_USE_ITEM = 0x13,
ID_EQUIP_ITEM = 0x15,
ID_UNEQUIP_ITEM = 0x16,
ID_DROP_ITEM = 0x17,
};
然后,当我收到一个数据包时,我有一个巨大的开关,看起来像这样处理数据包并发送它们:
switch(packet.packetID){
case ID_KEEP_ALIVE:
//...
break;
case ID_LOGIN_REQUEST:
//...
break;
case ID_CONNECTING:
//...
break;
case ID_DISCONNECT:
//...
break;
//..
}
这是我最好的例子,享受:)