2011-03-15 51 views
13

我有一個類中,我有一個枚舉,這樣的定義:typedef'ing一個枚舉不會使枚舉值可見

class X 
    { 
    public: 
     enum Direction {DIR_LEFT, DIR_RIGHT}; 
    }; 

現在我想此枚舉在另一個類可以重複使用,像這樣:

class Y 
    { 
    public: 
     typedef X::Direction Direction; 
    }; 

正如預期的那樣,使用ÿ::方向正常工作,如:

void myFunction (Y::Direction dir) 
{ 
} 

但ENU內的值meration似乎不會與typedef一起「複製」。如果我寫了下面,我得到的編譯錯誤:

myFunction (Y::DIR_LEFT); 

相反,我不得不再次提及原來的地方枚舉的,像這樣的:

myFunction (X::DIR_LEFT); 

這違背了我的typdefing的目的枚舉。

我看到的唯一解決方案是將枚舉從類X中移出,並將其放入另一個類(例如MyEnums),以便它可以被X和Y重用(儘管它們仍應該使用MyEnums :: DIR_LEFT並且MyEnums :: DIR_RIGHT),但至少代碼不再依賴於類X.

爲什麼枚舉值本身沒有通過typedef公開?

是否有任何其他模式來管理不同類中的枚舉?

回答

14

不幸的是,C++沒有引入一個新的範圍,但是enum儘管C++ 0x正在改進。

實際上,這意味着您不能鍵入一個枚舉並獲取枚舉值。

可以 do是使用一個嵌套的結構與你想要的名稱爲枚舉和typedef THAT。

class X 
{ 
public: 
    struct Direction { enum EnumType {LEFT, RIGHT}; }; 
}; 

class Y 
{ 
public: 
    typedef X::Direction Direction; 
}; 

現在你可以這樣做: myFunction (Y::Direction::LEFT);

嵌套結構的目的是建立一個「假」的範圍holld兩個枚舉名稱和它的值。

+3

你可能應該刪除'DIR_'前綴,因爲它是一個人造的「窮人的命名空間」:'struct Direction {enum {LEFT,RIGHT};};' - 只比C++ 0x語法更髒「枚舉類方向{LEFT,RIGHT};' – anatolyg 2011-03-15 18:01:36

+0

@anatolyg事實上,這是一個好主意,我做了這個改變。 – 2011-03-15 18:19:04

0

任何由多於一個類共享的東西都應該在類之外進行分解,也可以放到父類中。

direction.hpp:

#ifndef DIRECTION_HPP 
enum Direction {DIR_LEFT, DIR_RIGHT}; 
#endif 

x.hpp:

#ifndef X_HPP 
#include "direction.hpp" 

class X 
{ 
    Direction dir; 
}; 
#endif // X_HPP 

y.hpp

#ifndef Y_HPP 
#include "direction.hpp" 

class Y 
{ 
    Direction dir; 
}; 
#endif // Y_HPP 
+0

你不是現在用你的枚舉來污染全局命名空間嗎? OP的版本沒有這個問題。 – JBentley 2013-10-08 16:46:39

0

這是我的枚舉用C如何工作++的理解。 (或者至少是我在Microsoft Visual C++中觀察到的枚舉行爲。)

enum關鍵字不會像類那樣創建範圍。

然後爲您的枚舉'方向',全名是X ::方向。該枚舉中的值仍然是類作用域的一部分,因此它們是X :: DIR_LEFT和X :: DIR_RIGHT。

當您在其他類中鍵入枚舉枚舉時,這不會更改枚舉值的範圍。

如果你想在多個位置分享它,我建議你將枚舉放入一個名稱空間的頭文件中。

0

如果你想枚舉值是既類的成員,該 解決方案是定義與枚舉一個單獨的類,並且 從它繼承,如:

class MyEnums 
{ 
protected: 
    ~MyEnums() {} // Prevent delete through pointer to this class 
public: 
    enum Direction 
    { 
     DIR_LEFT, 
     DIR_RIGHT 
    }; 
}; 

class X : public MyEnums 
{ 
    // ... 
}; 

class Y : public MyEnums 
{ 
    // ... 
}; 

用戶將看到X: :方向,X :: DIR_LEFT和Y ::方向, Y :: DIR_LEFT。當然,他們仍然能夠通過 y :: DIR_LEFT到期望X :: Direction的函數;以 爲例,使MyEnums成爲模板,其派生類爲 模板參數。

+3

它看起來像是繼承的濫用:/ – 2011-03-15 18:09:09

+0

@Matthieu M.對於「誤用」的定義是什麼?這是C++中使用繼承來共享 聲明的更少或更少的標準技術,例如,請參閱std :: iterator。 – 2011-03-15 19:20:51

+0

這不是因爲這個標準確實需要它。受保護的析構函數應該可以避免許多問題,但它仍然是「怪異的」,因爲我現在可以通過多態非常不相關的類。 'typedef'在這裏似乎是一個更好的選擇。 – 2011-03-16 07:33:25

0

如果原始聲明:

 
    class X 
    { 
    public: 
     enum Direction {DIR_LEFT, DIR_RIGHT}; 
    }; 

被嵌入在一個大的遺留代碼庫,那麼我們可能需要一個解決方案,它變化X的任何現有用途::方向。在這種情況下,比較難看:

 
    class Y 
    { 
    public: 
     typedef enum X::Direction Direction; 
     static const enum X::Direction DIR_LEFT = X:DIR_LEFT; 
     static const enum X::Direction DIR_RIGHT = X:DIR_RIGHT; 
    } 

作品...

絕對推薦新的代碼,但是!

+0

這與重新定義enum完全相同。 – 2015-01-07 12:17:35

+1

正確,但是如果原始定義發生更改(例如左側和右側給出不同的值),則使用類Y的代碼將繼續正常工作。 – 2015-01-08 16:06:43