探究C++对象模型 (一)

2014-11-24 02:27:53 · 作者: · 浏览: 6

先引用两句名言作为开场白:

"C++老手分两类:一种人把语言用得烂熟,OO观念也有;另一种人不但如此,还对于台面下的机制,如编译器合成的default constructor、object的内存布局等有莫大的兴趣。"

"了解C++对象模型,绝对有助于你在语言本身以及面向对象观念两方面的层次提升。"

首先以Point类为例


再看下对象模型


这个模型好像跟我们以往的认知有些不一致呀,vtable首四个字节怎么是type_info的指针?type_info是RTTI的内容,是编译器用来进行类型识别的,它到底存不存在呢?

用代码测试一下


[cpp]
// VirtualTable.cpp : Defines the entry point for the console application.
//

#include "stdafx.h"
#include
using namespace std;

class Base {
private:
int x;

public:
virtual void f() { cout<<"Base::f"< virtual void g() { cout<<"Base::g"< virtual void h() { cout<<"Base::h"< Base(){x = 2;};


};




class Derive : public Base{
private:
int y;
public:
virtual void f1() { cout<<"Derive::f1"< virtual void g1() { cout<<"Derive::g1"< virtual void h1() { cout<<"Derive::h1"< Derive(){y = 3;};

};

int main(int argc, char* argv[])
{

typedef void(*Fun)(void);

Base b;
Derive d;

Fun pFun = NULL;

cout <<"虚函数表入口指针地址"<< (int*)(&b) << endl;
cout <<"虚函数表的地址"<< (int*)*(int*)(&b) << endl;

cout <<"Base — 第一个数据成员"<< *((int*)(&b)+1) << endl;
cout <<"Derive — 第一个数据成员"<< *((int*)(&d)+1) << endl;
cout <<"Derive — 第二个数据成员"<< *((int*)(&d)+2) << endl;

// Invoke the first virtual function
pFun = (Fun)*((int*)*(int*)(&b));

pFun = (Fun)*((int*)*(int*)(&b)+0); // Base::f()
pFun();
pFun = (Fun)*((int*)*(int*)(&b)+1); // Base::g()
pFun();
pFun = (Fun)*((int*)*(int*)(&b)+2); // Base::h()
pFun();
//以上代码说明 虚函数表位于对象内存的最开始的位置
pFun = (Fun)*((int*)*(int*)(&d)+0); // Base::f()
pFun();
pFun = (Fun)*((int*)*(int*)(&d)+1); // Base::g()
pFun();
pFun = (Fun)*((int*)*(int*)(&d)+2); // Base::h()
pFun();
pFun = (Fun)*((int*)*(int*)(&d)+3); // Derive::f1()
pFun();
pFun = (Fun)*((int*)*(int*)(&d)+4); // Derive::g1()
pFun();
pFun = (Fun)*((int*)*(int*)(&d)+5); // Derive::h1()
pFun();


system("pause");
return 0;
}

// VirtualTable.cpp : Defines the entry point for the console application.
//

#include "stdafx.h"
#include
using namespace std;

class Base {
private:
int x;

public:
virtual void f() { cout<<"Base::f"< virtual void g() { cout<<"Base::g"< virtual void h() { cout<<"Base::h"< Base(){x = 2;};


};


class Derive : public Base{
private:
int y;
public:
virtual void f1() { cout<<"Derive::f1"< virtual void g1() { cout<<"Derive::g1"< virtual void h1() { cout<<"Derive::h1"< Derive(){y = 3;};

};

int main(int argc, char* argv[])
{

typedef void(*Fun)(void);

Base b;
Derive d;

Fun pFun = NULL;

cout <<"虚函数表入口指针地址"<< (int*)(&b) << endl;
cout <<"虚函数表的地址"<< (int*)*(int*)(&b) << endl;

cout <<"Base — 第一个数据成员"<< *((int*)(&b)+1) << endl;
cout <<"Derive — 第一个数据成员"<< *((int*)(&d)+1) << endl;
cout <<"Derive — 第二个数据成员"<< *((int*)(&d)+2) << endl;

// Invoke the first virtual function
pFun = (Fun)*((int*)*(int*)(&b));

pFun = (Fun)*((int*)*(int*)(&b)+0); // Base::f()
pFun();
pFun = (Fun)*((int*)*(int*)(&b)+1); // Base::g()
pFun();
pFun = (Fun)*((int*)*(int*)(&b)+2); // Base::h()
pFun();
//以上代码说明 虚函数表位于对象内存的最开始的位置
pFun = (Fun)*((int*)*(int*)(&d)+0); // Base::f()
pFun();
pFun = (Fun)*((int*)*(int*)(&d)+1); // Base::g()
pFun();
pFun = (Fun)*((int*)*(int*)(&d)+2); // Base::h()
pFun();
pFun = (Fun)*((int*)*(int*)(&d)+3); // Derive::f1()
pFun();
pFun = (Fun)*((int*)*(int*)(&d)+4); // Derive::g1()
pFun();
pFun = (Fun)*((int*)*(int*)(&d)+5); // Derive::h1()
pFun();


system("pause");
return 0;
}

没有看到 type_info的影子,这也正是我们以往心目中Vtable的内存位置

这是神马情况?上文的图在胡扯?

再看下面代码,

测试代码(vc8.0执行正常,vc6会报错,可能对象模型不一致)

[cpp]
#include "iostream"
#include "string"


using namespace std;
class Aclass
{
public:
int a;
virtual void set