【问题标题】:C++ Function Pointers to an Object指向对象的 C++ 函数指针
【发布时间】:2012-10-12 10:05:54
【问题描述】:

我不确定这在 C++ 中是否可行。我知道您可以将指向函数或静态成员函数的指针作为参数传递。我想要一个特定对象的函数指针,这样当函数执行时,就在对象上完成。

class MyClass
{
   public:
      MyClass(int id){mId = id;}
      void execute(){cout<<mId<<endl;}
   private:
      int mId;
};


MyClass obj1(1);
MyClass obj2(2);

typedef (Executor)();
Executor ex1 = &obj1::execute();
Executor ex2 = &obj2::execute();

所以当执行 ex1 时,应该打印“1”,如果执行 ex2,则打印“2”。这可能吗?

【问题讨论】:

  • 看看 {std,boost}::function

标签: c++ pointers function-pointers functor member-function-pointers


【解决方案1】:

处理这个问题的工具是函数模板bind

auto ex1 = std::bind(&MyClass::execute, obj1);

您可以将绑定存储在 function 对象中:

std::function<void()> ex1 = std::bind(&MyClass::execute, obj1);

请注意,默认情况下bind 将按值存储obj;您可以使用ref 存储引用:

std::function<void()> ex1 = std::bind(&MyClass::execute, std::ref(obj1));

一个相关的工具是mem_fn,它包装了一个成员函数指针:

void (MyClass::*ex1)() = &MyClass::execute;  // raw member function pointer
ex1(obj1);

auto ex1 = std::mem_fn(&MyClass::execute);   // mem_fn wrapper
ex1(obj)

但是,因为mem_fn 不绑定实例,所以每次调用时都必须提供实例。


为了避免在绑定成员函数时写类名,可以使用宏:

#define BIND_MEM_FN(o,m) \
    std::bind(&std::remove_reference<decltype(o)>::type::m, (o))

宏是必要的,因为您只能从其类型和名称形成成员函数指针,并且您不能将名称(unqualified-id)传递给函数。

【讨论】:

  • std::mem_fn 有一些相关的功能,可能是 OP 感兴趣的,尽管成员函数指针的调用不如绑定的调用那么简洁,因为你必须通过实例作为显式参数。
  • 不知道 C++ STL 中有这样的东西。我想写我自己的。有没有一种方法可以简单地说 obj::execute,而不必传递函数 (&MyClass::execute) 和对象 (obj)?所以基本上是一种自动检测 obj(在 obj::execute 中)不是类并将其解释为对象的方法。
  • 这是针对 C++11 的,在旧版本中没有办法(或者可能是宏)吗?
  • @goocreations - boost::bind()/boost::function() 适用于不支持 c++11 的用户。并不是没有“自动检测”
  • @goocreations 在旧版本的 C++ 中,您可以使用 std::bind1ststd::mem_fun 并将结果存储在 boost::function 中;见boost.org/doc/libs/1_51_0/doc/html/function/…
【解决方案2】:

这是可能的,但不是你描述的方式。 您可以按照上述 cmets 提出的方式进行操作,但更优雅和 C++ 的方式是使用函子。 Functor 基本上是一个重载了运算符() 的对象。 在你的情况下,它可能是这样的:

class MyClass
{
   public:
       MyClass(int id){mId = id;}
       void operator()(){cout<<mId<<endl;}
   private:
   int mId;
};

MyClass obj1(1);
MyClass obj2(2);

obj1();
obj2();

这样你的对象实际上模仿了函数的行为。 在这里你可以阅读更多:http://en.wikipedia.org/wiki/Function_object#In_C_and_C.2B.2B

【讨论】:

  • 我真的不想使用函子。在这种情况下,您总是必须将您的实现放在 () 运算符中。如果你在不同的函数中做,你需要大量的开销代码。
  • 在这种情况下,您可以将成员指针作为您的类数据成员,并在构造函数中将其设置为适当的私有方法。 operator () 只需要调用该数据成员指向的方法。这样,您就可以从两个世界中受益。而且你也没有封装违规。
  • 是的,我就是这个意思。我想要一个尽可能“干净”的解决方案。我想我会和你一起去的想法。谢谢。
【解决方案3】:

成员函数指针:

typedef void (MyClass::*Executor)();
Executor ex1 = &MyClass::execute;
Executor ex2 = &MyClass::execute;

obj1.*ex1();
obj2.*ex2();

编辑:更正了 cmets 中提到的代码。

我犯了一个错误,因为我确实很少使用(成员)函数指针。但不是因为我使用了 std::bind,而是因为我使用了多态性 :)

实际上我不记得我上次使用(成员)函数指针是什么时候了,除了与 OS API 接口。成员函数指针优于非成员函数指针,std::bind/std::function 可能优于成员函数指针,但多态性优于以上所有。

【讨论】:

  • 也许我犯了一个简单的错误,但我得到了以下错误:ISO C++ 禁止使用绑定成员函数的地址来形成指向成员函数的指针。 i> 看来你最好使用std::bindstd::mem_fn
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多