c 中為什麼可以通過指標或引用實現多型詳解

2022-09-25 03:18:08 字數 1912 閱讀 1206

在c++中司空見慣的事情就是:可以通過指標和引用可以實現多型,而物件不可以。 那為什麼?讓我們來解開這神秘的暗紗!

在乙個類的例項中,只會存放非靜態的成員變數。 如果該類中存在虛函式的www.cppcns.com話,再多加乙個指向虛函式列表指標—vptr。

例如宣告如下兩個類,並分別例項化兩個物件,它們的記憶體分配大致如下:(vptr具體在什麼位置,與編譯器有關,大多數都在開始處)

class base

; virtual string getname()

geta();

int a;

};class derived : public base

; virtual string getname()

getb();

i程式設計客棧nt b;

};base b1, b2;derived d1, d2;

記憶體分布大致如下:

1. 類物件中,只有成員變數與vptr.

2. 普通成員函式在記憶體的某一位置放著。它們與c語言中定義的普通函式沒有區別。 當我們通過物件或物件指標呼叫普通成員函式時, 編譯器會拿到它。怎麼拿到呢?當然是通過名字了,編譯器都會對我們寫的函式的名字進行修飾對映,讓它們變成記憶體中唯一的函式名。

3. 無論基類還是子類,每一種類型別的虛函式表只有乙份,它裡面存放了基類的型別資訊和指向基類中的虛函式的指標。 某一類型別的所有物件都指向了相同的虛函式表。

例如:下面的 base型別的物件b1或指標pb1,只能使用getname() 和geta()方法。 無論它們是如何來的!!!!!

// 直接構造得到

base b1;

base* pb1 = new base();

// 即使從子類轉換而來, 通過b1或pb1也永遠訪問不到getb()方法。

derived d1;

b1 = d1;

pb1 = new derived();

本質上它們沒有任何區別,在32/64位系統中都是4/8位元組的乙個變數。 唯一不同的就是編譯器解釋它們的方式,即通過指標來定址出來的物件型別不同,大小不同 ,指標型別來告訴編譯器如何解釋該指標。

有**如下 :

derived* _pd = new derived();

base* _pb = _pd;

_pb.getname(); // 返回 derived.

想要知道如何通過指標來實現的多型,就要看看對基類指標賦值是發生了什麼! 具體來說 如下圖所示:

我們會發現,對指標的賦值,僅僅是讓基類指標_pb指向的子類物件的地位址。 當我們使用基類指標呼叫getname()函式(該函式是虛函式,它的位址在函式表中)時, 會由_pb指向的位址找到子類的虛函式表指標vptr_上海,再由vptr_上海在虛函式表中找到子類的getname(),從而呼叫它。就這樣實現了多型。

有**如下:

base b1;

derived d1;

b1 = d1;

b1.getname(); // 返回 base

base b2 = d1

b2.getname(); // 返回 base

上面**中無論賦值操作還是賦值構造時, 只會處理成員變數,乙個類物件裡面的vptr永遠不會變,永遠都會指向所屬型別的虛函式表,操作如下圖所示:

因此,通過物件呼叫虛函式時,就沒有必要進行動態解析了,白白增加了間接性,浪費效能。編譯器直接在編譯時就可以確認具體呼叫哪乙個函式了,因此沒有所謂的多型。

補充說明:

1. 引用本質上也是通過指標的解引用(即*_point)來實現的,可以

2. 即使通過 基類的指標呼叫基類的虛函式 或 通過子類的指標呼叫子類的虛函式 以及通過子類指標呼叫基類的虛函式, 也是通jvkxpzhk過多型機制來完成的(即一步步的間接性來完成)。

3. 乙個空的class的物件的大小為1個位元組, 編譯器之所以要這麼做,程式設計客棧是為了區別同乙個類型別的不同物件!

C 中為什麼要用虛函式 指標或引用才能實現多型?

學過c 的都知道,要實現c 的多型性必須要用到虛函式,並且還要使用引用或者指標,以前學習的時候書本上也是這麼說,但是書本上沒有說為什麼?其實只要你認真思考過這個問題你會有三個疑問 為什麼要用虛函式?為什麼要用指標或者引用?為什麼使用派生類和基類物件之間直接賦值不能實現?乙個簡單的例子 cpp vie...

C 中引用與指標有什麼區別

1 從記憶體分配方面來講,系統為指標變數分配儲存空間,而引用與繫結的變數共享記憶體空間,系統不另外為引用變數分配儲存空間。指標是乙個實體,而引用僅僅是另乙個變數的別名。int main int argc,char argv 2 引用必須初始化,而指標不必,指標可以在需要的時候進行賦值。3 引用一旦初...

為什麼 C 中成員函式指標是 16 位元組?

當我們討論指標時,通常假設它是一種可以用void 指標來表示的東西,在 x86 64 平台下是 8 個位元組大小。例如,下面是來自 維基百科中關於 x86 64 的文章 的摘錄 pushes and pops on the stack are always in 8 byte strides,and...