虚继承与虚函数表

http://www.cnblogs.com/itech/archive/2009/02/27/1399996.html

http://www.learncpp.com/cpp-tutorial/125-the-virtual-table/

http://wenku.baidu.com/view/0738df1ea76e58fafab003c5.html

http://www.cnblogs.com/itech/category/170009.html

http://blog.csdn.net/angelxf/article/details/7853101

 

内存布局举例如下:

1classBase

{

public:

    FunctionPointer *__vptr;

    virtualvoidfunction1() {};

    virtualvoidfunction2() {};

};

  

classD1: publicBase

{

public:

    virtualvoidfunction1() {};

};

  

classD2: publicBase

{

public:

    virtualvoidfunction2() {};

};

 

每个类的基类中如果有虚函数,那么在基类中就有一个隐藏的vptr指针;虚函数如下图所示:

 

 

 

2)含有成员变量情况下的内存布局(多重继承)

 转自:http://www.cnblogs.com/itech/archive/2009/02/28/1399995.html

#include <iostream>
using namespace std;

class B1
{
public:
 int x;
 virtual void v1(){ cout << "B1::v1" << endl; }
 void f1(){cout << "B1::f1" << endl; }
};

class B2
{
public:
 int y;
 virtual void v2(){ cout << "B2::v2" << endl; }
 void f2(){ cout << "B2::f2" << endl; }
};

class B3
{
public:
 int z;
 virtual void v3(){ cout << "B3::v3" << endl; }
 void f3(){ cout << "B3::f3" << endl; }
};

class D : public B1, public B2, public B3
{
public:
 int a;
 void v3(){ cout << "D::v3" << endl; }
 virtual void vD(){ cout << "D::vD" << endl; }
};

typedef void (*Fun)();

void PrintMember(int *pI)
{
 cout << *pI << endl;
}
void PrintVT(int *pVT)
{
 while(*pVT != NULL)
 {
  (*(Fun*)(pVT))();
  pVT++;
 }
}

void PrintVTAndMember(B1 *pD)
{
 int *pRoot = (int*)pD;
 int *pVTB1 = (int*)*(pRoot + 0);PrintVT(pVTB1);
 int *pMB1 = pRoot +1; PrintMember(pMB1);
 int *pVTB2 = (int*)*(pRoot + 2);PrintVT(pVTB2);
 int *pMB2 = pRoot +3; PrintMember(pMB2);
 int *pVTB3 = (int*)*(pRoot + 4);PrintVT(pVTB3);
 int *pMB3 = pRoot +5; PrintMember(pMB3);
}

void TestVT()
{
 B1 *pB1 = new D();
 D *pD = dynamic_cast<D*>(pB1);
 pD->x = 10;
 pD->y = 20;
 pD->z = 30;
 pD->a = 40;
 PrintVTAndMember(pD);
 delete pD;
}

 


int _tmain(int argc, _TCHAR* argv[])
{
 //A a;
 D d;
 int len=sizeof(D);

 TestVT();

 return 0;
}

 

输出如下:

 

解释:

 与单继承相同的是所有的虚函数都包含在虚函数表中,所不同的多重继承有多个虚函数表,当子类对父类的虚函数有重写时,子类的函数覆盖父类的函数在对应的虚函数位置,当子类有新的虚函数时,这些虚函数被加在第一个虚函数表的后面。

vs2008 VS2008使用命令行选项查看对象的内存布局

http://www.cnblogs.com/microgrape/archive/2011/05/11/2043794.html

 

3)含有虚拟继承的 多继承情况;

 


#include <iostream>
using namespace std;

class B
{
public:
 int i;
 virtual void vB(){ cout << "B::vB" << endl; }
 void fB(){ cout << "B::fB" << endl;}
};

class D1 : virtual public B
{
public:
 int x;
 virtual void vD1(){ cout << "D1::vD1" << endl; }
 void fD1(){ cout << "D1::fD1" << endl;}
};

class D2 : virtual public B
{
public:
 int y;
 void vB(){ cout << "D2::vB" << endl;}
 virtual void vD2(){ cout << "D2::vD2" << endl;}
 void fD2(){ cout << "D2::fD2" << endl;}
};

class GD :  public D1, public D2
{
public:
 int a;
 void vB(){ cout << "GD::vB" << endl;}
 void vD1(){cout << "GD::vD1" << endl;}
 virtual void vGD(){cout << "GD::vGD" << endl;}
 void fGD(){cout << "GD::fGD" << endl;}
};


typedef void (*Fun)();

void PrintMember(int *pI)
{
 cout << *pI << endl << endl;
}
void PrintVT(int *pVT)
{
 while(*pVT != NULL)
 {
  (*(Fun*)(pVT))();
  pVT++;
 }
}

