- 以前我們在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 (台味很重)
回覆刪除