2009-06-13 9 views
38
class Foo { 
public: 
    Foo() { do_something = &Foo::func_x; } 

    int (Foo::*do_something)(int); // function pointer to class member function 

    void setFunc(bool e) { do_something = e ? &Foo::func_x : &Foo::func_y; } 

private: 
    int func_x(int m) { return m *= 5; } 
    int func_y(int n) { return n *= 6; } 
}; 

int 
main() 
{ 
    Foo f; 
    f.setFunc(false); 
    return (f.*do_something)(5); // <- Not ok. Compile error. 
} 

Come posso farlo funzionare?Puntatore funzione C++ (membro classe) a funzione membro non statico

+1

Le funzioni statiche 'func_x' e' func_y' non sono contrassegnate come tali? –

risposta

31

La linea che si desidera è

return (f.*f.do_something)(5); 

(che compila - ho provato)

"*f.do_something" si riferisce al puntatore stesso --- "f" ci dice dove ottenere il valore do_qualita da. Ma dobbiamo ancora dare un oggetto che sarà il puntatore quando chiameremo la funzione. Ecco perché abbiamo bisogno del prefisso "f.".

+8

Tecnicamente, "f.do_something" restituisce il puntatore e l'operatore ". *" Chiama la funzione pointer-to-member su una classe. –

+0

Quindi presumo che 'return (f. * Foo :: do_something) (5)' funzioni anche. – ThomasMcLeod

+1

@ThomasMcLeod Non lo fa. –

0

Provare (f. * Do_qualcosa) (5);

35
class A{ 
    public: 
     typedef int (A::*method)(); 

     method p; 
     A(){ 
      p = &A::foo; 
      (this->*p)(); // <- trick 1, inner call 
     } 

     int foo(){ 
      printf("foo\n"); 
      return 0; 
     } 
    }; 

    void main() 
    { 
     A a; 
     (a.*a.p)(); // <- trick 2, outer call 
    } 
+3

+1 per due prese –

+0

Tudok, dopo aver ripassato il tuo post una seconda volta mi sono reso conto che anche tu hai dato la risposta giusta (trucco 2). Grazie. – Girish

+0

Il tuo codice non funziona. Copia/incolla e prova a compilare. test_function_pointer_2.C: nel costruttore 'A :: A()': test_function_pointer_2.C: 7: errore: argomento di tipo 'int (A ::)()' non corrisponde 'int (A :: *)() ' – user180574

-4

Penso che chiamare un membro non statico della classe possa essere eseguito anche utilizzando una funzione membro statica.

+1

Questo non è possibile. "Quando si modifica un membro dati in una dichiarazione di classe, la parola chiave static specifica che una copia del membro è condivisa da tutte le istanze della classe. Quando si modifica una funzione membro in una dichiarazione di classe, ** la parola chiave static specifica che la funzione accede solo membri statici **. " Vedere [riferimento MSDN] (http://msdn.microsoft.com/en-us/library/s1sb61xd (v = vs80) .aspx) – ForceMagic

+0

bene, è possibile mantenere un elenco di tutte le istanze tramite il costruttore e quindi chiamare per tutte le istanze, ma immagino che sia un po 'un'idea: p –

3
class A { 
    int var; 
    int var2; 
public: 
    void setVar(int v); 
    int getVar(); 
    void setVar2(int v); 
    int getVar2(); 
    typedef int (A::*_fVar)(); 
    _fVar fvar; 
    void setFvar(_fVar afvar) { fvar = afvar; } 
    void insideCall() { (this->*fvar)(); } 
}; 

void A::setVar(int v) 
{ 
    var = v; 
} 

int A::getVar() 
{ 
    std::cout << "A::getVar() is called. var = " << var << std::endl; 
    return var; 
} 

void A::setVar2(int v2) 
{ 
    var2 = v2; 
} 

int A::getVar2() 
{ 
    std::cout << "A::getVar2() is called. var2 = " << var2 << std::endl; 
    return var2; 
} 

int main() 
{ 
    A a; 
    a.setVar(3); 
    a.setVar2(5); 

// a.fvar = &A::getVar; 
    a.setFvar(&A::getVar); 
    (a.*a.fvar)(); 

    a.setFvar(&A::getVar2); 
    (a.*a.fvar)(); 

    a.setFvar(&A::getVar); 
    a.insideCall(); 

    a.setFvar(&A::getVar2); 
    a.insideCall(); 

    return 0; 
} 

Ho esteso la risposta di Nick Dandoulakis. Grazie.

Ho aggiunto una funzione che imposta il puntatore della funzione membro dall'esterno della classe. Ho aggiunto un'altra funzione che può essere chiamata dall'esterno per mostrare la chiamata interna del puntatore della funzione membro.

+0

Invece di pubblicare solo un blocco di codice, per favore * spiega * perché questo codice risolve il problema posto. Senza una spiegazione, questa non è una risposta. –

+0

@MartijnPieters Ho scritto che è stato esteso dalla risposta di Nick Dandoulakis. È stato spiegato lì. Sono nuovo in StackOverflow, forse ho bisogno di fare in un modo diverso. –

+0

Beh, potresti spiegare cosa hai cambiato, per esempio, e perché. –

0
#include<iostream> 
using namespace std; 

class A { 

public: 
    void hello() 
    { 
     cout << "hello" << endl; 
    }; 

    int x = 0; 

}; 


void main(void) 
{ 

    //pointer 
    A * a = new A; 
    void(A::*pfun)() = &A::hello; 
    int A::*v1 = &A::x; 

    (a->*pfun)(); 
    a->*v1 = 100; 
    cout << a->*v1 << endl << endl; 

    //----------------------------- 
    A b; 
    void(A::*fun)() = &A::hello; 
    int A::*v2 = &A::x; 

    (b.*fun)(); 
    b.*v2 = 200; 
    cout << b.*v2 << endl; 

}