- 以前我們在Effective C++ 有看過, 用enum取代 #define 跟 const 可以避免錯誤。
- 許多遊戲engine 或包含大量UI的AP會使用enum管理音效, 貼圖等recourse。
- enum還有個有趣的技巧叫 enum hack, 方便我們針對enum眾多recourse 的物件寫基本的測試程式。
enum vs. const
假設今天有一個 GamePlayer如下class GamePlayer{
public:
    const static int iMage = 0;
    const static int iPaladin = 1;
    GamePlayer(int classType);
    void Attack();
private:
    GamePlayer();
    GamePlayer(const GamePlayer&);
    GamePlayer& operator = (const GamePlayer&);
    int Talent;    
}; 
GamePlayer::GamePlayer(int ClassTtpe){
    Talent = ClassTtpe; 
}; 
void GamePlayer::Attack(){
    switch(Talent){
        case 0:
            printf("fire ball\n");
            break;
        case 1:
            printf("Hammer of Justice\n");
            break; 
        default:
            //exception
            break; 
}
const 可能在添加新職業時犯以下粗心錯誤const static int iMage = 1;
const static int iMonk= 1; // the same !
就容易跑出些鬼打牆不容易debug的問題。
enum type check
另外一種危險的錯誤發生在使用GamePlayer的人如果今天宣告了 GamePlayer(1000);
或某人寫了一隻測試程式想驗證是否每個職業都正常運作與否
for( i = 0 ; i <  1000 ; i++){
        GamePlayer TESTER(i);
        TESTER.Attack(); 
} 
會導致 GamePlayer Attack的時候進入switch default 發生不可預期的exception煩惱這問題的時候我們可以改寫成這樣
enum SpecialTypeClass{
        Mage = 0,
        Paladin ,
        War    ,
        Shaman ,
        Thief
}; 
宣告GamePlayer的使用者就會被Compiler提醒必須要寫成 GamePlayer Abow(GamePlayer::SpecialTypeClass::Shaman) ;
如此明確的定義也另外增加了程式的閱讀性
這樣寫的另一個好處是 switch case會更好看, 不用擔心數字的一一mapping
switch(Talent){
        case SpecialTypeClass::Mage:
            printf("fire ball\n");
            break;
        case SpecialTypeClass::Shaman:
            printf("Earth shock\n");
            break;
        case SpecialTypeClass::Thief:
            printf("split knife\n");
            break;
        case SpecialTypeClass::Paladin:
            printf("Hammer of Justice\n");
            break;
        default:
            //exception
            break;
}
enum hack
最後回到測試程式的小技巧(說穿了不值錢.. = =)
enum SpecialTypeClass{
        Mage = 0,
        Paladin ,
        War    ,
        Shaman ,
        Thief,
        TalentNum
}; 
加一個 Bound…  for( i = 0 ; i <  GamePlayer::TalentNum ; i++){
        GamePlayer TESTER((GamePlayer::SpecialTypeClass)i);
        TESTER.Attack(); 
} 
have fun
 
 
其實... 盜賊是Rogue XDDDD
回覆刪除XDD (台味很重)
回覆刪除