【问题标题】:why "this" pointer is not needed when calling virtual function with pointer-to-function?为什么使用指向函数的指针调用虚函数时不需要“this”指针?
【发布时间】:2019-09-11 03:17:20
【问题描述】:

示例:

class A {
public:
    virtual void print() { std::cout << "A::print" << std::endl; }
}

我所知道的: 我们可以使用指向成员函数的指针和一个对象来调用成员函数,这样就可以了

typedef void (A::*fptr)(); //pointer-to-member-function
fptr p = &A::print;
A a;
(a.*p)(); // prints "A::print"

但似乎我可以使用没有对象的函数指针调用 A::print:

typedef void (*fptr)();
long *vptr; // pointer to virtual table
fptr func;  // pointer-to-function

vptr = (long*)(&a);
func = (fptr)( *(long*)(*vptr) ) // pointer to first function in virtual table
func(); // prints "A::print"

我的问题是为什么这行得通?难道我们不需要一个“this”指针来调用虚函数吗?

【问题讨论】:

  • 代码通过不相关类型的指针访问对象来调用未定义的行为。任何事情都有可能发生。
  • 很多东西都可以通过(缺乏)运气来“工作”。

标签: c++ class pointers virtual-functions


【解决方案1】:

在这种情况下它可以工作,因为您的打印函数不访问任何类成员变量,这意味着该函数不需要使用“this”来执行它,这就是它工作的原因。

如果所讨论的方法依赖于任何成员变量,它将会非常失败。

如果您考虑以下方法的 asm:

void func1() { return; }
struct Foo {
  void func2() { return; }
};

在这两种情况下,它们都可以简单地归结为:

  ret

在此处添加打印语句:

void func1() { printf("hello world"); }
struct Foo {
  void func2() { printf("hello world"); }
};

两者的汇编现在看起来像:

  call printf
  ret

因此,虽然您在第二种情况下使用错误的调用约定来调用方法,但在这种情况下并不是什么大问题(因为从未使用过)

【讨论】:

  • 你错过了问题中的重要词汇:虚函数。假设使用了this。
  • @S.M.什么意思?
  • @curioosguy 指向虚拟表的指针放在*this附近,因此用于获取虚拟表。
猜你喜欢
  • 1970-01-01
  • 2014-09-24
  • 1970-01-01
  • 2014-11-25
  • 1970-01-01
  • 1970-01-01
  • 2011-10-08
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多