Newsgroup: it.comp.lang.c++
Titolo: come si fa il casting da un puntatore_a_metodo a un'altro?

ciao a tutti
ho una classe che ha un membro pubblico, che è un puntatore a
funzione (metodo) di un'altra classe:
class EVT {
public:
    EVT() { }
    virtual ~EVT() { }
};
class CInt {
public:
    /* cut di roba inutile */
    bool (EVT::*OnChange)(int);
};
class Prova : public EVT
{
public:
    CInt int1;
    bool Int1Change(int newval);
    Prova() { int1.OnChange =
reinterpret_cast<EVT::*>(&Prova::Int1Change); }
    ~Prova();
};
ho dovuto mettere il reinterpret_cast perchè VC dice che con
'Int1.OnChange = &Prova::Int1Change;' :
cannot convert from 'bool (__thiscall Prova::*)(int)' to 'bool
(__thiscall EVT::*)(int)'
Types pointed to are unrelated; conversion requires
reinterpret_cast, C-style cast or function-style cast
ma ora, con il reinterpret_cast:
syntax error : '<tag>::*'
come si fa a fare un cast del genere? nn si può??
ciao
xaero

cel'ho fatta?
bastava mettere un typedef nel reinterpret_cast.
ho un'altra cosa da chiedere:
class CLASSE1
{
public: // o private: ?
    void foo();
};
class PIPPO {
public:
    CLASSE1 x;
};
come faccio a fare in modo che il metodo CLASSE1::foo() sia
accessibile solo da PIPPO ??
xaero

 };
Ti sei parzialmente risposto da solo. Pero' ti scrivo per avvertirti che stai
per fare una cosetta piuttosto pericolosa.
Tramite un puntatore a metodo non virtuale di una classe dovresti richiamare
solo metodi che fanno parte di quella classe, non metodi che fanno parte di una
classe derivata da questa. Se lo fai rischi prima o poi di fati male.
Quindi se in CInt vuoi poter richiamare Prova::Int1Change tramite il puntatore
OnChange, o dichiari quest'ultimo come puntatore ad un membro di Prova o
dichiari Int1Change in EVT come metodo virtuale (anche puro).
--
Andrea Ferro
---------
Brainbench C++ Master. Scored higher than 97% of previous takers
Scores: Overall 4.46, Conceptual 5.0, Problem-Solving 5.0
More info 
http://www.brainbench.com/transcript.jsp?pid=2522556

 wrote in message
news:9h2rro$c2965$1...@ID-51253.news.dfncis.de...

class PIPPO;
class CLASSE1
{
    friend class PIPPO;
private:
    void foo();
};
Occhio che PIPPO puo' accedere a tutti i membri di CLASSE1, non solo a foo.


 dichiari Int1Change in EVT come metodo virtuale (anche puro).
[#p.s. mi sono sbagliato e ti č arrivata una copia del msg in
mailbox]
mi puoi spiegare quali sono i rischi?
io ci sono riuscito adesso adesso, con reinterpret_cast.
quello che dici tu non credo lo posso fare, e ora ti spiego perchč:
CInt deve sostituire int in un set di classi che sto scrivendo, per
fare in modo che ogni volta che il membro (di tipo CInt) di una
qualunque classe viene cambiato, venga aggiornato quello che serve,
o
viene annullato l'assegnamento.
dato che non so quali classi conterranno dei membri di tipo CInt,
come
faccio a dichiarare un puntatore a metodo?
allora ho scritto cosě:
typedef bool (EVT::*EVENT_METHOD)(int);
class CInt
{
public:
    EVT* EventListener;
    EVENT_METHOD EventMethod;
    // ......
e nel costruttore della classe che contiene il (i) CInt imposto
tutto:
class CLASSE1 : public EVT
{
public:
    CInt size;
    bool OnChangeSize(int newSize)
    {
        if(newSize > 0 && newSize < 100)
            return false;
        else
            return true;
    }
    CLASSE1()
    {
        size.EventListener = this;
        size.EventMethod =
reinterpret_cast<EVENT_METHOD>(OnChangeSize);
    }
}
funziona, e fin'ora (cioč nell'arco di un'ora ^__^) non ha mai dato
problemi. es:
int main()
{
    CLASSE1 c;
    c.size = 50; // ok
    c.size = 987; // resta 50
    return 0;
}
ciao
xaero

 dichiari Int1Change in EVT come metodo virtuale (anche puro).
[#p.s. mi sono sbagliato e ti č arrivata una copia del msg in


 quello che dici tu non credo lo posso fare, e ora ti spiego perchè:
... cut
per il problema che hai descritto esistono soluzioni conosciutissime. E persino
una serie di pattern. Prova a cercare "Observer".


 una serie di pattern. Prova a cercare "Observer".
ho letto un paio di articoli sul Observer Pattern, ma non mi pare
che è proprio quello che cerco.
io devo fare delle classi (per ora string e int) che devono
funzionare come le proprietà di un oggetto ActiveX, per costruire
dei wrapper per le finestre in win32.
praticamente:
per esempio per spostare una finestra (programmando con l'sdk win32)
devo usare SetWindowPos.
allora nella mia classe wrapper inserisco due variabili membro CInt,
x e y. quando scrivo:
Finestra1.x = 55;
l'operator = di CInt chiama la funzione x la notifica del
cambiamento di x, che chiama SetWindowPos().
potrei risolvere tutto costruendo delle classi che vanno bene solo
come membri della classe di Finestra1, ma sarebbe stato molto più
bello scrivere qualcosa di riutilizzabile.
ancora non ho letto nulla riguardo i templates, ma ora mi chiedo se
possono essere utili in qesto caso.
nella dichiarazione della classe x es. potrei scrivere:
CInt<CWindow> x ecc... ma funziona anche x il puntatore a funzione?
ciao
xaero

 cambiamento di x, che chiama SetWindowPos().
Pessima idea. Una classe CInt non ha senso che "sappia" che l'int e' una
posizione di una finestra (e tanto meno che e' la posizione in orizzontale).
Questo genere di informazione e' pertinenza della classe di Finestra1. In
generale in una programmazione object oriented si evita di permettere l'accesso
diretto ai membri dati. Quindi la cosa diventerebbe
Finestra1.setX(55);
che ti risolve il problema.
Se proprio vuoi mantenere la sintassi di accesso ad un membro dato puoi usare il
pattern Observer per rendere la classe di Finestra1 un osservatore dei suoi
stessi membri.
A questo punto il membro invece che un int o un CInt e' un ObservableInt. Al
cambio di valore richiama l'update di tutti gli osservatori (ovvero della classe
esterna nel nostro caso) la quale fa quello che deve fare.
