Newsgroup: it.comp.lang.c++
Titolo: Errore sui puntatori a funzione

Sono di nuovo io con i soliti puntatori,
avendo una classe simile a:
class Base {
        private:
                  void metodo(void) {
                         /* definizione del metodo */
                  }
                  void (*puntatore) (void);
                  explicit Base(void) { 
                           this -> Base::puntatore = this ->Base::metodo;
                  }
};
 
Prima segnalazione del compilatore:
& espected in pointer to function
A questo punto modifico il codice di conseguenza, anche se mi pare che il
nome di una funzione ricade nel puntatore al primo byte della stessa nelle
espressioni.
Seconda segnalazione:
impossibile dichiarare un puntatore ad una funzione non static.
Ho modificato quindi il codice secondo quanto detto dal compilatore, ma non
sono molto sicuro di quanto mi ha detto.
Ringrazio tutti in anticipo.
-- 
La classifica dei prodotti MS:
C#, la migliore barzelletta di Bill Gates.
Visual C++, il meno standard dei compilatori C++.
J++, la copiatura più riuscita.
Windows, il più instabile.
Visual Basic, un esempio di prodotto decente della MS - forse l'unico -.
OutlookExpress, scandali su scandali.
La classifica degli "amici" coglioni:
Stefano Zanchi, il miglior lamer del mondo.
 

& espected in pointer to function
E' sempre il solito problema dei puntatori a metodo. Recentemente
c'e' stato un thread sull'argomento anche se la discussione era
parzialmente offuscata dall'essere offtopic (Win32).
HTH
Andrea
--
Andrea Griffini, Programmer
http://www.netservers.com/~agriff

 };
Ci sono tre errori: uno di accesso, uno sintattico e uno di tipi.
Quello di accesso è banale e probabilmente è una svista: hai reso il
costruttore private, la classe sarà istanziabile con grande difficoltà ;-)
A proposito, che significa la keyword "explicit" ?
Quello sintattico è nell'assegnazione: dovrebbe essere
this->puntatore = this->metodo;
Davvero non capisco perché usi il nome completo... e a dire il vero, non
capisco nemmeno perché usi il puntatore this: non sarebbe più semplice
scrivere
puntatore = metodo;
sapendo che ti trovi comunque all'interno della classe, e in particolare nel
suo costruttore ?
L'altro errore è sui tipi, ed è quello vero e proprio che cerchi: tu hai
dichiarato puntatore così:
void (*puntatore)(void);
ovvero come "puntatore a funzione che non accetta parametri e non ne
ritorna". Invece metodo, per come l'hai definito, è di tipo
void Base::metodo(void);
e quindi ricade nel solito problema delle funzioni membro: il compilatore,
chiamandola, le passa implicitamente il parametro this. I tipi del puntatore
e della funzione differiscono per la convenzione di chiamata utilizzata, e
quindi il compilatore si rifiuta di eseguire l'assegnamento. L'unico modo
per evitare questo è rendere static la funzione, in modo che possa essere
chiamata senza this:
static void metodo(void);
In definitiva, la sintassi corretta è la seguente:
class Base
{
private:
    void (*puntatore) (void);
    static void metodo(void)
    {
        /* definizione del metodo */
    }
public:
    Base(void)
    {
        puntatore = metodo;
    }
};

void Base::metodo(void);
Non vi è nessun modo per evitare di usare metodi static con un puntatore?
Grazie per quanto detto.


 Non vi è nessun modo per evitare di usare metodi static con un puntatore?
Se fanno parte di una classe, la loro convenzione di chiamata include
obbligatoriamente this, c'è poco da fare...
Altra cosa sarebbe se si potesse esplicitare la cosa, ad esempio dichiarare
un puntatore a funzione come
void Base::(*p)(void);
oppure
void *(Base::p)(void);
che fosse di tipo "puntatore a funzione MEMBRO DI BASE che accetta void e
ritorna void", allora l'assegnazione sarebbe fattibile e il compilatore che
gestisse questa cosa potrebbe ad esempio imporre di usare quel puntatore
passandogli un'istanza di base da usare come this per la funzione membro,
una cosa tipo
p = Base::f;
p2 = new Base();
(*p)(p2);
Ma credo che non si tratti di C++ valido ;-)
Massimo

Ma credo che non si tratti di C++ valido ;-)
Non come lo hai scritto perche' e' diversa la sintassi... ma il
concetto e' esattamente quello. Se ti capita la possibilita'
prova a leggere il punto 5 del capitolo 15 di "The C++ Programming
Language" (3 edizione)... parla proprio di queste cose.


   p=Base::f;         // p punta al metodo f di base
    p = &Base::f;
        ^
L'e commerciale e' richiesta dallo standard (5.3.1 3).
Ciao,
Nicola

Evviva grazie hai fatto un metodo statico!!!
Io (noi) la vediamo cosi':
#include <iostream>
class Base
{
private:
    void metodo() const
    { std::cout << "metodo" << std::endl; }
public:
    void (Base::*puntatore) () const;
    Base()  {  puntatore = metodo; }
};
int main()
{
	Base b;
	void (Base::*p) () const = b.puntatore;
	(b.*p)();
	return 0;
}
Sent via Deja.com
http://www.deja.com/

     Base()  {  puntatore = metodo; }
                                ^
A norma di standard questo e' un errore, deve essere scritto
&Base::metodo anche all'interno della stessa classe.
Ciao,
Nicola

 Language" (3 edizione)... parla proprio di queste cose.
Ti giuro, quando ho scritto quel messaggio ero convinto che i puntatori a
membro non esistessero e speravo che qualcuno li inventasse :-)))
Massimo

 L'e commerciale e' richiesta dallo standard (5.3.1 3).
Come mai invece per una funzione non membro basta il nome ?
Mi sembra un'incoerenza...
Massimo



Molto interessante. E strano.
g++ segnala la cosa se si compila con -Wall con il messaggio
     warning: assuming & on 'T::a()'
(notare che nel sorgente le parentesi dopo 'a' non ci sono)
mentre non sembra rispettare lo standard (pardon, l'ultimo
draft) quando questo afferma che *NON* e' ammesso mettere
fra parentesi il nome qualificato della funzione membro:
  class T
  {
    public:
      void a(){}
  };
  int main()
  {
    void (T::*m)();
    m=T::a;    // "warning: assuming & on 'T::a()'"
    m=&(T::a); // nessun warning per g++ -Wall --pedantic
    return 0;
  }
Sono al tempo stesso incuriosito e un po' intimorito da
quest'altra asimmetria *apparentemente* ingiustificata...


};
una curiosità: explicit serve ad impedire che i costruttori con un
solo parametro diventino operatori impliciti di conversione: a cosa ti
serve explicit se il costruttore non accetta parametri?
Anto

 quest'altra asimmetria *apparentemente* ingiustificata...
Non ne ho idea. Si puo' provare a chiedere su c.l.c++.m (o c.s.c++).
Ciao,
Nicola