虚表思考-再探虚表布局

 


思考类的布局,以前一直以为 一个类可能有多个虚表。
今天下午特别的写程序测试下。

 

程序参考了:陈皓博客的

结论是:无论一个类怎么继承来的,他的虚表只有一个!//

 

感觉:注意:虚表的理解,至少2个层次,动静结合
静,要知道 类的布局
动,要知道函数 动态绑定

 

 

 

#include "stdafx.h"

 

 

#include <iostream>

 

using namespace std;

 

 

 

class Base{

 

 

//private:

 

public:

 

  //virtual  ~Base()

 

  //{cout<<"i am in dtor"<<endl;//只有显示申明后才object中显示

  //}

 

 

public:

 

  virtual void f() { cout << "Base::f" << endl; }

 

  virtual void g() { cout << "Base::g" << endl; }

 

  void h() { cout << "unvirtual Base::h" << endl; }

 

 

};

 

 

class derived:public Base{

 

 

 

public:

 

  //virtual void f() { cout << "derived::f" << endl; } //使用父亲的

  virtual void g() { cout << "derived::g" << endl; }

 

 

  void h() { cout << "unvirtual derived::h" << endl; }

 

  virtual void i() { cout << "his own derived::i" << endl; }

 

 

};

 

 

void test_Main(){

 

  typedef void(*Fun)(void);

 

 

  Base b;

 

 

  Fun pFun = NULL;

 

 

  cout << "vtbl address" << (int*)(&b) << endl;

 

  cout << "vtbl 1st function" << (int*)*(int*)(&b) << endl;

 

  cout<<"打印转换过程"<<&b<<" "<<(int*)(&b)<<" "<<*(int*)(&b)<<" "<<(int*)*(int*)(&b)<<endl;

 

  cout<<"在此打印地址+ "<<&b+1<<" "<<(int*)(&b)+1<<" "<<*(int*)(&b)+1<<" "<<(int*)*(int*)(&b) +1<<endl;

 

 

 

  // Invoke the first virtual function

 

  pFun = (Fun)*((int*)*(int*)(&b));

 

 

 

  ( (Fun)*((int*)*(int*)(&b)) )();

 

     //奇怪的bug:显示的dtor,就要这里报错//这里就注释了base dtor

 

     //( (Fun)*((int*)*(&b)) )();//无法从Base转换为int *

 

     //( (Fun)*(*(int*)(&b)) )();//error C2100: 非法的间接寻址

     //( *((int*)*(int*)(&b)) )(); //error C2064: 项不会计算为接受0 个参数的函数

                   //不强制转换报错!不知道返回类型,不知道参数。所以转换

 

 

 

  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() //不存在vtbl..用户可以自己调用析构?

  //pFun();

 

 

 

 

  derived d;

 

 

 

      (  (Fun)* (int *)*(int *)(&d) ) ();//调用保留的函数

         // (Fun)* (int *)*(int *)(&d)  (); //结合性会计算为接受0 个参数的函数

    ( (Fun)* ( (int *)*(int *)(&d) +1) )();//调用重写

 

    ( (Fun)* ( (int *)*(int *)(&d) +2) )(); //调用新的虚函数

 

 

 

}

 

//调试方法:就是调用

test_Main()

 

后面试我的测试截图:

 

 

image

 

 

 补上虚表转换图示:

 

 

 

 

posted @ 2012-08-02 17:41  os66  阅读(306)  评论(1编辑  收藏  举报