在c++中,有两种数据成员:static和nonstatic,三种成员函数:static、nonstatic和virtual。c++对象模型:nonstatic data members被置于类对象之内,而staticdata members被置于类对象之外。static和nonstaticfunction members被放在类对象之外。virtual函数则由如下步骤支持:
1)每个class产生一个vtbl(虚函数表),vtbl中存放其类的类型type_info信息和虚函数指针;
2)对象内添加一个指向vtbl的指针vptr。vptr的设定和重置由类的构造函数、析构函数以及拷贝赋值运算符自动完成。
下面讨论各种情况下c++对象内存布局的情况,以下我做的实验用的都是VS 2013编译器,不同编译器下可能结果有些不同:
一、单继承(带成员变量、虚函数、虚函数覆盖)
1、例子
#include<iostream>
using namespace std;
class Parent{
public:
int iparent;
Parent() :iparent(10){}
virtual void f(){ cout << "Parent::f()" << endl; }
virtual void g(){ cout << "Parent::g()" << endl; }
virtual void h(){ cout << "Parent::h()" << endl; }
};
class Child:public Parent{
public:
int ichild;
Child() :ichild(100){}
virtual void f(){ cout << "Child::f()" << endl; }
virtual void g_child(){ cout << "Child::g_child()" << endl; }
virtual void h_child(){ cout << "Child::h_child()" << endl; }
};
class GrandChild:public Child{
public:
int igrandchild;
GrandChild() :igrandchild(1000){}
virtual void f() { cout << "GrandChild::f()" << endl; }
virtual void g_child() { cout << "GrandChild::g_child()" << endl; }
virtual void h_grandchild() { cout << "GrandChild::h_grandchild()" << endl; }
};
int main(){
typedef void(*pFun)(); //定义一个函数指针,参数列表空,返回值void
pFun fun = NULL;
GrandChild gc;
int** pVtab = (int**)&gc;
cout << "[0] GrandChild::vptr->" << endl;
for (int i = 0; (pFun)pVtab[0][i] != NULL; ++i){
fun = (pFun)pVtab[0][i];
cout << " [" << i << "] ";
fun();
}
cout << "[1] Parent.iparent = " << (int)pVtab[1] << endl;
cout << "[2] Child.ichild = " << (int)pVtab[2] << endl;
cout << "[3] GrandChild.igrandchild = " << (int)pVtab[3] << endl;
system("pause");
return 0;
}
2、运行结果
3、类继承关系
4、GrandChild类对象布局
5、说明
1) 虚表指针在最前面的位置
2) 父类的虚函数在子类的虚函数前面
3)成员变量根据其继承和声明顺序依次放在后面
4)在单一的继承中,被overwrite的虚函数在虚函数表中得到了更新
二、多继承(带成员变量、虚函数、虚函数覆盖)
1、例子
#include<iostream>
using namespace std;
class Base1 {
public:
int ibase1;
Base1() :ibase1(10) {}
virtual void f() { cout << "Base1::f()" << endl; }
virtual void g() { cout << "Base1::g()" << endl; }
virtual void h() { cout << "Base1::h()" << endl; }
};
class Base2 {
public:
int ibase2;
Base2() :ibase2(20) {}
virtual void f() { cout << "Base2::f()" << endl; }
virtual void g2() { cout << "Base2::g()" << endl; }
virtual void h() { cout << "Base2::h()" << endl; }
};
class Base3 {
public:
int ibase3;
Base3() :ibase3(30) {}
virtual void f() { cout << "Base3::f()" << endl; }
virtual void g() { cout << "Base3::g()" << endl; }
virtual void h() { cout << "Base3::h()" << endl; }
};
class Derive : public Base1, public Base2, public Base3 {
public:
int iderive;
Derive() :iderive(100) {}
virt