void PrintMemberAndVT(GD *pGD)
{
 int *pRoot = (int*)pGD;

 int *pD1VT = (int*)*(pRoot + 0);
 (*(Fun*)(pD1VT))(); (*(Fun*)(pD1VT +1))();
 int *pVB = (int*)*(pRoot +1);  cout << "vbtable's adress:" << *pVB << endl;
 int *pX = (pRoot + 2); PrintMember(pX);

 int *pD2VT = (int*)*(pRoot + 3);
 (*(Fun*)(pD2VT))();
 int *pVB2 = (int*)*(pRoot +4); cout << "vbtable's adress:" << *pVB2 << endl;
 int *pY = (pRoot + 5); PrintMember(pY);

 int *pA = (pRoot + 6); PrintMember(pA);

 int *pBVT = (int*)*(pRoot + 7);
 (*(Fun*)(pBVT))();
 int *pI = (pRoot + 8); PrintMember(pI);
}

void TestVT()
{
 B *pB = new GD();
 GD *pGD = dynamic_cast<GD*>(pB);
 pGD->i = 10;
 pGD->x = 20;
 pGD->y = 30;
 pGD->a = 40;
 PrintMemberAndVT(pGD);
 delete pGD;
}
int _tmain(int argc, _TCHAR* argv[])
{
 //A a;


 TestVT();

 return 0;
}

 结果:

解释:

 

 

vs2008 查看的内存布局如下:

 

虚继承情况下会有一个vbtable用来保存基类的内存;所以当D1和D2同时继承B时,B的内存没有重复,只是两个Vbtable同时指向这个内存;

 

4)没有虚继承的多继承情况下

 

举例:

class B
{
public:
 int i;
 virtual void vB(){ cout << "B::vB" << endl; }
 void fB(){ cout << "B::fB" << endl;}
};

class D1 :  public B
{
public:
 int x;
 virtual void vD1(){ cout << "D1::vD1" << endl; }
 void fD1(){ cout << "D1::fD1" << endl;}
};

class D2 :  public B
{
public:
 int y;
 void vB(){ cout << "D2::vB" << endl;}
 virtual void vD2(){ cout << "D2::vD2" << endl;}
 void fD2(){ cout << "D2::fD2" << endl;}
};

class GD :  public D1, public D2
{
public:
 int a;
 void vB(){ cout << "GD::vB" << endl;}
 void vD1(){cout << "GD::vD1" << endl;}
 virtual void vGD(){cout << "GD::vGD" << endl;}
 void fGD(){cout << "GD::fGD" << endl;}
};

 

那么此时的GD的内存布局如下:

 

说明此时基类B对象的内存是重复的,有2份,而虚拟继承就只有一份,在这个时候如果 定义 B*pB=new GD();会报错的。

 

5)单继承无虚继承的情况

class B
{
public:
 int i;
 virtual void vB(){ cout << "B::vB" << endl; }
 void fB(){ cout << "B::fB" << endl;}
};

class D1 :  public B
{
public:
 int x;
 virtual void vD1(){ cout << "D1::vD1" << endl; }
 void fD1(){ cout << "D1::fD1" << endl;}
};


class GD :  public D1
{
public:
 int a;
 void vB(){ cout << "GD::vB" << endl;}
 void vD1(){cout << "GD::vD1" << endl;}
 virtual void vGD(){cout << "GD::vGD" << endl;}
 void fGD(){cout << "GD::fGD" << endl;}
};

 

此时GD的内存布局如下:

 

6)

私有继承的内存布局

私有继承的内存布局和公有继承一样,只是不能直接访问基类的数据成员;

class B

{

public:

     int i;

     virtual void vB(){ cout << "B::vB" << endl; }

     void fB(){ cout << "B::fB" << endl;}

};

 

class D1public B

{

public:

     int x;

     virtual void vD1(){ cout << "D1::vD1" << endl; }

     void fD1(){ cout << "D1::fD1" << endl;}

};

 

 

class GD : D1

{

public:

     int a;

     void vB(){ cout << "GD::vB" << endl;}

     void vD1(){cout << "GD::vD1" << endl;}

     virtual void vGD(){cout << "GD::vGD" << endl;}

     void fGD(){cout << "GD::fGD" << endl;}

};

 

 

内存布局图如下:

 

7)

如果将成员变量变为私有的,内存布局也不会改变;

class B

{

     int i;

public:

    

     virtual void vB(){ cout << "B::vB" << endl; }

     void fB(){ cout << "B::fB" << endl;}

};

 

class D1public B

{

     int x;

public:

    

     virtual void vD1(){ cout << "D1::vD1" << endl; }

     void fD1(){ cout << "D1::fD1" << endl;}

};

 

 

class GD : D1

{

public:

     int a;

     void vB(){ cout << "GD::vB" << endl;}

     void vD1(){cout << "GD::vD1" << endl;}

     virtual void vGD(){cout << "GD::vGD" << endl;}

     void fGD(){cout << "GD::fGD" << endl;}

};

 

内存布局如下:

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 4
    评论
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值