C++ 使用枚举的一些好例子

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/4564322/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-28 15:45:32  来源:igfitidea点击:

Some good example for using enums

c++cenums

提问by Quixotic

I learned enumswhen I learned C and from time to time I keep myself reminding about it and most of the time by re-reading from some source,it occurred to me that this is due to the fact I never use it in my programming,my programming interest concentrate around algorithmic problem solving so I am not sure where could I possibly use enums.

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

Could somebody suggest some good example where using enums is makes things much easy?

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

I would appreciate algorithmic examples but both of algorithmic or non-algorithmic examples are welcome.

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

回答by dsolimano

Imagine that you are programming a depth first search and you want to tag your edges with whether they are tree, back, forward, or cross. You could create an enum EDGE_TYPE with the four possibilities and use it to tag your edges.

想象一下,您正在编写深度优先搜索,并且想要标记边缘是树形、后向、向前还是交叉。您可以创建具有四种可能性的枚举 EDGE_TYPE 并使用它来标记您的边缘。

回答by Bojan Komazec

When describing/observing some attribute of some system you might find that attribute can have any value from a limitedset. Name those values, assign each an integer value (code), collect them in an enumeration and you have defined a typeof that attribute. All actions considering that attribute can now use this type.

在描述/观察某些系统的某些属性时,您可能会发现该属性可以具有有限集合中的任何值。命名这些值,为每个值分配一个整数值(代码),在枚举中收集它们,并且您已经定义了该属性的类型。考虑到该属性的所有操作现在都可以使用此类型。

Example: for some system we can consider its state as one of its attributes. We can observe it and say that it can be in 'uninitialized' state, state of 'initialization', 'active' or 'idle' state (feel free to add more states here...). If you want to perform some action on that system but which depends on the current state, how will you pass state information to that action (function)? You can pass strings 'uninitialized', 'initialization'...but more efficient, simple and safe from errors would be if you would pass just one integer from a set:

示例:对于某些系统,我们可以将其状态视为其属性之一。我们可以观察它并说它可以处于“未初始化”状态、“初始化”状态、“活动”或“空闲”状态(在这里随意添加更多状态......)。如果您想在该系统上执行某些取决于当前状态的操作,您将如何将状态信息传递给该操作(函数)?您可以传递字符串 'uninitialized'、'initialization'...但是如果您只传递一个集合中的一个整数,则更有效、更简单和更安全:

enum State
{
   Uninitialized,
   Initialization,
   Active,
   Idle
};

That function will have State as an argument and can use switch when deciding what to do depending on the current state:

该函数将 State 作为参数,并且可以在根据当前状态决定做什么时使用 switch:

void foo(..., const State state,...)
{
   ...
   switch(state)
   {
      case Uninitialized:
          cout << "Uninitialized" << endl;
          break;
      case Initialization:
          ...
   }
   ...
}

Using enumeration type to describe a limited set of attribute's values is safer then using a set of #defines and integer variable. E.g. if you have:

使用枚举类型来描述一组有限的属性值比使用一组 #defines 和整数变量更安全。例如,如果您有:

#define UNINITIALIZED  0
#define INITIALIZATION 1
#define ACTIVE         2
#define IDLE           3

and

int nState;

nothing can stop you to assign any integer value to nState:

没有什么可以阻止您为 nState 分配任何整数值:

nState = 4; // What state is 4?

If you use enumeration:

如果使用枚举:

State state;

You cannot assign to it an arbitrary integer value but only an enumerator (although underlying type for enumeration is integer! - see this):

您不能为其分配任意整数值,而只能为它分配一个枚举器(尽管枚举的基础类型是整数! - 请参阅):

state = Active;

回答by thbusch

I use them as parameters to functions as opposed to using booleans to improve readability of my code.

我将它们用作函数的参数,而不是使用布尔值来提高代码的可读性。

回答by Leniel Maccaferri

Take a look at the rationale about enumat Wikipedia.

看看维基百科关于枚举基本原理

Worth mentioning too: Enumerated Types - enums

也值得一提:枚举类型 - 枚举

回答by Brian

One use of enums is to make code clearer at the call site. Compare:

