Newsgroup: it.comp.lang.c++
Titolo: Funzioni di callback

Salve a tutti,
qualcuno mi sa spiegare come usarle. Ad esempio data la seguente
funzione membro di una classe:
CProva::Funzione(???)
{
    ...
    // voglio a questo punto chiamare la funzione ???
    ...
}
al posto dei ??? voglio dichiarare un puntatore ad una funzione, da
richiamare dentro la funzione. Come posso fare?
Grazie per la collaborazione.

richiamare dentro la funzione. Come posso fare?
Dipende che argomenti prende, e che tipo di valore ritorna,
la funzione che vuoi chiamare.  Ad esempio, a una funzione
che prende un double e torna un int potresti dichiarare un
puntatore cosi` (tutto quanto segue vale nell'ipotesi che tu
voglia effettivamente un puntatore a *funzione*, NON un
puntatore-a-metodo che e` tutta un'altra cosa; in altri
termini, questo vale per funzioni libere, o membri statici
di una qualche classe, NON per metodi di un oggetto, che
hanno sintassi E semantica drasticamente diversi):
    CProva::Funzione(int (*ilpunt)(double)) {
e chiamarlo, ad esempio, cosi`:
    int risult = ilpunt(23.45);
Come sempre in C e C++, le dichiarazioni con sintassi strana
e` meglio gestirle con un typedef:
typedef int (*pfun_double_int_t)(double);
    CProva::Funzione(pfun_double_int_t ilpunt) {
comunque, e` solo una questione di stile, manutenibilita`, e
leggibilita` -- il codice generato sara` esattamente lo stesso.
Se vuoi, puoi divertirti, in fase di chiamata, a preporre al
"ilpunt" una operatore di dereferencing, cioe` chiamare:
        int risult = (*ilpunt)(23.45);
ma non avrebbe particolarmente senso farlo (puoi anche
mettercene piu` di uno, se vuoi) -- e` decisamente piu`
leggibile omettere l'asterisco e relative parentesi, e la
semantica e` _rigorosamente_ identica.
Alex


e come si fa per un puntatore-a-metodo di un oggetto qualunque?

e come si fa per un puntatore-a-metodo di un oggetto qualunque?
Non si fa: un puntatore-a-metodo e` sempre su di una SPECIFICA
classe (non esiste, insomma, l'equivalente di quello che sarebbe un
"void*" per un puntatore-a-dato), esattamente come un puntatore-a-
funzione e` sempre per SPECIFICI tipi di argomenti e risultato (non
c'e`, in C++ standard ne` in C standard, NESSUNA garanzia di
potere fare dei cast fra diversi puntatori-a-funzioni, o fra essi e
puntatori-a-dati: qualsiasi cast del genere e` "undefined behaviour",
cioe`, un dato compilatore puo`, come estensione, scegliere di
definire questo comportamento, ma non e` tenuto a farlo).
Per la grande maggioranza dei problemi che "sembrerebbe" ideale
risolvere con "puntatori a metodi di oggetti qualunque", la soluzione
ideale sta invece nell'uso di TEMPLATE ("generic programming");
altri si possono risolvere con eredita` multipla da classi-interfacce
di "mix-in", e RTTI; altri ancora richiedono una rifattorizzazione
del proprio progetto.
Esistono inoltre approcci/soluzioni, NON portabili, come l'estensione
al C++ che Borland ha implementato in C++Builder per "impacchettare"
un puntatore-a-oggetto, piu` un puntatore-a-metodo-dell'oggetto, in
un singolo "robo" che "sembra" un puntatore-a-funzione; o i "thunk" in
linguaggio macchina (o eventualmente in assembler) che si trovano in
giro per la rete per fare cose analoghe con altri compilatori (specie
con VC++).  L'uso di questi approcci va visto, naturalmente, come una
"ultima spiaggia", da usare solo in casi di emergenza/disperazione, in
quanto sacrifica *TOTALMENTE* la portabilita` del proprio codice.
Alex