所以,我對 C 有點陌生,我想知道什么是好的做法,甚至在編程時如何處理運行時錯誤,這是一個例子:
State s_toState(std::string state){
if (state == "MG")
return State::MG;
else if (state == "PR")
return State::PR;
else if (state == "SP")
return State::SP;
else if (state == "SC")
return State::SC;
else if (state == "RJ")
return State::RJ;
else if (state == "RN")
return State::RN;
else if (state == "RS")
return State::RS;
// ???
}
所以我有這個將 astring
轉換為 a 的函式State
。在不使用例外的情況下,我斷言給定狀態是現有狀態(MG、PR、SP 等)的理想方式是什么?
舉了一個例子,但我要求的是一般規則。據我所知,我可以使用例外、斷言或只是列印錯誤。我也假裝對此進行了單元測驗(也是單元測驗的新手,對此一無所知)。
uj5u.com熱心網友回復:
這看起來是使用例外的好機會。該cplusplus.com指導是合理的,但我發現,玩弄它是一個學習的更好的方法。
基本思想是這樣的:
- 函式
throw
是一個例外,終止該函式并將例外傳遞給呼叫該函式的任何人。 - 如果呼叫者在一個
try
塊中呼叫該函式,則后續catch
將被執行。 - 如果呼叫者沒有
try
/catch
系統,則呼叫者也將終止,并且該程序將重復函式呼叫堆疊,直到找到try
/catch
或被main()
終止。
uj5u.com熱心網友回復:
一般而言,處理此類錯誤(如任何錯誤)的方式取決于整個程式的需求 - 而您尚未指定。所以沒有一刀切的“一般規則”。
有選擇和權衡。
一種選擇是為您的State
列舉型別提供一個表示未確定或無效狀態的列舉器值,例如
enum class State {MG, PR, Undetermined};
然后,在您的函式中,回傳未確定的值,例如
State s_toState(const std::string &state)
{
State return_value = State::Undetermined;
if (state == "MG")
return_value = State::MG;
else if (state == "PR")
return_value = State::PR;
// etc
return return_value;
}
使用這種方法,函式總是回傳一個有效的 type 值State
。如果錯誤條件不嚴重(即如果提供了無效字串,程式可以繼續),則呼叫者可以決定是否需要檢查回傳值。可以報??告多種型別的錯誤條件(例如,通過多個列舉值代表不同的錯誤) 缺點是呼叫者可能忘記檢查回傳值并且行為不正確。
例如,另一種選擇是拋出例外;
State s_toState(const std::string &state)
{
if (state == "MG")
return State::MG;
else if (state == "PR")
return State::PR;
// etc
throw std::invalid_argument("Bad input string");
}
此選項需要明智地選擇要拋出的例外型別(例如,需要傳達有關錯誤狀態的哪些資訊)。如果呼叫者(或整個程式)在提供錯誤字串的情況下無法明智地繼續,則這種方法可能更可取,因為通過拋出例外,呼叫者被迫捕獲并采取任何恢復操作以避免被終止。因此,這種方法可能不適用于非嚴重錯誤——例如,如果提供了錯誤字串,執行可以繼續進行。
另一種選擇(C 17 及更高版本)是回傳std::optional<State>
. 這允許呼叫者檢查是否發生了錯誤(例如std::option::has_value()
return false
),或者如果在沒有檢查的情況下訪問該值,則會導致std::bad_optional_access
拋出型別例外(這可能適合呼叫者,或者可能沒有資訊)。
也可以使用assert()
- 如果指定條件不成立,則強制終止。通常,我更喜歡拋出例外而不是 using,assert()
但您可能更喜歡其他方式。
uj5u.com熱心網友回復:
答案取決于s_toState
“承諾”做什么。
如果state
無效是程式員的功能錯誤或其他內部邏輯錯誤。添加assert
并記錄狀態有效性作為前提條件(與!=nullptr
指標相同)。對于發布版本,添加一些默認行為,以便程式在可能的情況下不會崩潰。或者,如果您不撰寫關鍵軟體,則讓它崩潰,它至少會使除錯更容易。
如果它是用戶的可恢復故障和似是而非的場景(不是錯誤),則考慮回傳std::optional
或throw
。當拋出的例外總是被直接呼叫者捕獲時,我更喜歡前者,即從不向上傳播呼叫堆疊。我還發現它更清晰,因為它強制呼叫者明確處理它。
對于不可恢復的故障,即當直接呼叫者無法處理 時nullopt
,只需拋出并讓其他代碼處理。
我喜歡的命名convetion try_parse
回傳std::optional
,而parse
投擲。
可能值得一試例外和錯誤處理常見問題。
轉載請註明出處,本文鏈接:https://www.uj5u.com/gongcheng/362642.html