2010-07-23 16 views
9

C'è una classeC++. metodo di classe puntatori

class A { 
public: 
    A() {}; 

private: 
    void func1(int) {}; 
    void func2(int) {}; 


}; 

voglio aggiungere un puntatore a funzione che verrà impostato nel costruttore e punti di FUNC1 o func2.

Quindi posso chiamare questo puntatore (come membro della classe) da ogni procedura di classe e impostare questo puntatore nel costruttore.

Come posso farlo?

+3

A seconda dell'obiettivo, l'ereditarietà virtuale o un modello potrebbe essere più appropriato, FWIW. – Cogwheel

risposta

5

Aggiungere una variabile membro

void (A::*ptr)(); 

set nel costruttore

ptr=&A::func1; 

(o utilizzare la lista di inizializzazione) e lo chiamano nei metodi di A:

(this->*ptr)(); 
+0

(questo -> * ptr)(), non questo -> * ptr() – Tomek

+0

@Tomek: Grazie, corretto. – jpalecek

2

See boost::function per un modo di gestire i puntatori di funzioni e membri della classe in un modo più OO/C++.

Ad esempio (dalla documentazione):

struct X 
{ 
    int foo(int); 
}; 

boost::function<int (X*, int)> f; 

f = &X::foo; 

X x; 
f(&x, 5); 
0

Qualche esempio ...

class A; // forward declaration 
typedef void (A::*func_type)(int); 

class A { 
public: 
    A() { 
    func_ptr = &A::func1; 
    } 

    void test_call(int a) { 
    (this->*func_ptr)(a); 
    } 

private: 
    func_type func_ptr; 

    void func1(int) {} 
    void func2(int) {} 
}; 
+0

(questo -> * ptr)(), non questo -> * ptr() – Tomek

8
class A { 
public: 
    A(bool b) : func_ptr_(b ? &A::func1 : &A::func2) {}; 

    void func(int i) {this->*func_ptr(i);} 

private: 
    typedef void (A::*func_ptr_t_)(); 
    func_ptr_t_ func_ptr_; 

    void func1(int) {}; 
    void func2(int) {}; 
}; 

Detto questo, polimorfismo potrebbe essere un modo migliore per fare quello che vuoi fare con questo.

+1

Definitivamente. Questa è una sintassi complessa e insolita per una ragione. Questo è esattamente il problema che OO risolve facilmente. –

+0

Il codice non viene compilato (almeno su XCode), hai dichiarato func_ptr_ e quindi utilizzato func_ptr ... – RelativeGames

+2

@Cippyboy: non sono nemmeno sicuro di cosa rispondere. Ti sei preso la briga di svendere e commentare, ma non per sistemare questo errore banale ?! Beh, indovina un po ', lo lascio lì dentro, solo per farti dispetto. – sbi

2

Ho compilato ed eseguito questo codice. I vari membri devono essere pubblici in modo da poterli passare al costruttore. Altrimenti, ecco qui.

Tuttavia, sono d'accordo con altri poster che questa è quasi sicuramente una brutta cosa da fare. ;) Basta invocare virtual puro e quindi creare due sottoclassi di A che ogni override invoke().

#include <iostream> 
using namespace std; 

class A; 
typedef void(A::*MyFunc)(int) ; 

class A { 
    public: 

     A() {} 
     A(MyFunc fp): fp(fp) {} 

     void invoke(int a) 
     { 
      (this->*fp)(a); 
     } 

     void func1(int a) { cout << "func1 " << a << endl; } 
     void func2(int a) { cout << "func2 " << a << endl; } 
    private: 

     MyFunc fp; 
}; 

int main() 
{ 
    A* a = new A(& A::func1); 
    a->invoke(5); 
    A* b = new A(& A::func2); 
    b->invoke(6); 
} 
0

Perché pensi che sia una brutta cosa da fare. Ho solo bisogno di un puntatore a funzione e non voglio creare due sottoclassi per questo. Allora perché è così male?

+0

Non è necessario creare due sottoclassi per questo, 'A a'; è definire una variabile di A, e 'a (1, 123)', è una chiamata di funzione, e sta chiamando func1 con input param che è 123; il puntatore a funzione può sicuramente gestire la tua richiesta, ma functor è più facile da usare e la grammatica è elegante. Quando qualcuno ha bisogno di funzioni più complicate delle funzioni di chiamata, come ad esempio il salvataggio dello stato, devono sicuramente usare i funtori. Se pensi che functor possa soddisfare tutte le tue richieste, sono assolutamente d'accordo. Non ho alcun problema se si usa C++ come "C con classi", ma come dato di fatto, il C++ è molto più di questo. – shader

1

vi suggerisco di utilizzare funtore (o oggetto funzione), piuttosto che puntatore a funzione, perché il primo è più sicuro, e puntatore a funzione può essere difficile o imbarazzante di passare uno stato dentro o fuori la funzione di callback

A funtore è fondamentalmente un re-implementazione dell'operatore() della classe a, per la descrizione molto dettagliata prega di fare riferimento a Wikipedia: http://en.wikipedia.org/wiki/Function_object

Il codice dovrebbe essere qualcosa di simile:

class A { 
public: 
    A() {}; 
    void operator()(int function_index, int parameter) { 
    if(function_index == 1) 
     func1(parameter); 
    else if(function_index == 2) 
     func2(parameter); 
    else 
     { //do your other handling operation 
     } 
    } 


private: 
    void func1(int) {}; 
    void func2(int) {}; 
}; 

utilizzando quella classe:

A a; 
a(1, 123); //calling func1 
a(2, 321); //calling func2