枚举的一种用途是使调用站点的代码更清晰。相比:

//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
    }
}

Even though a boolean would work just as well, someone unfamiliar with the function will need to work much harder to determine what it does in the case that a boolean was used. Kick(Dog)is much clearer than Kick(false).

即使布尔值也能正常工作,但不熟悉该函数的人将需要更加努力地确定在使用布尔值的情况下它的作用。 Kick(Dog)比 清楚得多Kick(false)

回答by davka

with all said about using enums as symbolic constant, I'd like to emphasize that in C++ using enum in a classgives a very nice, readable and convenient way of encapsulating and exposing class's capabilities, e.g.

所有关于使用枚举作为符号常量的说法,我想强调的是,在 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);
}

回答by Jonas K

You can have first value and last value and everything else inbetween those values. The every where in the code check if your values are in the range. NOW add new values to your enum between first and last and don't wory abouth changing all of these checks!

您可以拥有第一个值和最后一个值以及这些值之间的所有其他值。代码中的每个位置检查您的值是否在范围内。现在在 first 和 last 之间向您的枚举添加新值,不要担心更改所有这些检查!

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...
   }
}

回答by Thomas Matthews

enums can make code easier to read and may present better type checking during compilation.

enums 可以使代码更易于阅读,并且可以在编译期间提供更好的类型检查。

Issues With Enums

枚举问题

  1. They can be converted to intor unsigned intand assigned into those kind of variables, thus creating a hole in the type checking benefit.
  2. Their symbol name cannot be printed directly. Passing an enumto std::coutresults in the enumconverted to an integer then printed out. Most implementations must perform a table lookup to convert the enumto text before printing.
  1. 它们可以转换为intunsigned int分配到那些类型的变量中,从而在类型检查的好处中造成漏洞。
  2. 它们的符号名称不能直接打印。传递enumto std::cout导致enum转换为整数然后打印出来。大多数实现必须enum在打印之前执行表查找以将 转换为文本。

Alternatives

备择方案

Another alternative to enumis to use a string. I've worked at shops where they pass a constant string instead of an enum. One advantage is that the named value is always available, even when debug symbols are not. Also there are no conversions required when printing.

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

Some disadvantages to strings:

字符串的一些缺点:

  1. Can't be used in switchstatement.
  2. Case sensitivity when comparing.
  3. Comparing may take more execution time.
  4. Occupies more data or executable space.
  1. 不能在switch语句中使用。
  2. 比较时区分大小写。
  3. 比较可能需要更多的执行时间。
  4. 占用更多的数据或可执行空间。

回答by R.. GitHub STOP HELPING ICE

Enums have one advantage over #define, but it's purely an implementation detail: debuggers typically can show/use enumvalues but #defined values.

枚举比 有一个优势#define,但它纯粹是一个实现细节:调试器通常可以显示/使用enum值,但#defined 值。

On the other hand, #definehas several fundamental advantages, one of which is that you can test for the existence with #ifdef. This is useful if you need to support multiple versions of a library, and want to optionally use new enum-like choices if they're available.

另一方面,#define有几个基本优点,其中之一是您可以使用#ifdef. 如果您需要支持库的多个版本,并且希望有选择地使用新的类似枚举的选项(如果它们可用),这将非常有用。

Some library authors use a hybrid approach of first defining the constants with enumthen:

一些库作者使用混合方法,首先定义常量,enum然后:

#define FOO FOO
#define BAR BAR

etc.

等等。

回答by Vargeux

I started a personal project in, and I wanted to identify my packet ID, it looks like this:

我开始了一个个人项目,我想识别我的数据包 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,
};

and then, when I receive a packet, I've got a huge switch that looks like this to process the packets and send them:

然后,当我收到一个数据包时,我有一个巨大的交换机,看起来像这样来处理数据包并发送它们:

switch(packet.packetID){
    case ID_KEEP_ALIVE:
        //...
        break;
    case ID_LOGIN_REQUEST:
        //...
        break;
    case ID_CONNECTING:
        //...
        break;
    case ID_DISCONNECT:
        //...
        break;
    //..
}

it's my best example, enjoy :)

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