在繼承中構成多型有兩個條件
1:必須通過基類的指標或者引用呼叫虛函式;
2:被呼叫的函式必須是虛函式,並且派生類必須對於虛函式進行重寫;
這就是我們的多型,但是多型是怎麼實現的呢?
class
base
private:
intm_a
;int
m_b;};
class
a:public
base
private:
inta
;intb;
};
我們來看最基本的繼承
aa;
base*p
=&a;
p->
fun(
);
這是我們的賦值相容規則,我們的子類可以給父類的指標或者是引用賦值,呼叫的父類的方法。
但是如果我們的程式加上virtual
class
base
private:
intm_a
;int
m_b;};
class
a:public
base
void
print()
private:
inta
;intb;
};intmain()
這時候就會呼叫我們的子類fun()。
為什麼會出現這種情況呢?
class
base
private:
intm_a
;int
m_b;
};
我們來看這個類的大小很明顯是8,但是我們加了關鍵字virtual後
class
base
private:
intm_a
;int
m_b;
};
這個類的大小是 12;
我們來看這個類的成員
我們看到了這個__vfptr指標。
virtual
function
pointer
這個虛表函式指標始終只有乙個,不管乙個類裡面有多少個虛函式
這就是我們所說的虛函式表,這個__vfptr是乙個指向虛函式表的指標。
這個表裡面所放的是虛函式的位址。虛表最後位置是nullptr表示結束
這個是父類的虛函式表。
子類在繼承下來的時候會繼承父類的虛表,但是子類進行了重寫,就會更改虛函式表對應虛函式的位址,所以實現我們的賦值。
但是我們怎麼來用程式看到這個指標呢?
__vfptr是隱藏在內部的,我們可以通過編譯器檢視,但是我們不能顯式呼叫,我們拿到其首部的四個位元組列印來看
baseb;
printf
("%x\n",*
(int*)
&b);
vfptr
*vfptr_ar=(
vfptr*)
(*(int*)
&b);
cout
<
<
vfptr_ar
<
<
endl
;
這就是虛函式的位址。
列印虛表函式
typedef
void(*
vfptr)(
);void
print
(vfptr
*ptr)}
intmain()
多型 2 多型的實現原理
當類中宣告虛函式時,編譯器會在類中生成乙個虛函式表 虛函式表是乙個儲存類成員函式指標的資料結構 虛函式表是由編譯器自動生成與維護的 virtual成員函式會被編譯器放入虛函式表中 存在虛函式時,每個物件中都有乙個指向虛函式表的指標 vfptr指標 物件在建立的時,由編譯器對vfptr指標進行初始化 ...
C 多型實現原理
用virtual關鍵字申明的函式叫做虛函式,虛函式肯定是類的成員函式。存在虛函式的類都有乙個一維的虛函式表叫做虛表。類的物件有乙個指向虛表開始的虛指標。虛表是和類對應的,虛表指標是和物件對應的。多型性是乙個介面多種實現,是物件導向的核心。分為類的多型性和函式的多型性。多型用虛函式來實現,結合動態繫結...
多型實現的原理
多型實現的原理從兩個方面說明 1.虛函式表 2.rtti機制 當你在乙個類中使用了virtual關鍵字,那麼就產生了虛函式表,虛函式表中存放的是虛函式的入口位址,父類有父類的虛表,子類有子類的虛表,當繼承時,虛表進行了複製,在子類中重寫了父類的虛函式時,子類虛表中這個函式位址就替換成子類虛函式的位址...