您的位置:首页 > 其它

虚函数杂记

2015-09-15 00:22 239 查看
  在之前的一篇博文C++中的虚函数表是什么时期建立的?,我们知道虚函数表在编译期间就生成了,但是它被放置在可执行文件的什么地方呢?

虚函数表放置位置

  为了解决这个问题,我们先来看下C++对象模型。

  在C++对象模型中,nonstatic data members被配置于每一个class object中,static data members则被存放在个别的class object之外。static和nonstatic function members也被放在个别的class object之外。virtual functions则以两个步骤支持之:

  1. 每一个class产生出一堆指向virtual functions的指针,放在表格之中。这个表格被称为virtual table (vtbl)。

  2. 每一个class object被安插一个指针,指向相关的virtual table。通常这个指针被称为vptr。vptr的设定(setting)和重置(resetting)都由每一个class的constructor、destructor和copy assignment运算符自动完成。每一个class所关联的type_info object(用以支持runtime type identification, RTTI)也经由virtual talbe被指出来,通常放在表格的第一个slot。

  我们以一个程序来说明C++对象模型:

class Point
{
public:
Point(float xval);
virtual ~Point();

float x() const;
static int PointCount();

protected:
virtual ostream& print(ostream &os) const;
float x;
static int _point_count;
}


  其对应的对象模型为:

  

#include <iostream>
using namespace std;

class Base1 {
public:
virtual void f() { cout << "Base1::f" << endl; }
virtual void g() { cout << "Base1::g" << endl; }
virtual void h() { cout << "Base1::h" << endl; }

};

class Base2 {
public:
virtual void f() { cout << "Base2::f" << endl; }
virtual void g() { cout << "Base2::g" << endl; }
virtual void h() { cout << "Base2::h" << endl; }
};

class Base3 {
public:
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:
virtual void f() { cout << "Derive::f" << endl; }
virtual void g1() { cout << "Derive::g1" << endl; }
};

typedef void(*Fun)(void);

int main()
{
Fun pFun = NULL;

Derive d;
int** pVtab = (int**)&d;

//Base1's vtable
//pFun = (Fun)*((int*)*(int*)((int*)&d+0)+0);
pFun = (Fun)pVtab[0][0];
pFun();

//pFun = (Fun)*((int*)*(int*)((int*)&d+0)+1);
pFun = (Fun)pVtab[0][1];
pFun();

//pFun = (Fun)*((int*)*(int*)((int*)&d+0)+2);
pFun = (Fun)pVtab[0][2];
pFun();

//Derive's vtable
//pFun = (Fun)*((int*)*(int*)((int*)&d+0)+3);
pFun = (Fun)pVtab[0][3];
pFun();

//The tail of the vtable
pFun = (Fun)pVtab[0][4];
cout << pFun << endl;

//Base2's vtable
//pFun = (Fun)*((int*)*(int*)((int*)&d+1)+0);
pFun = (Fun)pVtab[1][0];
pFun();

//pFun = (Fun)*((int*)*(int*)((int*)&d+1)+1);
pFun = (Fun)pVtab[1][1];
pFun();

pFun = (Fun)pVtab[1][2];
pFun();

//The tail of the vtable
pFun = (Fun)pVtab[1][3];
cout << pFun << endl;

//Base3's vtable
//pFun = (Fun)*((int*)*(int*)((int*)&d+1)+0);
pFun = (Fun)pVtab[2][0];
pFun();

//pFun = (Fun)*((int*)*(int*)((int*)&d+1)+1);
pFun = (Fun)pVtab[2][1];
pFun();

pFun = (Fun)pVtab[2][2];
pFun();

//The tail of the vtable
pFun = (Fun)pVtab[2][3];
cout << pFun << endl;

return 0;
}


View Code

参考资料

  《深入探索C++对象模型》
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: