我正在用C++进行枚举,以使用二进制标志制作一个有限状态机。看起来像:

enum VStates
{
    NEUTRAL         =   0x00000000,     // 000000
    //  Physical Status
    DRY             =   0x00000001,     // 000001
    WET             =   0x00000002,     // 000010
    HOT             =   0x00000004,     // 000100
    COLD            =   0x00000008,     // 001000
    BURNED          =   0x00000016,     // etc..
    FROZEN          =   0x00000032,
    EROS            =   0x00000064,     //
    THANATOS        =   0x00000128,     //
    SLEEP           =   0x00000256,
    STUNNED         =   0x00000512,
    PARALYZED       =   0x00001024,
    POISONED        =   0x00002048,     //
    BLIND           =   0x00004096,
    SOFT            =   0x00008192,     // Flexible
    TOUGH           =   0x00016384,     // Resistent
    MAGNETIZED      =   0x00032768,
    POSSEDERUNT     =   0x00131072,     //
    // Mental Status
    ANGRY           =   0x00262144,
    DRUGGED         =   0x00524288, // Drugs Meaning
    HORNY           =   0x01048576, // Sexual Meaning
    // Material Status
    METAL           =   0x02097152,
    WOOD            =   0x04194304,
    GLASS           =   0x08388608,
    AIR             =   0x16777216,
    EARTH           =   0x33554432,
    DUST            =   0x67108864,
    LIGHT           =   0x134217728,
    SHADOW          =   0x268435456,
    WATER           =   0x536870912,
    // Total Status
    PROTECTED       =   0x1073741824,
    INVULNERABLE    =   0x2147483648

};

有些状态是不兼容的,所以我使用按位运算符来管理它们。现在,我的编译器说:
warning: integer constant is too large for 'long' type

这是声明此枚举的正确方法吗?我喜欢避免警告,因此,如何解决此问题?

最佳答案

(注意:为使答案完整,我将添加一些我没有花时间注意到的内容,但其他人指出:您使用的是0x前缀,这意味着您的数字将被解释为十六进制。实际上是2的幂,并且您的位标志测试将无法正常工作!)

如果您的枚举已失去控制,请不要使用枚举类型。使用类似 std::bitset 的东西。然后,您的枚举可以只是名称集中的简单编号列表,而您将不会成倍地耗尽枚举空间!

例如:

enum VState {
    NEUTRAL,
    DRY,
    WET,
    COLD,
    BURNED,
    FROZEN,
    /* ... */
    VState_Max
};

bitset<VState_Max> state;

state[COLD] = true;
if (state[COLD]) {
    cout << "I am cold\n";
}

现在,您的枚举很小,可以维护,您不必担心会在64位平台上运行。

我注意到您在原始示例中将NEUTRAL的值设置为“0”。如果您的意图是可以将其与其他功能结合使用……例如能够成为state = NEUTRAL | INVULNERABLE | SHADOW并单独测试NEUTRAL,那将是以前无法实现的。现在它将...您只需将其保留在为位集编制索引的枚举中即可。

但是,如果打算将其用作“nothing set”的名称,则可以将其从枚举中删除,而无需测试是否设置了以下任何位:
if (state.none()) {
    // we are in the "NEUTRAL" state of nothing set...
}

...如果您想将所有位设置为false,则可以使用:
state.reset();

10-05 18:16
查看更多