2012-11-07 93 views
1

問題是C++不允許在類中聲明命名空間(我在互聯網上搜索過,發現這個;如果它不是真的,請說出來)那麼,欺騙這個問題的最好方法是什麼?什麼是類內名稱空間的好替代方案?

上下文:我的類有一個枚舉。

class GameCharacter { 
public: 
    enum MovingState { 
     Running, 
     Walking, 
     Stopped 
    }; 
    ... 
}; 

OBS:這個例子是不是真實的,這是完全假設的。

C++定義枚舉名稱是類範圍內,然後使用這些狀態我必須直接從類名使用範圍操作符(GameCharacter::Running,例如;或using GameCharacter::Running)。

我認爲這是不好的,因爲屬於枚舉的名稱在類範圍內;我想爲RunningState枚舉創建一個範圍。 (以這種方式訪問​​它:GameCharacter::MovingState::Running) 然後,我的第一個想法是創建一個名稱空間,它將爲枚舉定義一個範圍。

class GameCharacter { 
public: 
    // does not compile 
    namespace MovingState { 
     enum State { 
      Running, 
      Walking, 
      Stopped 
     }; 
    }; 
    ... 
}; 

但是C++禁止它。此代碼不能編譯。 (main.cpp:3:5: error: expected unqualified-id before ‘namespace’

我試圖用這種方式做事情的原因是因爲有可能在同一範圍內創建第二個枚舉類型的名稱。這可能會導致名稱衝突。

class GameCharacter { 
public: 
    enum MovingState { 
     Running, 
     Walking, 
     Stopped 
    }; 
    enum DrivingState { 
     Accelerating, 
     Breaking, 
     Stopped  // Compilation error: conflicts with previous declaration ‘GameCharacter::MovingState GameCharacter::Stopped’ 
    }; 
    ... 
}; 

(我的想法是,在這種情況下,各國應稱爲GameCharacter::MovingState::StoppedGameCharacter::DrivingState::Stopped) 那麼,我該怎麼辦?

+2

'打破'意味着停止工作。你的意思是'制動'? –

+0

當然,對不起我的英語不好...... –

+0

很多母語爲英語的人說得對 - 實際上我最近看到幾個SO問題上的拼寫錯誤! –

回答

2

在C++ 1X(C++的新版本是去年標準化的),你可以使用strongly typed enumerations,裏面放的標識符在枚舉類的範圍本身(以及其他改進)。這些聲明與enum class

class GameCharacter { 
public: 
    enum class State { 
     Running, 
     Walking, 
     Stopped // Referred to as GameCharacter::MovingState::Stopped. 
    }; 
    ... 
}; 

在此期間,如果你堅持用C++編譯器03或要保留兼容性,只需使用class代替namespace並宣佈爲你所建議的構造私人你自己的答案。如果外部世界不需要看到它,你可以使整個class私人。

2

另一個我發現的是,而不是命名空間,使用類,但問題是這樣的項目不夠清晰,類可以實例化。 (雖然我可以欺騙這個問題與私有構造函數)

class GameCharacter { 
public: 
    class MovingState { 
     MovingState(); 
      /* or, in C++11: 
      * MovingState() = delete; 
      */ 
    public: 
     enum State { 
      Running, 
      Walking, 
      Stopped // Referred as GameCharacter::MovingState::Stopped. 
     }; 
    }; 
    class DrivingState { 
     DrivingState(); 
      /* or, in C++11: 
      * DrivingState() = delete; 
      */ 
    public: 
     enum State { 
      Accelerating, 
      Breaking, 
      Stopped // Referred as GameCharacter::DrivingState::Stopped. 
     }; 
    }; 
    ... 
}; 

這個工作,但我不是很清楚,如果這是最好的解決方案。我認爲應該有另一種方式。我想要意見。你怎麼看?

+0

這是一個很好的解決方案。它缺少什麼? –

+1

+1這是C++ 03中的常用解決方案,在強類型化C++ 11 –

0

如果你在你的類這麼多,你覺得你需要它的子分類爲命名空間,那麼你類有太多的東西

你應該把東西移出去。尤其是所有這些枚舉都不需要成爲一個類的成員。爲什麼不把它們放在類所在的同一個命名空間中?

+0

GRASP模式之前。如果僅在該類中使用,則將enum移開是沒有意義的。 編輯:另外,僅僅因爲一個類有太多的東西並不一定意味着它是壞的設計。課程可以承擔很多責任。 –

+0

@LeonardoRaele:不一定。聽起來就像是一件事情,只是因爲一些設計模式告訴你要把所有東西都包含進一個對象中。實際上,通過擁有所有這些類型,您的目標就是承擔很大的責任。它們屬於命名空間。你可以使它成爲只包含這些枚舉和類的命名空間,如果它讓你感覺更好...... –

+0

'另外,僅僅因爲一個類有太多東西並不一定意味着它設計的不好。 ,根據「太多」的定義,這意味着_precisely_。 –

3

嘗試使用新的C++ 11功能 - strongly typed enumerations。由於它,你不會有名稱衝突,你將會得到非常強大的類型系統。

1

這聽起來像是一個C++ 11的工作Strongly Typed Enumerations

class GameCharacter { 
public: 
    enum class MovingState { 
     Running, 
     Walking, 
     Stopped 
    }; 
    ... 
    void f(Movingstate m) { if (m == MovingState;:Running) ... } 
}; 
void f() { if (mm == GameCharacter::MovingState::Running) ... } 
1

如果使用C++ 11,可以使用

class GameCharacter { 
public: 
    enum class DrivingState { Accelerating, Breaking, Stopped }; 
    enum class WalkingState { Stopped, Running, Walking }; 

    DrivingState driving_state() { return ds_; } 
    void set_driving_state(DrivingState ds) { ds_ = ds; } 

    WalkingState walking_state() { return ws_; } 
    void set_walking_state(WalkingState ws) { ws_ = ws; } 

    DrivingState ds_; 
    WalkingState ws_; 
}; 

int main() { 
    GameCharacter g; 
    g.set_walking_state(GameCharacter::WalkingState::Stopped); 
    g.set_driving_state(GameCharacter::DrivingState::Stopped); 
    return 0; 
} 
1

您可以使用一個結構,而不是一個命名空間,如果你不能使用C++ 11 strongly typed enums

class GameCharacter { 
public: 
    struct MovingState { 
     enum Enum { 
      Running, 
      Walking, 
      Stopped 
     }; 
    } 
    ... 
}; 

這是我們採用了一段時間(直到C++ 11支持),因爲它可以在命名空間技巧不同的地方使用。

相關問題