簡體   English   中英

如何在 C++ 中使用枚舉

[英]How to use enums in C++

假設我們有一個像下面這樣的enum

enum Days {Saturday, Sunday, Tuesday, Wednesday, Thursday, Friday};

我想創建這個enum一個實例並用適當的值初始化它,所以我這樣做:

Days day = Days.Saturday;

現在我想用現有的enum值檢查我的變量或實例,所以我這樣做:

if (day == Days.Saturday)
{
    std::cout << "Ok its Saturday";
}

這給了我一個編譯錯誤:

錯誤:'.' 之前的預期主表達式令牌

所以要清楚,說之間有什么區別:

if (day == Days.Saturday) // Causes compilation error

if (day == Saturday)

?

這兩個實際上指的是什么,一個是可以的,一個會導致編譯錯誤?

這段代碼是錯誤的:

enum Days {Saturday, Sunday, Tuesday, Wednesday, Thursday, Friday};
Days day = Days.Saturday;
if (day == Days.Saturday)

因為Days不是作用域,也不是對象。 它是一種類型。 而類型本身沒有成員。 你寫的相當於std::string.clear std::string是一種類型,因此您不能使用. 在上面。 你用. 在一個類的實例上。

不幸的是,枚舉是神奇的,所以類比就到此為止了。 因為對於一個類,你可以通過std::string::clear來獲取指向成員函數的指針,但是在 C++03 中, Days::Sunday是無效的。 (這是可悲的)。 這是因為 C++(在某種程度上)與 C 向后兼容,並且 C 沒有命名空間,因此枚舉必須在全局命名空間中。 所以語法很簡單:

enum Days {Saturday, Sunday, Tuesday, Wednesday, Thursday, Friday};
Days day = Saturday;
if (day == Saturday)

幸運的是, Mike Seymour發現 C++11 已經解決了這個問題。 更改enumenum class ,它獲得自己的范圍; 所以Days::Sunday不僅有效,而且是訪問Sunday唯一途徑。 快樂的時光!

這足以聲明您的枚舉變量並進行比較:

enum Days {Saturday, Sunday, Tuesday, Wednesday, Thursday, Friday};
Days day = Saturday;
if (day == Saturday) {
    std::cout << "Ok its Saturday";
}

其中大部分應該會給你編譯錯誤。

// note the lower case enum keyword
enum Days { Saturday, Sunday, Monday, Tuesday, Wednesday, Thursday, Friday };

現在, SaturdaySunday等可以用作頂級裸常量,而Days可以用作類型:

Days day = Saturday;   // Days.Saturday is an error

同樣稍后,測試:

if (day == Saturday)
    // ...

這些enum值就像裸常量 - 它們沒有作用域 - 在編譯器的一些額外幫助下:(除非您使用 C++11枚舉類)它們不像對象或結構成員那樣封裝,例如,並且您不能將它們稱為Days成員

您將擁有您正在尋找的C++11 ,它引入了一個enum class

enum class Days
{
    SUNDAY,
    MONDAY,
    // ... etc.
}

// ...

if (day == Days::SUNDAY)
    // ...

請注意,這個 C++ 在幾個方面與 C 有點不同,一個是 C 在聲明變量時需要使用enum關鍵字:

// day declaration in C:
enum Days day = Saturday;

您可以根據需要使用一個技巧來使用范圍,只需以這種方式聲明枚舉:

struct Days 
{
   enum type
   {
      Saturday,Sunday,Tuesday,Wednesday,Thursday,Friday
   };
};

Days::type day = Days::Saturday;
if (day == Days::Saturday)

枚舉不是使用一堆 if 語句,而是非常適合用於 switch 語句

我在為我的游戲構建的關卡構建器中使用了一些枚舉/開關組合。

編輯:另一件事,我看到你想要類似的語法;

if(day == Days.Saturday)
etc

你可以在 C++ 中做到這一點:

if(day == Days::Saturday)
etc

這是一個非常簡單的例子:

EnumAppState.h

#ifndef ENUMAPPSTATE_H
#define ENUMAPPSTATE_H
enum eAppState
{
    STARTUP,
    EDIT,
    ZONECREATION,
    SHUTDOWN,
    NOCHANGE
};
#endif

一些文件.cpp

#include "EnumAppState.h"
eAppState state = eAppState::STARTUP;
switch(state)
{
case STARTUP:
    //Do stuff
    break;
case EDIT:
    //Do stuff
    break;
case ZONECREATION:
    //Do stuff
    break;
case SHUTDOWN:
    //Do stuff
    break;
case NOCHANGE:
    //Do stuff
    break;
}

如果您仍在使用 C++03 並想使用枚舉,則應該在命名空間內使用枚舉。 例如:

namespace Daysofweek{
enum Days {Saturday, Sunday, Tuesday,Wednesday, Thursday, Friday};
}

您可以在命名空間之外使用枚舉,例如,

Daysofweek::Days day = Daysofweek::Saturday;

if (day == Daysofweek::Saturday)
{
    std::cout<<"Ok its Saturday";
}

您正在尋找強類型枚舉,這是C++11標准中可用的功能。 它將枚舉轉換為具有范圍值的類。

使用您自己的代碼示例,它是:

  enum class Days {Saturday, Sunday, Tuesday,Wednesday, Thursday, Friday};
  Days day = Days::Saturday;

  if (day == Days::Saturday)  {
    cout << " Today is Saturday !" << endl;
  }
  //int day2 = Days::Sunday; // Error! invalid

如果針對 C++11 之前的 C++ 標准,使用::作為枚舉的訪問器將失敗。 但是一些舊的編譯器不支持它,一些 IDE 只是覆蓋了這個選項,並設置了一個舊的 C++ 標准。

如果您使用 GCC,請使用-std=c++11-std=gnu11啟用 C+11。

要開心!

這不應該在 C++ 中工作:

Days.Saturday

Days 不是包含您可以使用點運算符訪問的成員的范圍或對象。 這種語法只是一種 C# 主義,在 C++ 中是不合法的。

Microsoft 長期以來一直維護一個 C++ 擴展,允許您使用范圍運算符訪問標識符:

enum E { A, B, C };

A;
E::B; // works with Microsoft's extension

但這在 C++11 之前是非標准的。 在 C++03 中,枚舉中聲明的標識符僅存在於與枚舉類型本身相同的范圍內。

A;
E::B; // error in C++03

C++11 使得使用枚舉名稱限定枚舉標識符是合法的,並且還引入了枚舉類,它為標識符創建一個新的作用域,而不是將它們放置在周圍的作用域中。

A;
E::B; // legal in C++11

enum class F { A, B, C };

A; // error
F::B;

可悲的是,枚舉的元素是“全局的”。 您可以通過執行day = Saturday訪問它們。 這意味着你不能有enum A { a, b } ; enum B { b, a } ; 因為他們有沖突。

盡管 C++(不包括 C++11)具有枚舉,但其中的值會“泄漏”到全局命名空間中。
如果您不想讓它們泄露(並且不需要使用枚舉類型),請考慮以下事項:

class EnumName {  
   public:   
      static int EnumVal1;  
      (more definitions)  
};  
EnumName::EnumVal1 = {value};  
if ([your value] == EnumName::EnumVal1)  ...

當你聲明你的枚舉值時,C++ 中的枚舉就像被你給它們的名字掩蓋的整數(這不是一個定義,只是一個提示它是如何工作的)。

但是您的代碼中有兩個錯誤:

  1. 拼寫enum全部小寫
  2. 你不需要Days. 周六之前。
  3. 如果在類中聲明此枚舉,則使用if (day == YourClass::Saturday){}

我認為您的根本問題是使用. 而不是:: ,它將使用命名空間。

嘗試:

enum Days {Saturday, Sunday, Tuesday, Wednesday, Thursday, Friday};
Days day = Days::Saturday;
if(Days::Saturday == day)  // I like literals before variables :)
{
    std::cout<<"Ok its Saturday";
}

如果我們想要嚴格的類型安全和范圍枚舉,在 C++11 中使用enum class是好的。

如果我們必須在 C++98 中工作,我們可以使用InitializeSahibSan給出的建議來啟用作用域枚舉。

如果我們還想要嚴格的類型安全,下面的代碼可以實現enum

#include <iostream>
class Color
{
public:
    static Color RED()
    {
        return Color(0);
    }
    static Color BLUE()
    {
        return Color(1);
    }
    bool operator==(const Color &rhs) const
    {
        return this->value == rhs.value;
    }
    bool operator!=(const Color &rhs) const
    {
        return !(*this == rhs);
    }

private:
    explicit Color(int value_) : value(value_) {}
    int value;
};

int main()
{
    Color color = Color::RED();
    if (color == Color::RED())
    {
        std::cout << "red" << std::endl;
    }
    return 0;
}

該代碼是從 Effective C++ 3rd: Item 18 一書中的類 Month 示例修改而來的

首先,將 enum 中的 'E' 設為小寫。

其次,在“Days.Saturday”中刪除類型名稱“Days”。

第三...給自己買一本好的 C++ 書。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM