引入定義乙個類的物件,首先系統已經給這個物件分配了空間,然後會呼叫建構函式(說明:假設存在建構函式)。乙個類有多個物件,當程式中呼叫物件的某個函式時,有可能要訪問到這個物件的成員變數。而對於同乙個類的每乙個物件,都是共享同乙份類函式。物件有單獨的變數,但是沒有單獨的函式,所以當呼叫函式時,系統必須讓函式知道這是哪個物件的操作,從而確定成員變數是哪個物件的。這種用於對成員變數歸屬對像進行區分的東西,就叫做this指標。事實上它就是物件的位址.
#include class parent{//基類
int d; public:
parent()
{ d=1;
cout<<"parent this ="補充:建構函式為什麼不能是虛函式
1. 從儲存空間角度,虛函式對應乙個指向vtable虛函式表的指標,這大家都知道,可是這個指向vtable的指標其實是儲存在物件的記憶體空間的。問題出來了,如果建構函式是虛的,就需要通過 vtable來呼叫,可是物件還沒有例項化,也就是記憶體空間還沒有,怎麼找vtable呢?所以建構函式不能是虛函式。
2. 從使用角度,虛函式主要用於在資訊不全的情況下,能使過載的函式得到對應的呼叫。建構函式本身就是要初始化例項,那使用虛函式也沒有實際意義呀。所以建構函式沒有必要是虛函式。虛函式的作用在於通過父類的指標或者引用來呼叫它的時候能夠變成呼叫子類的那個成員函式。而建構函式是在建立物件時自動呼叫的,不可能通過父類的指標或者引用去呼叫,因此也就規定建構函式不能是虛函式。
3. 建構函式不需要是虛函式,也不允許是虛函式,因為建立乙個物件時我們總是要明確指定物件的型別,儘管我們可能通過實驗室的基類的指標或引用去訪問它但析構卻不一定,我們往往通過基類的指標來銷毀物件。這時候如果析構函式不是虛函式,就不能正確識別物件型別從而不能正確呼叫析構函式。
4. 從實現上看,vbtl在構造函式呼叫後才建立,因而建構函式不可能成為虛函式從實際含義上看,在呼叫建構函式時還不能確定物件的真實型別(因為子類會調父類的建構函式);而且建構函式的作用是提供初始化,在物件生命期只執行一次,不是物件的動態行為,也沒有必要成為虛函式。
5. 當乙個建構函式被呼叫時,它做的首要的事情之一是初始化它的vptr。因此,它只能知道它是「當前」類的,而完全忽視這個物件後面是否還有繼承者。當編譯器為這個建構函式產生**時,它是為這個類的建構函式產生**——既不是為基類,也不是為它的派生類(因為類不知道誰繼承它)。所以它使用的vptr必須是對於這個類的vtable。而且,只要它是最後的構造函式呼叫,那麼在這個物件的生命期內,vptr將保持被初始化為指向這個vtable, 但如果接著還有乙個更晚派生的建構函式被呼叫,這個建構函式又將設定vptr指向它的 vtable,等.直到最後的建構函式結束。vptr的狀態是由被最後呼叫的建構函式確定的。這就是為什麼構造函式呼叫是從基類到更加派生類順序的另乙個理由。但是,當這一系列構造函式呼叫正發生時,每個建構函式都已經設定vptr指向它自己的vtable。如果函式呼叫使用虛機制,它將只產生通過它自己的vtable的呼叫,而不是最後的vtable(所有建構函式被呼叫後才會有最後的vtable)。
note:
1. 如果我們定義了乙個建構函式,編譯器就不會再為我們生成預設建構函式了。
2. 編譯器生成的析構函式是非虛的,除非是乙個子類,其父類有個虛析構,此時的函式虛特性來自父類。
3. 有虛函式的類,幾乎可以確定要有個虛析構函式。
4. 如果乙個類不可能是基類就不要申明析構函式為虛函式,虛函式是要耗費空間的。
5. 析構函式的異常退出會導致析構不完全,從而有記憶體洩露。最好是提供乙個管理類,在管理類中提供乙個方法來析構,呼叫者再根據這個方法的結果決定下一步的操作。
6. 在建構函式不要呼叫虛函式。在基類構造的時候,虛函式是非虛,不會走到派生類中,既是採用的靜態繫結。顯然的是:當我們構造乙個子類的物件時,先呼叫基類的建構函式,構造子類中基類部分,子類還沒有構造,還沒有初始化,如果在基類的構造中呼叫虛函式,如果可以的話就是呼叫乙個還沒有被初始化的物件,那是很危險的,所以c++中是不可以在構造父類物件部分的時候呼叫子類的虛函式實現。但是不是說你不可以那麼寫程式,你這麼寫,編譯器也不會報錯。只是你如果這麼寫的話編譯器不會給你呼叫子類的實現,而是還是呼叫基類的實現。
7.在
析構函式中
也不要呼叫虛函式。在析構的時候會首先呼叫子類的析構函式,析構掉物件中的子類部分,然後在呼叫基類的析構函式析構基類部分,如果在基類的析構函式裡面呼叫虛函式,會導致其呼叫已經析構了的子類物件裡面的函式,這是非常危險的。
8. 記得在寫派生類的拷貝函式時,呼叫基類的拷貝函式拷貝基類的部分,不能忘記了。
c 基類指標,子類指標,多型
基類指標和子類指標之間的相互賦值 1 將子類指標賦值給基類指標時,不需要進行強制型別轉換,c 編譯器將自動進行型別轉換。因為子類物件也是乙個基類物件。2 將基類指標賦值給子類指標時,需要進行強制型別轉換,c 編譯器將不自動進行型別轉換。因為基類物件不是乙個子類物件。子類物件的自增部分是基類不具有的。...
C 基類與子類 函式指標的定義和轉換
定義乙個類,作為基類 twindow public cwnd 定義乙個字類 class tform public twindow void onbuttonclicked 定義乙個函式指標 typef void twindow functionptr 使用這個指標 functionptr fun f...
繼承,基類指標指向子類物件
include include using namespace std class a a a class b public a b void update void print b b class c public a c void update void print c c class d pu...