设为首页 加入收藏

TOP

ATL布幔下的秘密之内部工作方式(三)
2012-11-04 15:06:29 来源: 作者: 【 】 浏览:913
Tags:ATL 秘密 内部 工作 方式
  程序9.

#include <iostream>
using namespace std;

class Class {
virtual void fun() { cout << "Class::fun" << endl; }
};

int main() {
Class objClass;

cout << "Address of virtual pointer " << (int*)(&objClass+0) << endl;
cout << "Value at virtual pointer " << (int*)*(int*)(&objClass+0) << endl;
return 0;
}

  程序的输出为:

Address of virtual pointer 0012FF7C
Value at virtual pointer 0046C060

  虚函表数指针存储了一个虚函数表的地址。并且,虚函数表存储了类中所有虚函数的地址。换句话说,虚函数表是一个数组,这个数组的元素为虚函数指针的地址。让我们看看下面这个程序来考虑吧。

  程序10.

#include <iostream>
using namespace std;

class Class {
virtual void fun() { cout << "Class::fun" << endl; }
};

typedef void (*Fun)(void);

int main() {
Class objClass;

cout << "Address of virtual pointer " << (int*)(&objClass+0) << endl;
cout << "Value at virtual pointer i.e. Address of virtual table "
<< (int*)*(int*)(&objClass+0) << endl;
cout << "Value at first entry of virtual table "
<< (int*)*(int*)*(int*)(&objClass+0) << endl;
cout << endl << "Executing virtual function" << endl << endl;
Fun pFun = (Fun)*(int*)*(int*)(&objClass+0);
pFun();
return 0;
}

  这个程序中有一些使用了类型转换的间接调用,其中最重要的一行是:

Fun pFun = (Fun)*(int*)*(int*)(&objClass+0);

  在这里,Fun为一个由typedef定义的函数指针类型:

typedef void (*Fun)(void);

  让我们来剖析一下这个冗长的间接调用。(int*)(&objClass+0)给出了虚函数表指针的地址,这个虚函数表指针是类的第一个入口,我们将它转换为了int*。要获得这个地址的值,我们需要使用间接调用运算符(也就是*),然后将它再次转换为int*,也就是(int*)*(int*)(&objClass+0)。这就会给出虚函数表的第一个入口。要获得这个位置的值,也就是获得类中第一个虚函数的地址,我们需要再次使用间接调用运算符,并将其转换为合适的函数指针类型,所以 Fun pFun = (Fun)*(int*)*(int*)(&objClass+0);
就表示从虚函数表的第一个入口获得值,作Fun的类型转换,并将其存入pFun之中。


  那么,当类中含有多于一个的虚函数,又会怎么样呢?现在我们希望存取虚函数表中的第二个虚函数,请看下面的程序:

  程序11.

#include <iostream>
using namespace std;

class Class {
virtual void f() { cout << "Class::f" << endl; }
virtual void g() { cout << "Class::g" << endl; }
};

int main() {
Class objClass;

cout << "Address of virtual pointer " << (int*)(&objClass+0) << endl;
cout << "Value at virtual pointer i.e. Address of virtual table "
<< (int*)*(int*)(&objClass+0) << endl;

cout << endl << "Information about VTable" << endl << endl;
cout << "Value at 1st entry of VTable "
<< (int*)*((int*)*(int*)(&objClass+0)+0) << endl;
cout << "Value at 2nd entry of VTable "
<< (int*)*((int*)*(int*)(&objClass+0)+1) << endl;

return 0;
}

  程序的输出为:

Address of virtual pointer 0012FF7C
Value at virtual pointer i.e. Address of virtual table 0046C0EC

Information about VTable

Value at 1st entry of VTable 0040100A
Value at 2nd entry of VTable 0040129E


  那么,有一个问题很自然地出现了——编译器是如何知道虚函数表的长度的呢?答案是:虚函数表的最后一个入口为NULL。你可以把程序改一改来考虑这个问题。

首页 上一页 1 2 3 4 5 下一页 尾页 3/5/5
】【打印繁体】【投稿】【收藏】 【推荐】【举报】【评论】 【关闭】 【返回顶部
分享到: 
上一篇ATL布幔下的秘密之虚函数背后的东.. 下一篇InstallShield制作带ODBC的安装软..

评论

帐  号: 密码: (新用户注册)
验 证 码:
表  情:
内  容: