对象虚函数的获取方法

#include <iostream>
#include <unistd>

using namespace std;

class TestClass
{
public:
  virtual void print1()
  {
    cout << "print1" << endl;
  }

  virtual void print2()
  {
    cout << "print3" << endl;
  }

  void print3()
  {
    cout << "print3" << endl;
  }
};

 

typedef void (*FUNC) ();

 

int main(int argc __attribute__((unused)), char *argv[] __attribute__((unused)))
{
  TestClass test;
  FUNC fun = (FUNC) (int *) * ((int *) * (int *) * (&test) + 0);   // 第一个int *即是vptr, 取得virtual table首地址, 第二int *解引用
  fun();                                                           // 获得virtual table第一个内容, 即函数所在的位置, 第三个int *
  fun = (FUNC) (int *) * ((int *) * (int *) * (&test) + 1);        // 解引用获得第一个虚函数地址
  fun();  // print2
  fun = (FUNC)) (int *) * ((int *) * (int *) * (&test) + 2);
  fun();  // coredump 非print3
  exit(EXIT_SUCCESS);
}

### 获取对象虚函数表(vtable)的方法 在 C++ 中,虚函数表(vtable)是编译器实现运行时多态的核心机制之一。每个含有虚函数的类在编译时都会生成一个虚函数表,其中存储了该类所有虚函数的地址。对象中包含一个指向其类虚函数表的指针(vptr),该指针通常位于对象内存布局的最开始位置[^2]。 #### 通过指针访问虚函数表 可以通过对对象内存布局的分析,手动访问虚函数表。具体方法是将对象的地址转换为指针,然后通过指针访问对象内存起始位置的指针(即 vptr),再通过该指针访问虚函数表。 以下是一个示例代码,展示如何访问虚函数表并获取虚函数地址: ```cpp #include <iostream> class Base { public: virtual void func1() { std::cout << "Base::func1" << std::endl; } virtual void func2() { std::cout << "Base::func2" << std::endl; } virtual ~Base() {} }; int main() { Base obj; // 获取对象虚函数表指针 void** vptr = *(void***)(&obj); // 获取虚函数地址 void (*func1Ptr)() = (void(*)())(vptr[0]); void (*func2Ptr)() = (void(*)())(vptr[1]); std::cout << "Calling func1 through vtable:" << std::endl; func1Ptr(); // 调用 Base::func1 std::cout << "Calling func2 through vtable:" << std::endl; func2Ptr(); // 调用 Base::func2 return 0; } ``` 上述代码中,`*(void***)(&obj)` 获取对象 `obj` 的虚函数表指针,然后通过索引访问虚函数表中的函数指针。`vptr[0]` 和 `vptr[1]` 分别对应 `Base` 类中的 `func1` 和 `func2` 函数地址[^4]。 #### 注意事项 - 这种方式依赖于编译器的具体实现,不同编译器可能有不同的内存布局。 - 直接操作虚函数表指针是不安全的,通常不建议在生产代码中使用。 - 该方法主要用于调试、学习或底层开发,如实现某些特定的运行时机制。 #### 多继承中的虚函数表访问 在多继承的情况下,每个基类都有自己的虚函数表,因此派生类对象中会包含多个虚函数表指针。访问这些虚函数表需要根据编译器的内存布局进行调整。例如,在 GCC 编译器中,派生类对象的内存布局会按照继承顺序依次包含各个基类的虚函数表指针[^2]。 ###
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值