C++中有两种数据成员:
- 静态
- 非静态
三种成员函数:
- 静态
- 非静态
- 虚函数
- 非静态数据成员在对象之内
- 静态数据成员在对象之外
- 静态、非静态成员函数在对象之外
- 类中存在虚函数时,一个类相应一个virtual table(vtbl)放在对象之外,对象中安插一个指针vptr指向这个表。但vptr放在对象的什么位置上要视编译器而定。vptr的设置由构造、析构、赋值运算符函数自己主动完毕。
C++对象模型例如以下图所看到的:
每一个类相关联的信息由vtbl内的一个slot指出。用来支持RTTI机制。
測试例程:
#include <iostream>
using namespace std;
class A {
public:
int x, y;
static int s;
void f1() { }
static void f2() { }
virtual void f3() { }
};
int A::s = 123;
int main()
{
cout << "size = " << sizeof(A);
return 0;
}
执行结果:
能够看出,对象所在内存中仅仅包括有整型变量x、y、vptr,其他成员所有存在于对象之外。
以下讨论继承体系下的对象模型。以下这个測试例程有点意思:
#include <iostream>
using namespace std;
class A {
public:
int x, y;
};
class B: public A {
};
class C: virtual public A {
};
int main()
{
cout << "class B size = " << sizeof(B) << endl;
cout << "class C size = " << sizeof(C) << endl;
return 0;
}
执行结果:
类C採用了虚继承,内部就多了四字节。这是因为虚继承的特性决定的:在虚拟继承情况下,基类(虚基类)无论在继承链中被派生多少次。永远仅仅会存在一个实例。
和virtual table类似。也存在一个指针表(virtual base class table),表中每一个指针指向一个虚基类地址,在对象中也安插一个指针指向这个表(微软的编译器就採用了这样的做法)。所以类C才会添加了四字节空间。
同一时候。基类(无论是不是虚基类)的数据成员直接被放置于派生类对象中。所以,class C所占空间为8+4=12字节。
假设有例如以下class:
class X {
public:
virtual ~X()
{}
virtual void foo()
{}
private:
int a, b;
};
那么class X的模型应该例如以下所看到的:
环境:
Win7 + VS2013
參考:
《深度探索C++对象模型》 P9-P13.