多态的原理
- 虛函數表
發現輸出是8個位元組,int占4個位元組,那麼是什麼占用了空間呢class base { public: virtual void func() { cout << "func" << endl; } private: int a_; }; int main() { base b; cout << sizeof(b) << endl; // 8 32位 return 0; }
發現除了a__外還有一個_vfptr數組, 數組中存放虛函數的指針
- 派生類中虛表覆寫
class base { public: virtual void func() { cout << "func" << endl; } virtual void func1() { cout << "func1" << endl; } void func2() { cout << "func2" << endl; } private: int a_; }; class derive : public base { public: virtual void func() override { cout << "derive func" << endl; } private: int b_; }; int main() { base b; derive d; return 0; }
可以看到派生類對象中繼承自基類的_vfptr數組中被重寫的虛函數已經變成派生類中的函數指針
- 結論
- 類中虛函數的指針會被存在虛表中,虛表是一個指針數組,這個數組最後面放了一個nullptr
- 不是虛函數的函數,其函數指針不會被放進虛表
- 派生類的虛表生成, 先将基類中的虛表内容拷貝一份到派生類虛表中,然後看派生類中是否重寫了基類的虛函數,如果重寫就将派生類中的虛函數指針覆寫基類的虛函數, 派生類新增的虛函數按其在派生類的聲明次序增加到派生類虛表的最後
- 虛表存的是虛函數指針,不是虛函數,虛函數和普通函數一樣都存在代碼段
- 多态條件
- 虛函數覆寫
- 對象的指針或引用調用虛函數
必須用指針或引用調用虛函數才能構成多态的原因是, 滿足多态以後的函數調用是在運作的時候從對象裡找的, 不滿足多态的函數是編譯時确認好的derive d; base a = d; base* p = &d; base& r = d;
-
動态綁定與靜态綁定
靜态綁定又稱前期綁定,在程式編譯器确定了程式的行為,也稱靜态多态,比如函數重載
滿足多态以後的函數調用是在運作的時候從對象裡找的, 不滿足多态的函數是編譯時确認好的
-
動态綁定與靜态綁定
靜态綁定又稱前期綁定,在程式編譯器确定了程式的行為,也稱靜态多态,比如函數重載
動态綁定又稱後期綁定,是在程式運作期間,根據具體拿到的類型确定程式的具體行為,調用具體的函數