1. 程式人生 > >C/C++基礎----用於大型程式的工具(異常處理,名稱空間,多重繼承)

C/C++基礎----用於大型程式的工具(異常處理,名稱空間,多重繼承)

獨立開發的子系統間協同處理錯誤的能力
使用各種庫(可能包含獨立開發的庫進行協同開發的能力)
對比複雜的應用概念建模的能力

異常處理

異常將問題的檢測和解決過程分離開
當執行一個throw之後,程式控制權轉移到了與之匹配的catch
控制權的轉移有兩個重要的含義
1沿著呼叫鏈的函式可能會提早退出
2一旦程式開始執行異常處理程式碼,則沿著呼叫鏈建立的物件將被銷燬
  • 棧展開
棧展開,層層往外查詢。如果找到了匹配的catch,則進入執行程式碼。執行完catch之後,找到與try塊關聯的最後一個catch子句之後的點,並從這裡繼續執行。
如果沒找到,則呼叫terminate退出程式

棧展開過程中,物件被自動銷燬,可能當前物件只構造了一部分,我們也要確保這部分被正確的銷燬。

解構函式總是會被執行,可以使用類來控制資源的分配
解構函式需要執行某個可能丟擲異常的操作,則該操作應該被放置在一個try語句塊中,並且在解構函式中得到處理。
  • 異常丟擲,catch
當丟擲一條表示式時,該表示式的靜態編譯時型別決定了異常物件的型別
catch中宣告的型別必須是完全型別,可以是左值引用,但不能是右值引用。
多個catch語句之間存在繼承關係,繼承鏈底端的類放在前面。
catch語句允許的型別轉換
1非常量轉常量
2派生類轉基類
3陣列或函式轉指標

重新丟擲
空throw只能出現在catch內或catch直接或間接呼叫的函式內。
catch(…)捕獲所有異常

如想處理建構函式初始值丟擲的異常
template<typename T>
Blob<T>::Blob(std::initializer_list<T> il) try : data(std::make_shared<std::vector<T>>(il) {}
既能處理建構函式體丟擲的異常也能處理成員初始化列表丟擲的異常。
  • noexcept說明符
經常用在1確認函式不會丟擲異常2根本不知道該如何處理異常
noexcept運算子
noexcept(fun(i))  //表示給定的表示式是否會丟擲異常
  • 異常類層次

exception僅僅定義了拷貝構造、拷貝賦值、虛解構函式、what虛擬函式
exception、bad_cast、bad_alloc定義了預設建構函式
logic_error和runtime_error沒有預設構造,接收一個string或C風格字串

(1)語言本身所支援的異常

此類異常用以支撐某些語言特性。主要包括:
bad_alloc:new操作失敗會丟擲。
bad_cast:執行期間加在一個引用上面的動態性型別轉換操作失敗時丟擲。
bad_typeid:執行RTTI時,交給typeid的引數為零或空指標時丟擲
bad_exception:非預期的異常

(2)C++標準程式庫發出的異常

logic_error。邏輯錯誤是由於程式內部邏輯而導致的錯誤。邏輯錯誤是可以避免的,且在程式開始執行之前,能夠被檢測到。
domain_error:專業領域內的範疇 invalid_argument:無效引數,比如講bitset以char而非0或1進行初始化 length_error:可能超越了最大極限,比如對著某個字串附加太多字元。 out_of_range:引數不再預期範圍內。例如在諸如array的容器或字串string中採用一個錯誤索引。

runtime_error,用來指出“不在程式範圍內,且不容易迴避”的事件。此類錯誤只在程式執行時才是可檢測的。
range_error:內部計算時發生區間錯誤
overflow_error:算數運算時發生上溢
underflow_error:算數運算時發生下溢

名稱空間

為防止名字衝突提供了更加可控的機制
名稱空間可以不連續
#include通常不在名稱空間內,標頭檔案中所有名字定義成該名稱空間的成員
名稱空間之外定義必須使用含有字首的名字
模板特例化必須定義在原模板所屬的名稱空間內
內聯名稱空間中的名字可以直接被外層名稱空間直接使用,關鍵字inline必須出現在名稱空間第一次定義的地方。
  • 匿名的名稱空間
未命名的名稱空間中定義的變數擁有靜態週期,可以不連續,但是不能跨越多個檔案。
所定義名字的作用域與該名稱空間所在作用域相同,不會橫跨多個不同檔案。
  • using宣告和using指示
using宣告
有效範圍從宣告的地方到using宣告所在作用域結束。外層作用域的同名實體被隱藏。
可以出現在全域性作用域、區域性作用域、名稱空間作用域以及類作用域中
簡單地令名字在區域性作用域內有效
using指示
可以出現在全域性作用域、區域性作用域、名稱空間作用域。
將名稱空間成員提升到包含名稱空間本身和using指示的最近作用域的能力。
標頭檔案通常只負責定義介面部分名字,而不定義實現部分名字。因此標頭檔案做多隻能在它的函式或者名稱空間內使用using指示或宣告。
名稱空間中名字隱藏的規則有一個重要的例外:
給函式傳遞一個類型別的物件時,除了在常規的作用域查詢外,還會查詢實參類所屬的名稱空間,對應傳遞的引用或指標的呼叫同樣有效。
1先在當前作用域尋找
2在外層作用域查詢
3實參類所屬的名稱空間
影響候選函式的搜尋
using宣告如果跟已有函式衝突會引發錯誤,using指示則不會,只要呼叫時指明作用域。

一個未宣告的類或函式如果第一次出現在友元宣告中,則認為他是最近的外層名稱空間的成員。

多重繼承

構造順序,首先構造虛基類,然後按派生列表中的順序依次構造直接基類。
物件、指標和引用的靜態型別決定了能夠使用哪些成員。