先引用两句名言作为开场白:
"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"<
};
class Derive : public Base{
private:
int y;
public:
virtual void f1() { cout<<"Derive::f1"<
};
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"<
};
class Derive : public Base{
private:
int y;
public:
virtual void f1() { cout<<"Derive::f1"<
};
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