多態—— 一個接口 多種形態,
編譯器在執行過程中遇到virtual關鍵字的時候,將自動安裝動態聯編需要的機制,首先為這些包含virtual函數的類(注意不是類的實例)--即使是祖先類包含虛函數而本身沒有--建立一張虛擬函數表VTABLE。在這些虛擬函數表中,編譯器將依次按照函數聲明次序放置類的特定虛函數的地址。同時在每個帶有虛函數的類中放置一個稱之為vpointer的指針,簡稱vptr,這個指針指向這個類的VTABLE。
一般來說一個對象的大小為所有成員變量的大小,但是當存在虛函數的時候即使這個類沒有任何成員變量,他的對象的大小也不為0,為一個虛函數指針的大小。當定義父類的一個函數為虛函數時,在子類中重載這個函數,用一個父類指針指向子類對象,并調用該函數的時候,調用的是子類的函數而不是父類的。如果
父類中這個函數不是虛函數的話,調用的就是父類的函數了

菱形繼承
#include<iostream>using namespace std;class AA{public: int _aa;};class BB : public AA{public: int _bb;};class CC : public AA{public: int _cc;};class DD :public BB, public CC{public: int _dd;};int main(){ DD d; d.BB::_aa = 0; d.CC::_aa = 1; d._bb = 2; d._cc = 3; d._dd = 4; cout<< sizeof(d) << endl; return 0;}
我們能夠看到對象d中有繼承的類BB和類CC,我們能夠看到菱形繼承中,對象d中存在兩個成員_aa,這就存在問題,當我們想要訪問_a時,編譯器也不會知道我們想要訪問的是哪一個變量,這就說明菱形繼承存在一個“數據冗余”和“二義性“的問題。那么如何解決菱形繼承所存在的這種問題呢菱形虛擬繼承
#include<iostream>using namespace std;class AA{public: int _aa;};class BB :virtual public AA{public: int _bb;};class CC :virtual public AA{public: int _cc;};class DD :public BB, public CC{public: int _dd;};int main(){ DD d; d.BB::_aa = 0; d.CC::_aa = 1; d._bb = 2; d._cc = 3; d._dd = 4; cout<< sizeof(d) << endl; return 0;}虛擬繼承解決了這些問題
新聞熱點
疑難解答