Newsgroup: it.comp.lang.c++
Titolo: Puntatori a membri

Sto creando una serie di classi wrapper su una libreria C, e mi 
piacerebbe aggiungere una specie di gestione degli eventi.
Dunque, ho una classe base CBase e una CChild che deriva da CBase.
Quello che vorrei fare e' definire un metodo in CChild che viene
chiamato dal codice di CBase: ovvero vorrei che il metodo
void CChild::onClose() venisse "generato" da CBase::~CBase.
Spero di essere stato chiaro...
Pensavo a dei callback, ma ho problemi di cast quando cerco di eseguire
il puntatore a funzione (definito in CBase) un metodo di un'altra classe
(ovvero di CChild) (ovviamente... :-()
Se qualcuno sa aiutarmi...
Ciao.

 Spero di essere stato chiaro...
Chiarissimo, e cio` che richiedi specificamente (cioe` fare una
qualsiasi chiamata a metodo di classe-figlio nel distruttore di
classe-base) non e`, semplicemente, possibile, a causa dell'ordine
di distruzione specificato dal linguaggio C++ (che d'altronde non
avrebbe potuto specificarlo diversamente; Lippmann, "Inside the
C++ Object Model", ha una buona trattazione a questo livello).
E` una delle mille ragioni per cui si impongono gli idiomi
"two-phase construction" e "two-phase destruction": quasi
qualsiasi operazione SOSTANZIALE nei costruttori e nei distruttori
presenta problemi, limiti, fragilita`, in diversi e svariati casi.
La necessita` di controllare l'ordine degli accadimenti e`
spesso comune a queste esigenze di two-phase.
(Nonostante i nomi carini, gli idiomi si riducono ad avere
specifiche funzioni di inizializzazione e terminazione...!-).
Molto spesso esigenze di questo tipo si risolvono meglio con
idiomi basati su template.  Ad esempio, puoi dire che CBase
e i suoi derivati CChild sono classi astratte (cioe`, non
istanziabili) e che quella che si istanzia e` sempre una
CChild "rivestita" da un apposito template.  Cioe`, mai
    CChild pippo;
ma
    Concrete<CChild> pippo;
con
template <class T>
class Concrete: public T {
public:
    ~Concrete() { this->T::onClose(); }
};
Qui l'ordine di distruzione ti favorisce poiche` il distruttore
di Concrete<CChild> gira PRIMA della distruzione della CChild
da cui eredita.  (Il this->T:: non e` necessario, ma mi pare che
aggiunga chiarezza).
Nel 90+% dei casi in cui mi sono sottoposti problemi di questo
tipo negli ultimi 2 anni, ho trovato che un approccio a template
(con le tipiche PWAN nei due versi) e` la soluzione migliore.
[NB: PWAN = Pattern Without A Name: un template che ha fra i
suoi parametri il tipo da cui deve ereditare e/o quello che
deve ereditare da lui; identificata da Coplien nel 1995].
Alex

[...]
Perfetto, il tutto funziona alla grande:
#include <stdio.h>
template <class T>
class CTempl : public T {
public:
        CTempl() { onInit(); }
        ~CTempl() { onClose(); }
};
class CParent {
public:
        virtual void onInit() {};
        virtual void onClose() {};
};
class CChild : public CParent  {
public:
        void onInit  () { printf ( "\nOpening...\n" ) ; }
        void onClose () { printf ( "\nClosing...\n" ) ; }
};
int main ( int argc, char** argv ) {
        CTempl<CChild> t;
        return 0;
}
=================================================================
[stefano@Linux test]$ ./a.out
Opening...
Closing...
=================================================================
_GRAZIE MILLE!!!_
Ciao

 Perfetto, il tutto funziona alla grande:
Non hai bisogno dei virtual in questo caso, incidentalmente.
Solo quando vuoi implicitamente chiamare attraverso puntatore
o reference alla BASE metodi della DERIVATA, e in questo
caso col template PWAN abbiamo rovesciato quest'ordine di
dipendenza quindi puoi eliminare il virtual (non danneggia,
se ne hai bisogno x altri usi, ma causa overhead, sia pure
ridotto, per cui se non ti serve ad altro, toglilo...).
Alex