web-dev-qa-db-ja.com

オブジェクトのメンバー関数へのポインターを取得します

問題は次のとおりです。

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_valuesオブジェクトのsome_classを使用して結果を取得します。

3)だから、具体的なオブジェクトがあり、このオブジェクトへのポインターを取得したいsome_function

出来ますか?この関数の結果はオブジェクトの具体的なsome_fcn_ptrに依存するため、some_valueは使用できません。

オブジェクトのsome_functionへのポインターを取得するにはどうすればよいですか?ありがとう。

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

少なくとも、それは関数へのポインタだけではありません。

メンバー関数は、このクラスのすべてのインスタンスに共通です。すべてのメンバー関数には、暗黙の(最初の)パラメーター-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のラバ:

#include <functional>

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

関数またはメソッドの両方をパラメーターとして使用できる、何らかの種類のラッパーを作成できます。

関数を起動するために次のクラスを使用しました(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)

本当に便利

11
Vyktor

いいえ、C++クラスメソッドへのポインタを取得することはできません(メソッドが静的に宣言されていない限り)。その理由は、クラスメソッドには常に、クラスインスタンスへのポインターthisがあるためです。しかし、ポインタを介してメソッドを呼び出す場合、そのポインタはthisポインタをカプセル化できず、インスタンスはアタッチされないため、この動作は無効です。

9
Dov Grobgeld

正確にあなたが要求したものではありませんが、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
celtschk

Boost ライブラリを使用しました。コードに「boost/bind.hpp」を含めました。次に、「fn」という名前のメソッドを次のように定義できます

auto fn = boost :: bind(ClassName :: methodName、classInstanceName、boost :: placeholders :: _ 1);

2
Zoob