//轉自網友博客、
1、 派生類對象與普通類對象的相同之處在于,可以直接訪問該類的所有對象(包括this指針指向的對象和其他對象)的protected和private成員(包括其基類成員)。不同之處在于派生類對象只能訪問其對應基類對象的protected成員(有隱式this指針傳遞),而不能訪問其基類的其他對象的protect成員,而普通類對象則也可以直接訪問該類所有對象的成員。
2、 在C++中,基類指針只能訪問在該基類中被聲明(或繼承)的數據成員和成員函數(包括虛擬成員函數),而與它可能指向的實際對象無關,所以如果需要用基類指針來訪問一個沒有在該基類中聲明但是又在其派生類中定義了的成員,則需要執行dynamic_cast來完成從基類指針到派生類指針的安全向下轉換。把一個成員聲明為虛擬的,只推延了“在程序執行期間根據指針指向的實際類類型,對于要調用實例的解析過程”
3、 關于基類,派生類的相關補充:
1、 派生表中指定的類必須先被定義好,方可被指定為基類。
2、 派生類的前向聲明不能包括其派生表,而只需要類名即可。
3、 缺省的繼承是private。
4、 繼承而來的派生類的虛擬函數一般加上virtual較好,也可以省略。但基類中一定要聲明為virtual。
5、 對于基類的靜態成員,所有派生類對象都引用基類創建的這個相同,單一,共享的靜態成員,而不是創建該派生類的另一個獨立的靜態成員。
6、 友員關系不會被繼承,派生類沒有成為“向它的基類授權友誼的類”的友員。
4、 繼承機制下,派生類對象的構造函數(析構函數)調用順序為:
1、 基類(子對象的)構造函數,若有多個基類,則以類派生表中出現的順序為序。
2、 成員類對象的構造函數,若有多個成員類對象,則以它們在類定義中被聲明的順序為序。
3、派生類自己的構造函數。
4、派生類對象的析構函數的調用順序與它的構造函數相反。繼承機制下,析構函數的行為如下:派生類的析構函數先被調用,再靜態調用基類的析構函數(從直接基類開始)。注意一般基類的析構函數不應該是protected,因為虛擬函數承接了“調用者所屬類類型的訪問級別”。作為一般規則,我們建議將類層次結構的根基類(聲明了一個或多個虛擬函數)的析構函數聲明為虛擬的。
5、 關于繼承機制下基類構造函數(析構函數)相關的幾點說明:
1、 作為一般規則,派生類構造函數應不能直接向一個基類的數據成員賦值,而是要把值傳遞給適當的基類構造函數來達到初始化賦值的目的。(一般是通過成員初始化表的方式)
2、 若基類不用于創建對象,則最好將其構造函數放在protect區,只允許其派生類對象調用;若基類只允許創建某一個特定的派生類類型的對象,則應該將基類的構造函數放在private區,并將此特定的派生類聲明為該基類的友元來達到目的。
3、 派生類并不繼承基類的構造函數,每個派生類都必須提供自己的構造函數集,派生類的構造函數只能合法的調用其直接基類的構造函數。(注意這里虛擬繼承提供了一個特例:虛擬基類的初始化變成了最終派生類的責任)。
6、 關于虛擬函數的相關
1、 必須使用指針或者引用來支持虛擬函數機制(面向對象程序設計),基類對象由于其靜態編譯,故不會保留派生類的類型身份。
2、 第一次引入虛擬函數的基類時,必須在類體中將虛擬函數聲明為virtual,但若在該基類外部定義該虛擬函數時不能指定virtual。該基類的派生類中該虛擬函數virtual可加可不加,但從多重繼承考慮,最好加上。
3、 派生類改寫的基類虛擬函數,其原型必須與基類虛擬函數完全匹配(包括const和返回值),但返回值有個特例:派生類實例的返回值可以是基類實例返回類型的公有派生類類型。
4、 純虛擬函數(聲明后緊跟=0,函數定義可寫可不寫)只是提供了一個可被其派生類改寫的接口,其本身不能通過虛擬機制被調用,但可以靜態調用(寫了函數定義的虛基類的純虛擬函數)。一般來說,虛擬函數的靜態調用的目的是為了效率(避免動態綁定)。
5、 包含(或繼承)了一個或多個純虛擬函數的類被編譯器識別為抽象基類,抽象基類不能用來創建獨立的類對象,只能作為子對象出現在后續的派生類中。
6、通過基類指針來調用的虛擬函數的真正實例是在運行時刻確定的。但傳給虛擬函數的缺省實參是在編譯時刻根據被調用函數的對象的類型決定的(也即是若通過基類指針或引用調用派生類實例的虛擬函數,則傳遞給它的缺省實參是由基類指定的)。
7、 虛擬繼承和多繼承相關:
1、 虛擬繼承主要實為了解決繼承了多個基類實例,但是只需要一份單獨的共享實例的情況。
2、 非虛擬派生中,派生類只能顯式的初始化其直接基類(即派生類只能調用其直接基類的構造函數),而在虛擬派生中,虛擬基類的初始化變成了最終派生類的責任,這個最終派生類是由每個特定的類對象聲明來決定的,其非虛擬基類的初始化同非虛擬派生一樣,只能由其直接派生類完成。(即中間派生類的對于虛擬基類構造函數的調用被抑制)。
3、 虛擬繼承下構造函數的調用順序按直接基類的聲明順序,對每個繼承子樹作深度優先遍歷。第一步按此順序調用所有虛擬基類的構造函數;第二步按此順序調用非虛擬基類的構造函數。析構函數的調用順序與構造函數相反。
4、 虛擬基類成員的可視性,對于虛擬基類成員的繼承比該成員后來重新定義的實例權值(優先級)小,故特化的派生類實例名覆蓋了共享的虛擬基類的實例名。而在非虛擬派生下的解析引用過程,每個繼承得到的實例都有相同的權值(優先級)。
5、 繼承下派生類的類域被嵌套在基類類域中,若一個名字在派生類域中沒有被解析出來,則編譯器在外圍基類域中查找該名字定義。在多繼承下,名字解析查找過程為先是在本類類域中查找,再對繼承子樹中的所有基類同時查找,每個繼承得到的實例都有相同的權值(優先級)。若在兩個或多個基類子樹中都找到了該名字,則對其的使用是二義的。