assert,可以讓問題及早被發現,也可以透過assert與client溝通。廢話不多說,讓我先舉幾個
assert常見的用法。參數檢查
例如有個設定月份的method,所以月份的範圍理應是1到12。所以assert可以用來幫忙檢查傳進來的參數是否合理,如List 1。List 1 - Checks parameter
void setMonth(unsigned char month)
{
assert(month > 0);
assert(month <= 12);
if (month > 0 && month <= 12) {
m_month = month;
}
}
這裡有幾個重點要提醒,有人會想到,既然月份的範圍是1到12,那為何不寫成assert(month > 0 && month <= 12); 一行就好?我是不建議這樣寫,原因是當assertion fail的時候debugger通常會停在該行,但像這樣混在一起寫,你就比較難分出到底是那一條件不成立,當然還是有辦法,只不過要多一些步驟,所以我建議還是分開寫,比較清楚。另外,還有人會認為既然有加
assert了,為何還要加if (month > 0 && month <= 12)? 這裡有個觀念很重要,通常assert是debug版本才會有作用(當然這要看語言與環境,不過通常都是這樣),所以List 1中 line 3 與 line 4 在release版根本是空白的,如果沒有if的保護,程式還是有可能落入一個不預期的狀態。Switch Case
假設有個function在處理command,然而"目前"只有三個command定義如List 2。List 2 - Command ID
typedef enum _CommandID_ {
command_attack = 0,
command_heal,
command_run
} CommandID;
如果Command ID是由我定義,而處理command的function(如List 3)是你寫的,你可以在switch case的地方加個assert去做個例外的警告。所以當我多加一個command ID時,而你因某種原因忘記多加一個case去處理他,這時候assert就可以發生作用,讓我們知道這裡有一個例外發生了,不用多花時間去trace。List 3 - Switch case
void processCommand()
{
CommandID cmd;
while (_commandQueue.count() > 0) {
cmd = _commandQueue[0];
switch (cmd) {
case command_attack:
// attack
break;
case command_heal:
// heal
break;
case command_run:
// run
break;
default:
assert(!"unknown command ID");
break;
}
_commandQueue.erase(_commandQueue.begin());
}
}
時間的關係,這篇先到此,有機會再多舉幾個例子。
沒有留言:
張貼留言