通过指针访问私有虚拟成员函数

时间:2016-05-04 00:25:03

标签: c++ pointers casting virtual-functions

class foo{
   public:
   int n;
   private:
   virtual void sayHi(){
      cout<<"Hi there!";
   }

};

如何获取sayHi()的地址?

main(){
foo f;
typedef void(*fptr)();
fptr func = reinterpret_cast<fptr>((&f)[0]);
(*func)();
}

上面的代码不起作用。

我知道“f”对象的前8个字节是指向虚拟表的指针,其中包含指向函数的指针,我使用的是64位机器。我基本上试图通过它的指针调用sayHi()而不是直接从f调用它,因为sayHi()无论如何都是私有的!我该怎么做?我分配它吗?

3 个答案:

答案 0 :(得分:2)

你不能简单地拥有一个指向非静态成员函数的指针,并在没有对象的情况下调用它。解释问题最直接的方法是使用pointer-to-member,如下所示:

auto fptr = &foo::sayHi;
foo f;
(f.*fptr)();

现在,您说要在不必通过f的情况下调用它。目前尚不清楚这意味着什么。使用lambda可能足以创建一个可以按你想要的方式运行的可调用

auto func = [] { return foo{}.sayHi(); };
func(); // call

或使用特定对象并通过引用(显示)或按值

捕获它
foo f;
auto func = [&f] { return f.sayHi(); };
func();

答案 1 :(得分:1)

sayHi()是类的非静态方法。您需要使用指向方法的指针而不是原始指针(方法指针的实现是特定于编译器的,因此假设指针到方法的内部布局不可移植)

另外,sayHi() 私有foo,因此main()无法直接访问它。你需要:

  1. sayHi()声明为 public

    class foo
    {
       int n;
    public:
       virtual void sayHi(){
          cout << "Hi there!";
       }
    };
    
    int main()
    {
        typedef void (foo::*fptr)();
        fptr func = &foo::sayHi;
        foo f;
        (f.*func)();
        return 0;
    }
    
  2. main()设为friend的{​​{1}}:

    foo

答案 2 :(得分:0)

嗯,ISO C ++禁止使用绑定成员函数的地址来形成指向成员函数的指针。但是,如果它有帮助,你可以做这样的事情。您可以查看结果here

#include <iostream>
using namespace std;

class foo{
   int n;
public:
   virtual void sayHi(){
      cout<<"Hi there!";
   }
};

typedef void(*fptr)();

int main() {
    auto func = reinterpret_cast<fptr>(&foo::sayHi);
    (*func)();
    return 0;
}