首先,講講const
我是分三個方面進行總結的,1,const常量;2,const指標,3, const在函數申明中的應用
1, const常量
其定義形式為
const type_name val_name;
這裡要注意初始化的問題,定義普通的常量時是需要進行初始化的,如果類內的資料成員,不能直接在類內進行初始化,需要在類的建構函式的初始化列表中進行初始化。
還需要說明的一點就是它跟宏定義的區別,const常量有資料類型,而宏常量是沒有資料類型,編譯器對於前者可以進行型別安全檢查,而對後者只是進行簡單的字元替換。
2, const修飾指標
如果const位於星號的左側,則const就是用來修飾指標所指向的內容,即指標指向的是常量,如果const位於星號的右側,const就是修飾指標本身,指標的指向就是不可以改變的,因此在定義的同時要對它進行初始化
3, const在函數申明中的應用
在一個函數申明中,const可以修飾函數的傳回值,或函數的參數,對於成員函數來說,還可以修飾整個函數,這樣的函數就是常成員函數,
申明常成員函數的形式為type_name function_name()const;
還需要注意的一點就是在類外定義常成員函數的時候需要帶上後面那個const限定符。(主要是與靜態成員函數進行區別一下)
修飾函數的形參時可以防止意外的修改,增強程式的健壯性,長成員函數的就是不允許對類內的其他資料成員進行修改,也是增強程式的健壯性。
函數重載
函數的重載依據有這麼幾個
參數的類型,參數的個數,以及參數的順序,還有一點就是加了const限定符的函數
匹配時,首先嚴格匹配,然後進行相容類型轉換如char到int之間,最後可以自訂類型轉換,
函數預設參數
函數預設參數是從右端開始設定,匹配時是從左端開始匹配
接下來講講類吧
關於類的內容就比較多了,
類跟結構體的區別,類中成員預設為private, 而結構體的成員預設為public,類內可以定義函數而結構體中就不可以定義,用我們老師的話來講,結構體是單純堆積的資料空間構造的類型,而類不但描述資料空間還描述其操作的自訂類型。
建構函式
其申明形式為
class_name();
這裡需要講講的就是在繼承時執行個體化一個衍生類別的對象時,建構函式的執行順序,首先要啟用基類的建構函式,完成對基類中成員的記憶體空間分配,然後執行建構函式的函數體,這點老師給出的一個比較好理解的解釋就是“分配空間等於是蓋房子,建構函式的函數體是裝修”,然後就是完成對衍生類別的成員的空間的分配,接著執行衍生類別的建構函式的函數體。如果沒有自訂建構函式時,系統會自動產生預設無參建構函式,如果使用者自己定義了建構函式,則系統不再踢狗預設建構函式。這裡說一下關於建構函式的初始化列表的問題,當類中含有常量成員和引用型成員時需要用到初始化列表,還有一種情況就是在繼承時,如果基類中沒有無參建構函式並且有參建構函式沒有預設參數時,那麼衍生類別的建構函式即必須要在初始化列表中給出基類的初始化。
解構函式
其申明形式為
~class_name();
解構函式的作用就是將申請的記憶體空間釋放出來,當沒有自訂時,系統會提供預設的解構函式。不過需要注意的就是,解構函式不能釋放由new申請的堆空間,這部分空間就需要程式員自己釋放,如果不釋放的話,可能會造成記憶體泄露。另外還有一點就是在繼承的時候,基類的解構函式應該盡量申明為虛函數,理由就是如果一個基類指標指向衍生類別的話,刪除它的時候時就會調用基類的解構函式,而不會調用衍生類別的解構函式,從而造成記憶體泄露。
拷貝建構函式
先講講拷貝構造的概念,拷貝構造就是在建立對象時,以其他對象為依據來建立對象,我們稱這種建立活動為拷貝構造,還是一樣,如果沒有自訂拷貝建構函式時,系統將提供預設拷貝建構函式,預設拷貝狗仔函數是一種淺拷貝,當類中含有指標成員的時候,預設拷貝建構函式也只是簡單的將指標的值複製過來,這樣在析構時,就會出現將同一片記憶體地區釋放兩次,造成程式出現異常。因此就需要自訂拷貝建構函式,這樣的拷貝也稱為深拷貝,
拷貝建構函式的申明形式為
class_name(conat class_name& parameter_name);
當然這裡形參也可以是class_name * parameter_name;
轉換建構函式
轉換建構函式是用於類型轉換的,這麼說吧,有一個類A,和一個B類型的資料,現在要將B類型的資料轉換為A類型,那麼就要在類A中這樣定義一個轉換建構函式 A(const B& parameter_name);
說到這裡就想說說operator自訂隱式轉換
其申明形式是這樣的
operator type_name ();所不同的是這個是將該類類型轉換為type_name類型的。跟上面那個正好相反,需要注意的一點就是這個是有傳回值的,傳回值類型就是所要轉換的類型
賦值操作符
還是,如果沒有自訂賦值操作符,系統會提供預設賦值操作符,但是如果需要在對象之間做深拷貝的話,是需要自訂賦值操作符的,
賦值操作符的申明形式為
class_name& operator=(class_name& parameter_name);
這裡申明的是一個返回class_name類型的引用函數,是為了做賦值時的左值
需要注意的一點就是,定義函數體是需要做自賦值檢查,理由是,定義賦值操作符是,被賦值的對象已經存在,需要先把被賦值的對象的空間釋放,重新進行資源分派,如果是自己賦值給自己的話,那麼,就會把這個要賦值的對象毀了,不能完成賦值操作,
靜態成員
靜態成員是在main函數之前構造,其生命週期相當於全域變數,需要注意的有兩點,一個是待用資料成員的初始化,需要在類外進行初始化的,
其形式為 type_name class_name::static_data_name=value;
第二個就是靜態成員函數的問題,當其在類外進行定義是,是不需要再加上static關鍵字的,還有就是其內部沒有預設的this指標,故靜態成員函數是不可以訪問類中的非待用資料成員的。其調用形式為class_name::function_name();類似於全域函數,只不過在前面加上類的範圍
現在來講講繼承
首先由三種繼承方式,分別為public,private, protected三種繼承方式,三種繼承方式下衍生類別對基類中成員的繼承的許可權變化為
public繼承下
衍生類別可以直接存取基類的public成員,以及protected成員,但對外的時候,protected是不允許外界直接存取的,,需要說明的一定就是,基類類型的指標在public繼承方式下是可以指向衍生類別的,這時候凡是衍生類別對象出現地方都可以用基類來代替,但在其他兩種方式下就不可以了。
protected繼承
基類的public,和protected成員在衍生類別的類外都是被看做protected成員
private繼承
基類的public和protected都在衍生類別的類外看做是private成員
這三種繼承方式下基類的private成員都在衍生類別的類外看做private成員
多重繼承,就是一個類同時從多個基類中派生
假定有一個基類Base,類A繼承類Base,類B也繼承類Base,類C同時繼承類A和類B這樣在類C中就有兩份類Base的資料,就會導致訪問時不知道究竟訪問的是哪個,所以引進了虛擬繼承的概念,讓類A和類B分別虛擬繼承基類Base,這樣類C在同時繼承類A和類B時就不會產生兩份基類Base的資料了,由此引出虛擬繼承的概念。
多態
首先如果基類和衍生類別中都含有相同的成員函數,在public繼承的前提下,如果,用一個基類類型的指標指向衍生類別的話,調用該成員函數時,調用的是基類的那個成員函數,而我們希望它可以根據傳來的參數的類型調用相應類型的函數,實現一種多態的效果。這樣就要引入虛函數的概念,
其定義形式為virtual type_bame function_name(parameter);
實現多態的辦法就是把基類中該函數申明為虛函數,衍生類別中相應函數可以不需要申明為虛函數,具體是程式運行時維持一張虛函數表,到底怎麼樣我也不是很清楚,總之就是這樣實現了我們想要的功能,這裡補充說明一點就是C++語言的多態性分為編譯時間的多態性和運行時的多態性,編譯時間的多態性是通過函數重載和模板實現,而運行時的多態性是通過虛函數實現的。
抽象類別
關於抽象類別的定義就是,在該類中至少有一個純虛函數的類,需要注意的是抽象類別是不可以被直接執行個體化的,但可以間接執行個體化,辦法就是,執行個體化其一個非抽象類別的衍生類別,來隱式調用抽象類別的建構函式,所以這也說明抽象類別的建構函式是有必要的。
補充說明一點就是純虛函數的概念
其形式是
virtual type_name function_name()=0;
需要在衍生類別中重新定義該函數,如果衍生類別不對它進行定義的話,那麼衍生類別也繼續是抽象類別。
最後講講關於異常處理
主要就是講講throes,try, catch
只有在try程式的語句段中使用了throw語句,catch程式段才有意義, 而無論有try程式段直接或間接調用的哪一級函數執行了throw語句,都會被catch捕獲,並且一旦拋出了異常(執行throw語句),下一條執行的語句就是捕獲該異常的的catch語句,所有中介層次的函數,及其定義的變數都將出棧
catch語句塊的5方面工作,
1,給出正確工作的提示資訊,並且在程式退出之前儲存可能會被破壞的資料
2,根據throw語句傳來的異常資訊進行相應的處理
3.對於處理不了的異常,儘可能將它轉變為能夠被另一個例外處理常式處理的形式,並拋出該異常
4,重新嘗試執行最初的語句
5,如果需要返回一個有效值給主調函數。
1,catch常跟在try後面,數量不限
2,catch包含的資料類型與函數的資料類型作用相同
3,如果拋出的異常在後面找不到與之匹配的catch,則系統預設調用abort()函數,終止程式
4,catch執行完後,程式將執行跟在最後一個catch後面的代碼
需要注意的就是catch的類型匹配十分嚴格,如拋出char類型的,用int型的不能捕捉到。