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
内存布局举例如下:
1)classBase
{
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 D1 : public 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 D1 : public 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;}
};
内存布局如下: