C++中的對象模型

所謂多態,即“多種形態“。

         C++中虛函數的主要作用就是實現多態,每一個具有虛函數的類都叫做多態類。這個虛函數或者是從基類繼承來的,或者是自己新增的。C++編譯器爲每一個多態類至少創

建一個虛函數表(vtable),他其實就是一個函數指針數組,其中存放着這個類所有的虛函數的地址及該類的類型信息,其中也包括那些繼承但未改寫的虛函數。簡單地說父類

的指針/引用調用重寫的虛函數,當父類指針/引用指向父類對象時調用的是父類的函數,指向子類對象時調用的是子類的函數。

【以下測試均在windows7 32位vs2008環境下的測試】

1、探索虛函數表

       虛函數表是通過一塊連續內存來存儲虛函數的地址。這張表解決了繼承、虛函數(重寫)的問題。在虛函數的對象實例中都存在一張虛函數表、虛函數表就像一張地圖、指

明瞭實際應該調用的虛函數。

#include<iostream>
using namespace std;
class Base
{
public:
       virtual void func1()
 { }
 virtual void func2()
 { }
private:

       int a;
};
void Test1()
{
       Base b1;
}
int main()
{
      Test1();
       return 0;
}

                                                                                            【虛函數表】

2、探索單繼承對象模型

class Base
{
public:
 virtual void func1()
 {
  cout<<"Base::func1"<<endl;
 }
 virtual void func2()
 {
  cout<<"Base::func2"<<endl;
 }
private:
 int a;
};
class Derive:public Base
{
public:
 virtual void func1()
 {
  cout<<"Derve::func1"<<endl;
 }
 virtual void func3()
 {
  cout<<"Derve::func3"<<endl;
 }
 virtual void func4()
 {
  cout<<"Derve::func4"<<endl;
 }
private:
 int b;
};
typedef void(*FUNC)();
void PrintVTable(int *VTable)
{
 cout<<"虛表地址->"<<VTable<<endl;
 for(int i=0;VTable[i]!=0;++i)
 {
  printf("第%d個虛函數地址:0X%x,->",i,VTable[i]);
  FUNC f=(FUNC) VTable[i];
  f();
 }
 cout<<endl;
}
void Test1()
{
 Base b1;
 Derive d1;
 int* VTable1=(int*)(*(int*)&b1);
 int* VTable2=(int*)(*(int*)&d1);
 PrintVTable(VTable1);
 
 PrintVTable(VTable2);
}

     VS2008監視窗口中的虛表

     可以看到派生類Derive::func1重寫基類Base::func1,覆蓋了相應虛表位置上的函數。(可以看到這裏沒有看到派生類Derive中的func3和func4,這個函數就放在func2的後面,

裏沒有顯示是vs的問題(bug))。

                                                                                           【單繼承對象模型】

 

3、探索多重繼承的內存分佈

class Base1
{
public:
 virtual void func1()
 {
  cout<<"Base1::func1"<<endl;
 }
 virtual void func2()
 {
  cout<<"Base1::func2"<<endl;
 }
private:
 int b1;
};
class Base2
{
public:
 virtual void func1()
 {
  cout<<"Base2::func1"<<endl;
 }
 virtual void func2()
 {
  cout<<"Base2::func2"<<endl;
 }
private:
 int b2;
};
class Derive:public Base1,public Base2
{
public:
 virtual void fun1()
 {
  cout<<"Derive::func1"<<endl;
 }
 virtual void fun3()
 {
  cout<<"Derive::func3"<<endl;
 }
private:
 int d1;
};
typedef void(*FUNC)();
void PrintVTable(int *VTable)
{
 cout<<"虛表地址->"<<VTable<<endl;
 for(int i=0;VTable[i]!=0;++i)
 {
  printf("第%d個虛函數地址:0X%x,->",i,VTable[i]);
  FUNC f=(FUNC) VTable[i];
  f();
 }
 cout<<endl;
}
void Test1()
{
 Derive d1;
 int* VTable=(int*)(*(int*)&d1);
 PrintVTable(VTable);
 VTable=(int*)(*((int*)&d1+sizeof(Base1)/4));
 PrintVTable(VTable);
}

                                                                                【多重繼承對象模型】

4、多態

多態即多種形態,C++的多態分爲靜態多態和動態多態。

(1)靜態多態就是重載,因爲是在編譯期決議確定,所以稱爲靜態多態。

(2)動態多態就是通過繼承重寫基類的虛函數實現的多態,因爲是在運行時決議確定、所以稱爲動態多態。

發佈了53 篇原創文章 · 獲贊 3 · 訪問量 2萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章