2009-05-22 97 views
31

爲什麼人們可以使用const作爲常量使用C++中的枚舉?爲什麼人們使用C++中的枚舉作爲常量,而他們可以使用const?

+0

我知道這是一個非常古老的線索,但你能舉一個例子嗎?當我讀到這個問題時,我正在考慮從函數返回一個int的代碼行,但是使用枚舉來定義返回值的特定「版本」,例如,錯誤條件,超時條件等。下面的一些答案似乎解決了完全不同的問題。在我看來,以這種方式使用枚舉是錯誤的,除非,正如人們所說,你的編譯器的功能受限於靜態常量。 – cosimo193 2017-05-17 14:52:12

+0

[我應該使用#define,enum還是const?](https://stackoverflow.com/questions/112433/should-i-use-define-enum-or-const) – 2018-03-08 09:21:58

回答

20

枚舉意味着一組相關的常量,因此添加的關係信息必須在他們的問題模型中有用。

+30

嗯,那看起來不像就像這個問題的答案一樣(雖然它被接受了)。人們使用枚舉,他們可以使用`const`,並且這些值與**不相關。通常你會看到`enum {SOMETHING = 2232; }(像那樣;只有一個值的匿名枚舉)而不是`const int SOMETHING = 2232;`。這是因爲枚舉永遠不會獲得任何存儲空間,而const變量仍然是一個變量,如果編譯器無法預測,它將獲得(靜態)存儲空間,而這通常不會需要存儲空間。 – 2011-05-12 12:09:52

+0

另一個原因是「const」POD變量是一個較新的C++特性,並且許多較舊的代碼庫(以及喜歡更高兼容性的程序員)仍然存在。 – 2016-11-21 06:13:09

-1

一個原因是const需要更多的打字:

enum { Val1, Val2, Val3 }; 

... ...與

const int Val1=0, Val2=1, Val3=2; 
+1

這不是唯一的原因。而且,在打字方面沒有太大的區別。 – 2009-05-23 11:17:03

34

枚舉是不同的類型,所以你可以做面向類型的東西像超載他們:

enum Color { Red,Green,Blue }; 
enum Size { Big,Little }; 

void f(Color c) { 
} 

void f(Size s) { 
} 

int main() { 
    f(Red); 
    f(Big); 
} 
+5

這不是問題的問題。問題是:爲什麼人們寫這樣的東西: enum {Margin = 50}; – Claudio 2013-10-16 08:37:42

20

當處理模板遇到了也有一個歷史原因aprogramming。一些編譯器可以使用枚舉中的值,但不能使用靜態const int來實例化類。

template <int N> 
struct foo 
{ 
    enum { Value = foo<N-1>::Value + N }; 
}; 

template <> 
struct foo<0> 
{ 
    enum { Value = 0; } 
}; 

現在你可以做的更明智方式:

template <int N> 
struct foo 
{ 
    static const int Value = foo<N-1>::Value + N; 
}; 

template <> 
struct foo<0> 
{ 
    static const int Value = 0; 
}; 

另一個可能的原因是,靜態const int的可能在運行時爲它保留內存,而枚舉永遠不會有一個爲它保留的實際內存位置,並將在編譯時處理。請參閱this related question.

10

枚舉在使用時更具描述性。試想一下:

int f(int fg, int bg) 

int f(COLOR fg, COLOR bg) 

此外,枚舉給多一點類型安全,因爲

  • 整數不隱式轉換爲枚舉類型
  • 枚舉之一類型不能隱式轉換爲另一種類型的枚舉
+0

這是一個古老的線索,但這個答案的結尾處的兩個陳述是錯誤的,需要糾正。 – motiz88 2013-09-12 11:13:06

+4

「整數不能隱式轉換爲枚舉類型」和「一種類型的枚舉不能隱式轉換爲另一種類型的枚舉」 - false。 在C++中,普通的`enum`將默默地轉換爲整數,因此它們嚴格地不提供這種安全性。但是,在C++ 11中,有一個`enum class`,它是一個適當的C++風格,對`enum`進行了「重新想象」:隱式轉換消失了,並且額外的值名必須始終是合格的。這與C#`enum`s類似,並且避免了C的舊`enum`產生的名稱衝突/命名空間污染問題。 – motiz88 2013-09-12 11:22:20

+0

@ motiz88 - 我想你可能會對此感到困惑。在gcc上試試這個代碼(你需要自己重新格式化): int main(){enum MyEnum1 {VAL11,VAL12,VAL13};枚舉MyEnum2 {VAL21,VAL22,VAL23,VAL24}; int int1 = VAL11; MyEnum1 enum1 = 3; MyEnum2 enum2 = VAL11; enum2 = enum1; int int2 = enum1;返回0; } 枚舉值會隱式地轉換爲整數,但反之亦然,而「枚舉類型」不會在對方之間隱式轉換。 原則上我相信ASk在這裏是正確的,但我不認爲它實際上是對操作問題的回答! – cosimo193 2017-05-17 15:25:47

4

枚舉也可以用作類型名稱。所以你可以定義一個函數,它將一個枚舉作爲一個參數,這使得它更清楚應該給這個函數什麼類型的值作爲參數,相比之下,將這些值定義爲const變量,並且函數只接受「int」作爲論據。

考慮:

enum my_new_fangled_type { 
    baz = 0, 
    meh = 1 
}; 

void foo (my_new_fangled_type bar) // bar can be a value listed in the enum 
{ 
    ... 
} 

與:

int const baz = 0; 
int const meh = 1; 

void foo (int bar) // what are valid values for bar? 
{ 
    ... 
} 
0

使用枚舉記錄了一個簡潔的方式有效的選擇,並允許編譯器強制執行。

如果他們使用枚舉存儲全局常量,例如Pi,那麼我不知道他們的目標是什麼。

10

我喜歡可與枚舉使用的自動行爲,例如:

enum {NONE, START, HEY, HO, LAST}; 

然後很容易循環,直到LAST,並且當一個新的狀態(或任何被表示)加入,所述邏輯適應。

for (int i = NONE; i < LAST; i++) 
{ 
    // Do stuff... 
} 

添加的東西...

enum {NONE, START, HEY, WEE, HO, LAST}; 

環路適應...

5

之前編譯器廠商實施了ISO/IEC 14882:1998的C++標準,這個代碼來定義一個常數類範圍導致編譯錯誤:

class Foo { 
    static const int MAX_LEN = 80; 
    ... 
}; 

如果該常量是整數類型,則kludgy解決方法是d efine它在類中枚舉:

class Foo { 
    enum { 
     MAX_LEN = 80 
    }; 
    ... 
}; 
41

布魯斯·埃克爾給出Thinking in C++一個原因:

In older versions of C++, static const was not supported inside classes. This meant that const was useless for constant expressions inside classes. However, people still wanted to do this so a typical solution (usually referred to as the 「enum hack」) was to use an untagged enum with no instances. An enumeration must have all its values established at compile time, it’s local to the class, and its values are available for constant expressions. Thus, you will commonly see:

#include <iostream> 
using namespace std; 

class Bunch { 
    enum { size = 1000 }; 
    int i[size]; 
}; 

int main() { 
    cout << "sizeof(Bunch) = " << sizeof(Bunch) 
     << ", sizeof(i[1000]) = " 
     << sizeof(int[1000]) << endl; 
} 

[編輯]

我認爲這將是更公平的鏈接布魯斯Eckel的網站:http://www.mindview.net/Books/TICPP/ThinkingInCPP2e.html

2

某些調試器在調試時將顯示枚舉名稱而不是其值。這可能非常有幫助。我知道我寧願看到day_of_week = MONDAY而不是day_of_week = 1

2

這部分是因爲老的編譯器不支持真正的類常量

class C 
{ 
    const int ARealConstant = 10; 
}; 

的聲明,使不得不這樣做

class C 
{ 
    enum { ARealConstant = 10 }; 
}; 

出於這個原因,許多便攜式圖書館繼續使用此表。

的另一個原因是,枚舉可以作爲一個方便的句法設備組織類的常量到那些相關的,和那些不

class DirectorySearcher 
{ 
    enum options 
    { 
    showFiles = 0x01, 
    showDirectories = 0x02, 
    showLinks = 0x04, 
    }; 
}; 

VS

class Integer 
{ 
    enum { treatAsNumeric = true }; 
    enum { treatAsIntegral = true }; 
    enum { treatAsString = false }; 
};