C 第二十一天 在談異常

2021-06-23 04:41:00 字數 3887 閱讀 9085

/*

異常以類似於將實參傳遞給函式的方式丟擲和捕獲。異常可以是可傳給非引用的形參的任意型別的物件,這意味這必須能夠輔助該類型別的物件。

不存在陣列或函式型別的異常。如果丟擲乙個陣列,被丟擲的物件轉換為指向陣列首元素位址,類似丟擲乙個函式,函式被轉化為指向該函式的指標。

執行throw的時候,不會執行跟在truw後面的語句,而是將控制從throw轉移到匹配的catch,該catch可以是同一函式中區域性的catch,也可以在直接或間接呼叫發生異常的 函式的另乙個函式中。控制從乙個地方轉移到另乙個地方,它的含義:

1.沿著呼叫鏈的函式提早推出。

2.一般而言,在處理異常的時候,丟擲異常的塊中的區域性儲存不存在了。

因為在處理異常的時候會釋放區域性儲存,所以被丟擲的物件就不能在區域性儲存,而是用throw表示式初始化乙個稱為異常物件(exception object)的特殊物件,異常物件油編譯器管理,而且保證駐留在可能被啟用的任意catch都可以訪問的空間。這個物件由throw建立,並且初始化為被丟擲的表示式的副本。異常物件將傳給對應的catch,並且在完全處理了異常之後撤銷。

(注:異常物件通過複製被丟擲表示式的結果建立,該結果必須是可以賦值的型別。)

析構函式應該從不丟擲異常。

建構函式與與異常:如果在建構函式物件的時候發生異常,則該物件可能只是初始化一部分,一些成員已經初始化,一些還沒油,即使物件的部分被構造了,也要保證將會適當地撤銷已構造的成員。類似的,在初始化陣列或其他容器的時候,也可能發生異常,也要保證會適當的撤銷已初始化的元素。

未捕獲的異常程式,將呼叫terminate函式,強行終止程式。

捕獲所有的異常格式:

try{}catch(...){}

捕獲所有異常的catch自居可以與任意型別的異常匹配。

catch(...)經常與重新丟擲表示式結合使用,catch完成可做的所有區域性工作,然後重新丟擲異常:

try{}catch(...)

建構函式要處理來自建構函式初始化式的異常,唯一的方法是將建構函式編寫為函式測試塊,函式測試塊的格式:

模板、類名::類名(建構函式形參列表) try:初始化列表catch(要捕獲的異常型別)

關鍵字try出現在成員初始化列表之前,並且測試塊的符合語句包圍了建構函式的函式體。catch子句可以處理從成員初始化列表丟擲的異常,也可以處理從建構函式體中丟擲的異常。

exception型別所定義的唯一操作是乙個名為what的虛成員,該函式返回const *char物件,它一般返回用來在丟擲位置構造異常物件的資訊。因為what是虛函式,如果捕獲了基類型別引用,對what函式的呼叫將執行適合異常物件的動態型別的版本。

可能存在異常的程式以及分配資源的程式應該使用類來管理那些資源,使用類管理分配和**可以保證如果發生異常就釋放資源。

auto_ptr類:auto_ptr類是接受乙個型別形參的模板,它為動態分配的物件提供異常安全,auto類在標頭檔案memory中定義。

auto_ptr類的成員:

auto_ptrap; //建立名為ap的未繫結的auto_ptr物件

auto_ptrap(p); //建立名為ap的auto_ptr物件,ap擁有指標p指向的物件,該建構函式為explicit

auto_ptrap1(ap2); //建立名為ap1的auto_ptr物件,ap1儲存原來儲存在ap2中的指標,將所有權轉給ap1,ap2成為未繫結的autp_ptr物件。

ap1=ap2; //將所有權從ap2轉給ap1,刪除ap1指向的物件並且使ap1指向ap指向的物件,使ap2成為未繫結的

~ap //析構函式,刪除ap繫結物件的引用。

*ap //返回對ap所繫結的物件的引用。

ap-> //返回ap儲存的指標。

ap.reset(p); //如果p與ap的值不同,則刪除ap指向的物件,並且將ap繫結到p

ap.release(); //返回ap所儲存的指標並且使ap成為未繫結的。

ap.get(); //返回ap儲存的指標。

(注意:auto_ptr只能用於管理從new返回的乙個物件,它不能管理動態分配的陣列,當autp_ptr被複製或賦值的時候,有不尋常的行為,因此,不能舊愛那個auto_ptr儲存在標準庫容器型別中。autp_ptr物件只能報ucnyige指向物件的指標,並且不能用於指定動態分配的陣列,使用autp_ptr物件指向動態分配的陣列,會導致未定義的執行時行為。當autp_ptr物件超出作用域或者另外撤銷的時候,就自動**autp_ptr所指向的動態分配物件。)

因為auto_ptr的賦值和複製操作是破壞性的,所以不能將auto_ptr物件儲存在標準容器中。標準的容器類要求在賦值或賦值之後兩個物件相等,auto_ptr不滿足這一要求,如果ap2賦值給ap1,則在賦之後ap1!=ap2,複製也類似。

auto_ptr的缺陷:

auto_ptr類模板為處理動態分配的記憶體提供了安全行和遍歷性的尺度。要正確使用,必須強加下列限制:

1.不要使用auto_ptr物件儲存指向靜態分配物件的指標,否則,當auto_ptr物件本身被撤銷的時候,它將試圖刪除指向非動態分配物件的指標,導致未定義行為。

2.永遠不要使用兩個auto_ptr物件指向同乙個物件,導致這個錯誤的一種明顯方式是,使用同一指標來初始化或者rest兩個不同的auto_ptr物件,另一種是使用auto_ptr物件的get函式的將誒過來初始化或者reset另乙個auto_ptr物件。

3.不要使用auto_ptr物件儲存指向動態分配陣列的指標,當auto_ptr物件被刪除的時候,它只釋放乙個物件----它使用普通的delete操作符,而不是陣列的delete 操作符。

4.不要將auto_ptr物件儲存在容器中,容器要求所儲存的型別定義賦值和複製操作符,使它們表現得類似於內建型別的操作符:在賦值或複製之後,兩個物件必須具有相同值,auto_ptr類不滿足這個要求。

異常說明:

1.異常說明跟在函式形參表之後,乙個異常說明在關鍵字throw之後跟著乙個由元括號擴住的異常型別列表,例如:

void recoup(int) throw (runtime_error);

該recoup丟擲的異常將會是runtime_error物件,或者runtime_error派生的型別的異常。異常型別列表也可以為空:

void no_problem() throw();

空的說明列表指出函式不丟擲任何異常。

如果乙個函式宣告沒有指定異常說明,則該函式可以丟擲任意型別的異常。

2.違反異常說明:

如果函式丟擲了沒有在其異常說明中列出的異常,就呼叫標準庫函式unexpected。預設情況下,unexpected函式呼叫terminate函式,terminate一般會終止程式。

3.異常說明與虛函式:

基類中虛函式的異常說明,可以與派生類中對應虛函式的異常說明不同,但是派生類虛函式的異常說明必須與對應基類虛函式的異常說明同樣嚴格,或者更嚴格。這個限制保證,當使用基類型別的指標呼叫派生類虛函式的時候,派生類的異常說明不會增加新的可丟擲異常。

4.函式指標說明:

void (*fntname) (形參) throw (異常形參)

如果不提供明異常說明,則該指標就可以指向能夠丟擲任意型別異常的具有匹配型別的函式

*/ #include#include//#include//包含異常的標頭檔案

