了解c ++中的指针指针以获取函数调用

时间:2019-01-02 17:28:24

标签: c++ pointers

我对以下代码中的指针语句感到困惑。 指针的目的是从虚拟表访问虚拟函数。这是文章的链接。 http://kaisar-haque.blogspot.com/2008/07/c-accessing-virtual-table.html

1 #include <iostream>
  2
  3 using namespace std;
  4
  5 //a simple class
  6 class X
  7 {
  8 public:
  9  //fn is a simple virtual function
 10  virtual void fn()
 11  {
 12   cout << "n = " << n << endl;
 13  }
 14
 15  //a member variable
 16  int n;
 17 };
 18
 19 int main()
 20 {
 21  //create an object (obj) of class X
 22  X *obj = new X();
 23  obj->n = 10;
 24
 25  //get the virtual table pointer of object obj
 26  int* vptr =  *(int**)obj;
 27
 28  // we shall call the function fn, but first the following assembly code
 29  //  is required to make obj as 'this' pointer as we shall call
 30  //  function fn() directly from the virtual table
 31  __asm
 32  {
 33   mov ecx, obj
 34  }
 35
 36  //function fn is the first entry of the virtual table, so it's vptr[0]
 37  ( (void (*)()) vptr[0] )();
 38
 39  //the above is the same as the following
 40  //obj->fn();
 41
 42  return 0;
 43 }
 44 

所以,我想知道如何理解第26行。

1 个答案:

答案 0 :(得分:1)

代码试图基于c ++中虚拟功能的某些可能实现进行黑客入侵。 vtable的实现未在标准中定义,并且不同的编译器可能会有所不同。也可能需要进行优化。

本文已有10年历史,并假设有一个特殊的vtable实现,在那之前是很常见的:

  1. 对象中的第一个隐藏指针(在对象起始地址处)指向函数数组。

  2. 函数数组表示该类中的所有虚函数。    只有编译器知道它们在数组中的放置顺序。通常使用声明顺序。

假设上述实现,“ obj”的地址实际上是指向虚拟表的指针的地址。该示例使用假设函数指针可以表示为int。对于64位OS和许多其他操作系统,这根本不是事实。 int *vptr是指向此数组的指针。因此, obj 指向一个指向int (int**)数组的指针。因此,*(int**)obj是指向数组本身的指针。

然后,该示例又进行了另一个不安全的转换,即从vptr [0](为'int')到指向该函数的指针。

因此,结果是,您遇到了一系列不确定的或不安全的行为,这些行为可能适用于特定编译器的特定版本的特定实现(可能与本文相同,已有10年历史了)。

请勿使用!!!