C++虚函数表理解
C++虛函數表理解
一,思維模式圖
二,代碼驗證
class A { public:A(int x) {fProtected = x;}float GetFProtected() {return fProtected;}public:float fpublic = 2.3f; //c++11支持了初始化,但不能使用autostring sname = "liqi";CMyNumOperator<int>* on = new CMyNumOperator<int>(); //對象也可以void TestFunc() {cout << "TestFunc" << endl;}static void StaticTestFunc() {cout << "Static-TestFunc" << endl;}virtual void ToString() {cout << "A::ToString" << endl;} protected:float fProtected;void ProtectedFunc() {cout << "PRotectedFunc" << endl;} private:void PrivateFunc() {cout << "PrivateFunc" << endl;}};//只管公有繼承,不管保護繼承和私有繼承,意義不大,也太復雜 class B : public A { public:friend void TestProtectedDerive();B() :A(1) {}void TestForDerive() {//公有繼承下//1,子類可以訪問父類的保護成員,不能訪問父類的私有成員 B ob;//PrivateFunc(); //error,子類不能訪問基類的私有成員ProtectedFunc(); //rightfProtected = 10; //rightob.fProtected = 20; //right }//1,c++中只要基類有相同簽名虛函數,則默認為此基類函數也是虛函數[與C#不同],如下情形都成立// (1) 函數不聲明 virtual// (2) 函數聲明了 virtual// (3) 函數聲明了 override// (4) 函數聲明了 virtual 和 override//2,c++中兩個關鍵詞作用不同,可以同時存在// virtual僅表明函數是虛函數,override是C++11中出現的,明確說明是對基類的重寫// 它的好處是當函數聲明不符合規則時,編譯器會報錯void virtual ToString() override{cout << "B::ToString" << endl;} };void TestVirtualFunctionTable() {cout << hex;typedef void(*PFUNC)();offsetof(A, fpublic); //利用此函數可以算函數布局 A oa(0);B ob;//一,通過內存地址修改不可訪問的保護變量*(float*)((int*)&oa + 1) = 123.4f; //類的第一個變量fpublic賦值,(int*)&oa + 1是跳過虛函數指針float fpublic = oa.fpublic;//二,通過內存地址調用虛函數//A和B的虛函數表地址不一樣,也就是說父類和子類各有一張虛函數表int* pvptr = (int*)(*((int*)(&oa)));cout << "A的虛函數表地址:" << pvptr << endl; //000DB0D4((void(*)())(*pvptr))(); //A::ToString pvptr = (int*)(*((int*)(&ob)));cout << "B的虛函數表地址:" << pvptr << endl; //000DB128((void(*)())(*pvptr))(); //B::ToString cout << "--------------------------" << endl;//最簡寫法((void(*)())(*((int*)*(int*)&oa)))();((void(*)())(*((int*)*(int*)&ob)))();}?
posted on 2018-07-19 19:14 時空觀察者9號 閱讀(...) 評論(...) 編輯 收藏
總結
- 上一篇: 【转】c++虚函数实现原理
- 下一篇: c++动态链接库及静态链接库的生成与使用