科技行者

行者学院 转型私董会 科技行者专题报道 网红大战科技行者

知识库

知识库 安全导航

至顶网软件频道基础软件ATL布幔下的秘密之虚函数背后的东西

ATL布幔下的秘密之虚函数背后的东西

  • 扫一扫
    分享文章到微信

  • 扫一扫
    关注官方公众号
    至顶头条

在本系列的教程中,我要讨论一些ATL的内部工作方式以及它所使用的技术,这是本系列的第二篇文章。

作者:李马编译 来源:VCKBASE 2007年10月19日

关键字:

  • 评论
  • 分享微博
  • 分享邮件
程序24.

#include <iostream>
using namespace std;

class Base {
 public:
 Base() {
  cout << "In Base" << endl;
  cout << "Virtual Pointer = " << (int*)this << endl;
  cout << "Address of Vtable = " << (int*)*(int*)this << endl;
  cout << "Value at Vtable = " << (int*)*(int*)*(int*)this << endl;
  cout << endl;
 }
 virtual void f1() { cout << "Base::f1" << endl; }
};

class Drive : public Base {
 public:
 Drive() {
  cout << "In Drive" << endl;
  cout << "Virtual Pointer = " << (int*)this << endl;
  cout << "Address of Vtable = " << (int*)*(int*)this << endl;
  cout << "Value at Vtable = " << (int*)*(int*)*(int*)this << endl;
  cout << endl;
 }
 virtual void f1() { cout << "Drive::f2" << endl; }
};

class MostDrive : public Drive {
 public:
 MostDrive() {
  cout << "In MostDrive" << endl;
  cout << "Virtual Pointer = " << (int*)this << endl;
  cout << "Address of Vtable = " << (int*)*(int*)this << endl;
  cout << "Value at Vtable = " << (int*)*(int*)*(int*)this << endl;
  cout << endl;
 }
 virtual void f1() { cout << "MostDrive::f2" << endl; }
};

int main() {
 MostDrive d;
 return 0;
}

  程序的输出为:

In Base
Virtual Pointer = 0012FF7C
Address of Vtable = 0046C0A0
Value at Vtable = 004010F5

In Drive
Virtual Pointer = 0012FF7C
Address of Vtable = 0046C090
Value at Vtable = 00401221

In MostDrive
Virtual Pointer = 0012FF7C
Address of Vtable = 0046C080
Value at Vtable = 00401186

  这个程序示范了虚函数表指针在每个类的构造函数中的初始化过程。这样看来,每个类构造函数中虚函数表的地址是不同的,main函数则使用了继承链中的最底部的派生类来创建对象。

  现在你可以看看虚函数表中各个类的构造函数的位置了,你可以将虚函数表中的第一个入口存入一个函数指针,并尝试运行它。

  程序25.

#include <iostream>
using namespace std;

typedef void(*Fun)();

class Base {
 public:
 Base() {
  cout << "In Base" << endl;
  cout << "Virtual Pointer = " << (int*)this << endl;
  cout << "Address of Vtable = " << (int*)*(int*)this << endl;
  cout << "Value at Vtable = " << (int*)*(int*)*(int*)this << endl;

  Fun pFun = (Fun)*(int*)*(int*)this;
  pFun();
  cout << endl;
 }
 virtual void f1() { cout << "Base::f1" << endl; }
};

class Drive : public Base {
 public:
 Drive() {
  cout << "In Drive" << endl;
  cout << "Virtual Pointer = " << (int*)this << endl;
  cout << "Address of Vtable = " << (int*)*(int*)this << endl;
  cout << "Value at Vtable = " << (int*)*(int*)*(int*)this << endl;

  Fun pFun = (Fun)*(int*)*(int*)this;
  pFun();
  cout << endl;
 }
 virtual void f1() { cout << "Drive::f1" << endl; }
};

class MostDrive : public Drive {
 public:
 MostDrive() {
  cout << "In MostDrive" << endl;
  cout << "Virtual Pointer = " << (int*)this << endl;
  cout << "Address of Vtable = " << (int*)*(int*)this << endl;
  cout << "Value at Vtable = " << (int*)*(int*)*(int*)this << endl;

  Fun pFun = (Fun)*(int*)*(int*)this;
  pFun();
  cout << endl;
 }
 virtual void f1() { cout << "MostDrive::f1" << endl; }
};

int main() {
 MostDrive d;
 return 0;
}

  程序的输出为:

In Base
Virtual Pointer = 0012FF7C
Address of Vtable = 0046C098
Value at Vtable = 004010F5
Base::f1

In Drive
Virtual Pointer = 0012FF7C
Address of Vtable = 0046C088
Value at Vtable = 00401221
Drive::f1

In MostDrive
Virtual Pointer = 0012FF7C
Address of Vtable = 0046C078
Value at Vtable = 00401186
MostDrive::f1

  这个程序示范了每个类中的构造函数是如何用自己的虚函数来填充虚函数表中的各入口的。所以,Base类使用Base类的虚函数地址来填充自己的虚函数表,当Drive类的构造函数执行它的时候会创建另外一个虚函数表,并存储自己的虚函数地址。
    • 评论
    • 分享微博
    • 分享邮件
    邮件订阅

    如果您非常迫切的想了解IT领域最新产品与技术信息,那么订阅至顶网技术邮件将是您的最佳途径之一。

    重磅专题
    往期文章
    最新文章