[英]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 已經解決了這個問題。 更改enum
到enum 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 };
現在, Saturday
、 Sunday
等可以用作頂級裸常量,而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++ 中的枚舉就像被你給它們的名字掩蓋的整數(這不是一個定義,只是一個提示它是如何工作的)。
但是您的代碼中有兩個錯誤:
enum
全部小寫Days.
周六之前。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 中工作,我們可以使用InitializeSahib
和San
給出的建議來啟用作用域枚舉。
如果我們還想要嚴格的類型安全,下面的代碼可以實現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.