5

Voglio memorizzare un puntatore a un oggetto e un puntatore al suo metodo di firma nota. Se conosco la classe, allora questo puntatore avere tipo:C++ memorizza un puntatore a una funzione membro di classe sconosciuta

int (MyClass::*pt2Member)(float, char, char) 

Ma come faccio a memorizzare il puntatore se non so il tipo?

voglio fare qualcosa di simile:

myObject.callThisFuncLater(&otherObject, &otherObject::method) 

Come posso memorizzare un puntatore al metodo di method in myObject e chiamare in un secondo momento?

+1

Sei miliardi di duplicati. – Puppy

+1

@DeadMG: mostra loro :) il mio contatore è bloccato a 2.178.933 domande totali – sehe

+0

Quali argomenti utilizzerai quando lo chiami in un secondo momento? – Beta

risposta

2

È possibile utilizzare boost::function (e boost::bind) per memorizzare un pezzo di codice da chiamare in seguito.

class MyClass 
{ 
public: 
    void callThisFuncLater(boost::function< int (float, char, char) > callBack); 
}; 
... 
myObject.callThisFuncLater(boost::bind(&otherObject::method, &otherObject)); 
+1

Potrei sbagliarmi, ma dovrei cambiare '& otherObject' e' & otherObject :: method'? – Vortico

+0

@Vortico Hai ragione, mi dispiace. Ho intenzione di modificare il mio post per correggerlo. –

5

Il modo più semplice per farlo se si ha accesso alle estensioni della libreria STL TR1 (disponibili su GCC e Visual Studio 2008 e poi è. Std :: funzione e std :: bind possono essere utilizzati per avvolgere un . invocazione che può essere chiamato in seguito Questa funzionalità è disponibile in funzione boost e spinta si legano anche:.

#include <functional> 

class MyClass { 
public: 
    template<typename T> callThisFuncLater(T& otherObject, 
             int(T::*)(float, char, char) method) { 
    return storedInvocation_ = std::bind(otherObject, 
            method, 
            std::placeholders::_1, // float 
            std::placeholders::_2, // char 
            std::placeholders::_3); // char 
    } 

    int callStoredInvocation(float a, char b, char c) { 
    storedInvocation_(a, b, c); 
    } 

private: 
    std::function<int(float, char, char)> storedInvocation_; 
}; 
-1

Personalmente vorrei scegliere un disegno diverso Semplicemente perché puntatori a funzione membro in C++ non sono facili da lavorare con Personalmente ho. sceglierei di utilizzare le interfacce e di ereditarle e analizzarle lungo queste:

Uno dei problemi con i puntatori di funzioni membro è che vengono implementati in modo diverso su diversi compilatori. Se usi i compilatori Borland/Embarcardero e vuoi limitarti a questo, puoi usare la parola chiave __closure, ma molto probabilmente non lo sei, e quindi dovresti usare qualche altra implementazione specifica del compilatore, o usare uno dei boost classi di aiuto come la funzione.

Ma se ci si trova in una situazione in cui è utile utilizzare i puntatori di funzioni dei membri in C++, riconsiderare il progetto.

+0

L'alternativa standard alle chiusure è la funzione lambda, ma non è ancora una sostituzione realistica per le funzioni dei membri. – MSalters

3

Non esiste un modo semplice come originariamente incorporato nella lingua o nella libreria standard (sebbene sia stato aggiunto di recente). Se hai familiarità con Boost, includono una soluzione per questo - Boost.Function.

Se per qualche ragione, tuttavia, non sei in grado o non vuole utilizzare Boost, v'è un modo generico di fare questo utilizzando i modelli (che, bisogna ammetterlo, è abbastanza simile soluzione per aumentare):

class FncPtr 
{ 
public: 
    virtual int call(float, char, char) = 0; 
}; 

template <typename T> 
class ClassFncPtr : public FncPtr 
{ 
    int (T::*pt2Member)(float, char, char); 
    T *inst; 
public: 
    ClassFncPtr(T* who, int (T::*memfunc)(float,char,char)) 
     : inst(who), pt2Member(memfunc) 
    { 
    } 
    int call(float a, char b, char c) 
    { 
     return (inst->*pt2Member)(a,b,c); 
    } 
}; 

template <typename T> 
FncPtr * makeFuncPointer(T* who, int (T::*memfunc)(float,char,char)) 
{ 
    return new ClassFncPtr<T>(who,memfunc); 
} 

Puoi anche creare sottoclasse FncPtr per poter utilizzare le funzioni non di classe, se lo desideri.

Problemi correlati