C++中的对象模型

来源:互联网 发布:mac不能同时登陆2个qq 编辑:程序博客网 时间:2024/06/03 22:58

所谓多态,即“多种形态“。

         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)动态多态就是通过继承重写基类的虚函数实现的多态,因为是在运行时决议确定、所以称为动态多态。

0 0
原创粉丝点击