3 回答

TA貢獻1890條經(jīng)驗 獲得超9個贊
盡管“在特殊情況下拋出異?!笔且粋€很好的答案,但您實際上可以定義這些情況是什么:當(dāng)滿足先決條件而不能滿足后置條件時。這使您可以編寫更嚴格,更嚴格和更有用的后置條件,而無需犧牲錯誤處理;否則,您必須毫無例外地更改后置條件,以允許所有可能的錯誤狀態(tài)。
調(diào)用函數(shù)之前,前提條件必須為true 。
后置條件是功能保證什么之后就返回。
異常安全性說明異常如何影響函數(shù)或數(shù)據(jù)結(jié)構(gòu)的內(nèi)部一致性,并經(jīng)常處理從外部傳入的行為(例如函子,模板參數(shù)的ctor等)。
建設(shè)者
關(guān)于可以用C ++編寫的每個類的每個構(gòu)造函數(shù),您幾乎沒有什么要說的,但是有幾件事。其中最主要的是構(gòu)造的對象(即構(gòu)造函數(shù)返回成功的對象)將被破壞。 您無法修改此后置條件,因為該語言假定該條件是正確的,并將自動調(diào)用析構(gòu)函數(shù)。 (從技術(shù)上講,您可以接受未定義行為的可能性,該語言對此不作任何保證,但這在其他地方可能會更好地涵蓋。)
當(dāng)構(gòu)造函數(shù)無法成功時引發(fā)異常的唯一替代方法是修改類的基本定義(“類不變”)以允許有效的“ null”或僵尸狀態(tài),從而允許構(gòu)造函數(shù)通過構(gòu)造僵尸來“成功” 。
僵尸的例子
這種僵尸修改的示例是std :: ifstream,您必須始終檢查其狀態(tài)才能使用它。例如,因為std :: string不存在,所以始終保證您可以在構(gòu)造后立即使用它。想象一下,如果您必須編寫如本例所示的代碼,并且如果忘記了檢查僵尸狀態(tài),那么您要么默默地得到不正確的結(jié)果,要么會破壞程序的其他部分:
string s = "abc";
if (s.memory_allocation_succeeded()) {
do_something_with(s); // etc.
}
甚至命名該方法也是一個很好的例子,說明如何必須為情況字符串修改類的不變式和接口,而無法預(yù)測或處理自身。
驗證輸入示例
我們來看一個常見的例子:驗證用戶輸入。僅僅因為我們要允許失敗的輸入并不意味著解析函數(shù)需要在其后置條件中包括該內(nèi)容。但是,這確實意味著我們的處理程序需要檢查解析器是否失敗。
// boost::lexical_cast<int>() is the parsing function here
void show_square() {
using namespace std;
assert(cin); // precondition for show_square()
cout << "Enter a number: ";
string line;
if (!getline(cin, line)) { // EOF on cin
// error handling omitted, that EOF will not be reached is considered
// part of the precondition for this function for the sake of example
//
// note: the below Python version throws an EOFError from raw_input
// in this case, and handling this situation is the only difference
// between the two
}
int n;
try {
n = boost::lexical_cast<int>(line);
// lexical_cast returns an int
// if line == "abc", it obviously cannot meet that postcondition
}
catch (boost::bad_lexical_cast&) {
cout << "I can't do that, Dave.\n";
return;
}
cout << n * n << '\n';
}
不幸的是,這顯示了兩個示例,這些示例說明C ++的作用域如何要求您破壞RAII / SBRM。Python中沒有這個問題的示例,顯示了我希望C ++擁有的一些東西– try-else:
# int() is the parsing "function" here
def show_square():
line = raw_input("Enter a number: ") # same precondition as above
# however, here raw_input will throw an exception instead of us
# using assert
try:
n = int(line)
except ValueError:
print "I can't do that, Dave."
else:
print n * n
前提條件
前提條件不必嚴格檢查-違反前提條件總是表示邏輯失敗,這是調(diào)用方的責(zé)任-但如果您檢查了前提條件,則拋出異常是適當(dāng)?shù)?。(在某些情況下,返回垃圾或使程序崩潰更合適;盡管這些動作在其他情況下可能是非常錯誤的。如何最好地處理未定義的行為是另一個主題。)
特別是,請對比一下stdlib異常層次結(jié)構(gòu)的std :: logic_error和std :: runtime_error分支。前者通常用于違反先決條件,而后者更適合于違反先決條件。

TA貢獻1868條經(jīng)驗 獲得超4個贊
昂貴的
內(nèi)核調(diào)用(或其他系統(tǒng)API調(diào)用)來管理內(nèi)核(系統(tǒng))信號接口難以分析語句中的
許多問題都goto
適用于異常。它們經(jīng)常跳過多個例程和源文件中潛在的大量代碼。通過閱讀中間源代碼,這并不總是顯而易見的。(使用Java。)中間代碼并不總能預(yù)料
到被跳過的代碼在編寫或未編寫時都會考慮到異常退出的可能性。如果最初是這樣寫的,那么可能不會考慮到這一點。想一想:內(nèi)存泄漏,文件描述符泄漏,套接字泄漏,誰知道?維護的復(fù)雜性
維護在處理異常周圍跳躍的代碼更加困難。
- 3 回答
- 0 關(guān)注
- 377 瀏覽
添加回答
舉報