C++:30 ---C++类成员,成员函数的内存布局
原创
©著作权归作者所有:来自51CTO博客作者游戏开发司机的原创作品,请联系作者获取转载授权,否则将追究法律责任
前面两篇文章我相信大家反复读了之后对这节不陌生了:
首先来看代码:
class Demo
{
public:
//静态成员变量
static const int sx = 0;
//静态函数
static void SF1()
{
}
public:
//成员变量
int x;
public:
//成员函数
void F1()
{
cout << "I'm from Demo::F1()" << endl;
}
void F2()
{
cout << "I'm from Demo::F1()" << endl;
}
virtual void F3()
{
cout << "virtual F3()" << endl;
}
public:
//构造函数,C++语法不允许获取构造函数和析构函数地址,要分析其地址,只能查看生产的汇编代码了。
Demo()
{
}
//析构函数
~Demo()
{
}
};
typedef void (Demo::*Func)();
typedef void(*func)();
union
{
Func f;
void *addr;
}ut;
int main(int argc, char** argv)
{
int i = 0;
cout << "main()函数的地址是 :" << std::hex << std::showbase << main << endl;
ut.f = &Demo::F1;
cout << "成员函数F1()的地址是 :" << std::hex << std::showbase << ut.addr << endl;
ut.f = &Demo::F2;
cout << "成员函数F2()的地址是 :" << std::hex << std::showbase << ut.addr << endl;
cout << "静态成员函数SF1()的地址是:" << std::hex << std::showbase << Demo::SF1 << endl;
cout << "静态成员变量sx的地址是 :" << std::hex << std::showbase << &Demo::sx << endl;
cout << "Demo类型实例的大小 :" << sizeof(Demo) << endl;
Demo* pObj = new Demo();
cout << "对象指针变量的地址是 :" << std::hex << std::showbase << &pObj << endl;
cout << "新建对象的地址是 :" << std::hex << std::showbase << pObj << endl;
cout << "成员变量的地址是 :" << std::hex << std::showbase << &pObj->x << endl;
cout << "虚函数表的入口地址 :" << std::hex << std::showbase << pObj << endl;
cout << "虚函数表F3的地址:"<< (int*)*(int*)(pObj) <<endl;
return 0;
}
这段代码的运行结果如下:
这里要指出的是大家可以看到静态成员函数和静态成员变量sx的地址都是0x00007FF开头的,实际上他们都在全局数据区域存储(全局变量,静态变量),如果你有耐心,可以断点查看下栈空间内的局部变量i的地址:
你会发现栈空间的地址和全局数据区的地址都不一样,这样你也理解了虚函数表的空间。
这样看这张图,你就知道哪些变量在哪里存储了。
如果我们修改对象构造的方式,通过在栈上构造一个对象,
int main(int argc, char** argv)
{
Demo pObj;
cout << "新建对象的地址是 :" << std::hex << std::showbase << &pObj << endl;
cout << "成员变量的地址是 :" << std::hex << std::showbase << &pObj.x << endl;
cout << "静态成员函数SF1()的地址是:" << std::hex << std::showbase << Demo::SF1 << endl;
cout << "静态成员变量sx的地址是 :" << std::hex << std::showbase << &Demo::sx << endl;
ut.f = &Demo::F1;
cout << "成员函数F1()的地址是 :" << std::hex << std::showbase << ut.addr << endl;
ut.f = &Demo::F2;
cout << "成员函数F2()的地址是 :" << std::hex << std::showbase << ut.addr << endl;
cout << "虚函数表的入口地址 :" << std::hex << std::showbase << &pObj << endl;
cout << "虚函数表F3的地址:"<< (int*)*(int*)(&pObj) <<endl;
return 0;
}
我想你现在根据刚才打印的成员变量,成员函数,虚函数表地址已经可以自己画出类成员的内存布局了。