#include//

using namespace std;

//異常說明和虛函式:

class base;

class derived:public base;

int main()

if(ap1.get())

cout<<"ap1是有繫結指標的"

ap1.reset(new string("today"));

cout<<*ap1

}

第二十一天

好久沒有寫點東西了。或許是為了忙個經濟師中級的考試,列印了很多的資料,每章一節一節地在消化,咀嚼著生硬的專業術語,那滋味,只有體會過了才知道。乙個晚上看下來,做夢也是這些內容,有點累,但是,為了目標,只有克服,努力前進。單位的專案要啟動了,事情特別多,給我們準備的時間就乙個禮拜,一開始拿到這個內容需...

第二十一天總結

今天學習了c 中的函式,感覺好難看懂,跟數學含糊一樣難,函式是一組一起執行乙個任務的語句。每個 c 程式都至少有乙個函式,即主函式 main 所有簡單的程式都可以定義其他額外 的函式。您可以把 劃分到不同的函式中。如何劃分 到不同的函式中是由您來決定的,但在邏輯上,劃分通常是根據每個函式執行乙個特定...

實習日記 第二十一天

本來今天是很有成就感的日子,以為自己的圖顯示已經完成了。但是拿真實的資料一測試發現問題很大啊。剛開始的時候我以為是查詢的時候遞迴深度太大了所導致的。所以我就測試了一下,發現遞迴確實會導致資料庫出問題。而且遞迴深度越深,時間越久。像我的資料,總共只有100條,關係層次最深是5,但是我講遞迴深度設為7 ...