整理自用 c 繼承 虛函式

2021-08-17 16:00:47 字數 2944 閱讀 5323

一般的認為,虛機制發生在物件呼叫時,其實不然,只要能用到之時,他便會出現!在呼叫基類函式的時候,如果基類呼叫了乙個虛函式,同樣虛機制也會產生效果!(不是基類的建構函式中!)

以下兩端**輸出結果完全不同,原因就在於:呼叫虛函式,只受當前物件的影響。即this指標。

#include 

using namespace std;

class base

virtual ~base() {}

public:

void

print(void)

void

get(void )

};class devined : public base

~devined() {}

public:

void

print(void)

};int main()

儘管a是devined型別的,但是該類中沒有get函式。而派生類指標可以隱式轉為基類指標,因此到基類中去找函式。接著,基類中get()呼叫了的print函式,而這只是乙個普通函式,在當前base類中只能找到乙個print函式,因此就直接執行了。

但是:如果get()呼叫了的print函式是乙個虛函式,由於前面已經說了:呼叫虛函式,只受當前物件的影響。即this指標。。因此,此時會根據a的動態型別來決定呼叫的函式。

#include 

using namespace std;

class base

virtual ~base() {}

public:

vitual void

print(void)

void

get(void )

};class devined : public base

~devined() {}

public:

vitual void

print(void)

};int main()

即便是呼叫的基類函式,也還是回到派生類的函式呼叫!

輸出:

devined!

繼續:如果虛函式存在著預設值狀態。

virtual 函式是動態繫結,而預設引數值卻是靜態繫結。 意思是你可能會 在「呼叫乙個定義於派生類內的virtual函式」的同時,卻使用基類為它所指定的預設引數值。

結論:絕不重新定義繼承而來的預設引數值!(可參考《effective c++》條款37)

對於本例:

b *p =

new b;

p->test();

p->test()執行過程理解:

(1) 由於b類中沒有覆蓋(重寫)基類中的虛函式test(),因此會呼叫基類a中的test();

(2) a中test()函式中繼續呼叫虛函式 fun(),因為虛函式執行動態繫結,p此時的動態型別(即目前所指物件的型別)為b*,因此此時呼叫虛函式fun()時,執行的是b類中的fun();所以先輸出「b->」;

(3) 預設引數值是靜態繫結,即此時val的值使用的是基類a中的預設引數值,其值在編譯階段已經繫結,值為1,所以輸出「1」;

最終輸出「b->1」。所以大家還是記住上述結論:絕不重新定義繼承而來的預設引數值!

建構函式不要呼叫虛函式。在基類構造的時候,虛函式是非虛,不會走到派生類中,既是採用的靜態繫結。顯然的是:當我們構造乙個子類的物件時,先呼叫基類的建構函式,構造子類中基類部分,子類還沒有構造,還沒有初始化,如果在基類的構造中呼叫虛函式,如果可以的話就是呼叫乙個還沒有被初始化的物件,那是很危險的,所以c++中是不可以在構造父類物件部分的時候呼叫子類的虛函式實現。但是不是說你不可以那麼寫程式,你這麼寫,編譯器也不會報錯。只是你如果這麼寫的話編譯器不會給你呼叫子類的實現,而是還是呼叫基類的實現。

在析構函式中也不要呼叫虛函式。在析構的時候會首先呼叫子類的析構函式,析構掉物件中的子類部分,然後在呼叫基類的析構函式析構基類部分,如果在基類的析構函式裡面呼叫虛函式,會導致其呼叫已經析構了的子類物件裡面的函式,這是非常危險的。

指向虛函式表的指標在32位系統下占用4個位元組,其位址分布在整個類成員變數的位址的首部

在虛函式表指標之後才是其他資料變數和成員變數

題目:**執行後,a和b的值分別為?(200,10)

class test

test(int temp1 = 0, int temp2 = 0)

int geta()

int getb()

};int main()

有上述分析可得:

1.pint+0的位址是class test的虛函式表位址,佔4個位元組。

2.pint+1的位址是class test宣告的第乙個成員變數的位置。

因此,經過修改後,虛函式指標變了,變數

a a

的數值變為200,其他保持不變。

delete子類物件是一定會呼叫父類的析構函式的!!!

先呼叫子類的析構函式然後呼叫父類的析構函式;

如果要呼叫父類指向子類的物件,此時才需要父類的析構函式是虛的。

c++類體系中,不能被派生類繼承的有:

1. 建構函式

2. 靜態成員函式

3. 賦值操作函式

建構函式不能被繼承,但是可以被呼叫。派生類的建構函式在初始化列表中應呼叫基類的建構函式。

虛函式 純虛函式 虛繼承資料整理

感謝這些優秀的文章 虛函式與純虛函式 虛函式的實現1 虛函式的實現2 菱形繼承與虛繼承 首先從虛函式開始說起吧.虛函式是實現了多型機制,具體表現為父型別的指標指向其子類的例項.然後通過服淚指標嗲用實際子類中的成員函式.這種技術可以讓父類指標有多種形態.如果呼叫非虛函式,無論物件是什麼型別,都執行基類...

整理自用 C 函式傳遞

這個本來是沒什麼需要說明的,但是偏偏是錯了幾道題,發現自己思考不夠嚴謹。函式傳遞,確實存在著值傳遞 址傳遞和引用傳遞三種。但是要搞清楚著通常是對於什麼變數而言的。以下三個是所謂的值傳遞,值傳遞和引用傳遞最簡單的表達形式 int abs int a intabs int a intabs int a ...

虛函式 虛繼承 C

關於虛表,我們就要用到乙個關鍵字 virtual,可以修飾函式,也可以修飾類。類的成員函式被virtual修飾之後,就成為了虛函式 修飾類,主要是虛繼承。在此之前,我們首先要了解乙個概念 物件模型,也就是說,乙個基類形成之後,裡面的成員是怎麼存放的,當派生類繼承基類之後,派生類的成員是怎麼存放的。我...