使用枚举的一些好例子

时间:2010-12-30 16:27:55

标签: c++ c enums

当我学习C时我学会了enums并不时地让我自己提醒它并且大多数时候通过从某些来源重新阅读,我突然意识到这是因为我从来没有在我的编程中使用它,我的编程兴趣集中在算法问题解决上,所以我不确定在哪里可以使用枚举。

有人可以提出一些很好的例子,使用枚举可以让事情变得简单吗?

我很欣赏算法示例,但欢迎算法或非算法示例。

10 个答案:

答案 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

值得一提:Enumerated Types - enums

答案 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可以使代码更易于阅读,并且可以在编译期间提供更好的类型检查。

枚举问题

  1. 他们可以转换为int或。{ unsigned int并分配到。{ 因此,那些变量 在类型检查中创建一个洞 益处。
  2. 无法打印其符号名称 直。传递enumstd::cout会产生enum 转换为整数然后打印 出。大多数实现必须 执行表查找以进行转换 打印前enum发送文字。
  3. 替代

    enum的另一种替代方法是使用字符串。我曾在商店里工作,他们传递的是常量字符串而不是枚举字符串。一个优点是命名值始终可用,即使调试符号不可用。此外,打印时无需转换。

    字符串的一些缺点:

    1. 不能在switch声明中使用。
    2. 比较时的区分大小写。
    3. 比较可能需要更多执行 时间。
    4. 占用更多数据或可执行文件 空间。

答案 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;
    //..
}

这是我最好的例子,享受:)