Get a pointer to object ' s member function

Oto problem:

1) mam taką klasę:

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

2) wewnątrz some_function, używam some_values z some_class obiektu, aby uzyskać wynik.

3) więc mam konkretny obiekt i chcę uzyskać wskaźnik do tego obiektu some_function.

Czy to możliwe? Nie mogę użyć some_fcn_ptr, ponieważ wynik tej funkcji zależy od konkretnego some_value obiektu.

Jak mogę uzyskać wskaźnik do some_function obiektu? Dzięki.

typedef  int (Some_class::*some_fcn_ptr)(double*, double*, int, int, void*);
Author: Willem van Ketwich, 2012-01-14

5 answers

Nie możesz, przynajmniej nie będzie to tylko wskaźnik do funkcji.

Funkcje Członkowskie są wspólne dla wszystkich instancji tej klasy. Wszystkie funkcje Członkowskie mają niejawny (pierwszy) parametr this. Aby wywołać funkcję członka dla konkretnej instancji, potrzebujesz wskaźnika do tej funkcji członka i tej instancji.

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;
}

Więcej informacji tutaj w C++ FAQ

Using Boost this can look like (C++11 provides similar funkcjonalność): {]}

#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);

Lambdy 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);
 36
Author: Andriy Tylychko,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2020-01-18 05:03:54

Możesz napisać jakiś rodzaj wrappera, który może używać zarówno funkcji, jak i metody jako parametru.

Użyłem następujących klas do uruchamiania funkcji (była używana w jednym moim programie 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);
}

I to rozszerzenie dla "metod":

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);
}

A następnie użyj go jako:

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

Znalazłem makro Tak:

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

Naprawdę przydatne

 11
Author: Vyktor,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-01-14 22:48:34

Nie, Nie można uzyskać wskaźnika do metody klasy C++ (chyba że metoda jest zadeklarowana jako statyczna). Powodem jest to, że metoda klasowa zawsze ma wskaźnik this, wskaźnik do instancji klasy. Ale gdyby wywołać metodę za pomocą wskaźnika, Wskaźnik ten nie mógłby hermetyzować wskaźnika this, a wtedy nie byłaby dołączona Żadna instancja, a zatem takie zachowanie nie jest legalne.

 10
Author: Dov Grobgeld,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-02-27 18:14:19

Chociaż nie dokładnie to, o co prosiłeś, jeśli możesz użyć C++11, to jednak poniższe mogą odpowiadać Twoim potrzebom (niesprawdzone):

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
Author: celtschk,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-01-14 22:25:30

Użyłem biblioteki Boost . I included " boost/bind.hpp " w moim kodzie. Następnie metodę o nazwie "fn" można zdefiniować jako

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

 2
Author: Zoob,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-03-04 00:01:28