【问题标题】:Get a pointer to object's member function获取指向对象成员函数的指针
【发布时间】:2012-02-10 13:16:54
【问题描述】:

问题来了:

1) 我有这样的课:

class some_class
{
public:
    some_type some_value;
    int some_function(double *a, double *b, int c, int d, void *e);
};

2) 在some_function 内部,我使用some_class 对象中的some_values 来获取结果。

3) 所以,我有一个具体的对象,我想得到一个指向这个对象的指针some_function

有可能吗?我不能使用some_fcn_ptr,因为这个函数的结果取决于对象的具体some_value

如何获得指向对象的some_function 的指针?谢谢。

typedef  int (Some_class::*some_fcn_ptr)(double*, double*, int, int, void*);

【问题讨论】:

标签: c++ function-pointers member


【解决方案1】:

你不能,至少它不会只是一个指向函数的指针。

成员函数对于此类的所有实例都是通用的。所有成员函数都有隐式(第一个)参数this。为了调用特定实例的成员函数,您需要一个指向该成员函数和该实例的指针。

class Some_class
{
public:
    void some_function() {}
};

int main()
{
    typedef void (Some_class::*Some_fnc_ptr)();
    Some_fnc_ptr fnc_ptr = &Some_class::some_function;

    Some_class sc;

    (sc.*fnc_ptr)();

    return 0;
}

更多信息请点击C++ FAQ

使用 Boost 可能看起来像(C++11 提供类似的功能):

#include <boost/bind.hpp>
#include <boost/function.hpp>

boost::function<void(Some_class*)> fnc_ptr = boost::bind(&Some_class::some_function, _1);
Some_class sc;
fnc_ptr(&sc);

C++11 的 lambda:

#include <functional>

Some_class sc;
auto f = [&sc]() { sc.some_function(); };
f();
// or
auto f1 = [](Some_class& sc) { sc.some_function(); };
f1(sc);

【讨论】:

    【解决方案2】:

    不,您不能获得指向 C++ 类方法的指针(除非该方法被声明为静态)。原因是类方法总是有指针this,一个指向类实例的指针。但是如果你通过一个指针来调用方法,那个指针不能封装this指针,那么就没有实例附加,所以这种行为是不合法的。

    【讨论】:

      【解决方案3】:

      您可以编写某种包装器,它可以同时使用函数或方法作为参数。

      我使用以下类来启动函数(在我的一个 SDL 程序中使用过):

      class CallbackFunction {
      public:
          // Constructor, copy constructor and destructor
      
          virtual int execute( SDL_keysym* keysym) const;
          virtual int operator()( SDL_keysym* keysym) const;
      
      protected:
          int( *callback)( SDL_keysym*));
      }
      
      int CallbackFunction::execute( SDL_keysym* keysym) const{
          return callback(keysym);
      }
      
      int CallbackFunction::operator()( SDL_keysym* keysym) const{
          return callback( keysym);
      }
      

      还有这个“方法”的扩展:

      template<class T>
      class CallbackMethod : public CallbackFunction {
      public:
          // Constructor, copy constructor and destructor
          CallbackMethod( T *object, int(T::*callback)( SDL_keysym* keysym));
      
          int execute( SDL_keysym* keysym) const;
          int operator()(SDL_keysym* keysym) const;
      
      protected:
          T *object;
          int(T::*method)( SDL_keysym* keysym);
      };
      
      // Object initialization (constructor)
      template<class T>
      CallbackMethod<T>::CallbackMethod( T *object, int(T::*callback)( SDL_keysym* keysym)):
          CallbackFunction( NULL),object(object),method(callback){
      }
      
      
      // Responsible for executing
      template<class T>
      int CallbackMethod<T>::execute( SDL_keysym* keysym) const {
          return (object->*method)(keysym);
      }
      template<class T>
      int CallbackMethod<T>::operator()( keysym) const {
          return (object->*method)( keysym);
      }
      

      然后将其用作:

      CallbackFunction *callback;
      callback = new CallbackFunction( myFunction);
      callback = new CallbackMethod<A>( instanceOfA, instanceOfA::myMethod);
      callback = new CallbackMethod<B>( instanceOfB, instanceOfB::myMethod);
      ...
      callback( keysym);
      

      我发现宏是这样的:

      CALLBACK(object,method) new CallbackMethod<typeof(*object)>( object, &method)
      

      很实用

      【讨论】:

        【解决方案4】:

        虽然不完全符合您的要求,但如果您可以使用 C++11,以下内容可能仍然适合您的需求(未经测试):

        std::function<int(double*, double*, int, int, void*)>
          some_function_of(Some_class& obj)
        {
          return [&](double* a, double* b, int c, int d, void* e){
            return obj.some_func(a, b, c, d, e); };
        }
        

        【讨论】:

          【解决方案5】:

          我使用了Boost 库。我在我的代码中包含了“boost/bind.hpp”。那么一个名为“fn”的方法可以定义为

          auto fn = boost::bind(ClassName::methodName, classInstanceName, boost::placeholders::_1);

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 2016-02-25
            • 2017-06-29
            • 2022-12-01
            • 1970-01-01
            • 1970-01-01
            • 2020-12-11
            • 2015-03-02
            相关资源
            最近更新 更多