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