Newsgroup: it.comp.lang.c++
Titolo: Distruttore, chi lo richiama?

Con il VC 6 il distruttore di questa classe deve essere pubblico,
altrimenti il compilatore si arrabbia. Non che sia un problema, ma non
capisco perche' non posso definirlo privato.
In questo esempio vuol dire che il compilatore (di nascosto) mette nel
codice la chiamata a WrapperInt.~SingoloInt(), e che se non lo
definisco e' come se il compilatore lo mettesse pubblico e poi lo
richiamasse ?
class SingoloInt
{
public:
	static int Leggi(){return SingoloInt::intero;}
	static void ScriviMaNonTroppo(int i){if(i<20) SingoloInt::intero =
i;}
	~SingoloInt(void){}
private:
	SingoloInt(void){}
	static int intero;
	static SingoloInt WrapperInt;
};
int SingoloInt::intero = 0;
SingoloInt SingoloInt::WrapperInt;
int main(void)
{
	int i = SingoloInt::Leggi();
	SingoloInt::ScriviMaNonTroppo(i+1);
	return 0;
}
-- 
Tieni per te il Papero se vuoi la mia email
Sito Papero -> 
http://utenti.tripod.it/papero

richiamasse ?
Nel caso che la tua classe non sia provvista di un dicostruttore, allora il
compilatore ne inserisce uno pubblico a suo "personale" utilizzo.
Nel caso che tu voglia definirne uno sei obbligato a dichiararlo come
pubblico dato che il compilatore inserisce automaticamente una sua chiamata
alla terminazione dell'oggetto.
Cmq č sempre meglio evitare di usare i costruttori, specialmente se non si
hanno operazioni da svolgere al loro interno.
Per quanto ne so l'unico utilizzo "intelligente" del distruttore  č quando
l'oggetto possiede attributi membro di tipo puntatore o reference.
Ciao.
-- 
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.
 

richiamasse ?
Il compilatore crea una serie di metodi automaticamente quando
questi non sono stati dichiarati da te... ad esempio quando scrivi:
   class Simple
   {
     int x,y;
   };
il compilatore si comporta come se tu avessi scritto:
   class Simple
   {
     public:
       Simple()  { }
       ~Simple() { } // Nota: *NON* virtual
       Simple(const Simple& src)
         : x(src.x),y(src.y)
       { }
       Simple& operator=(const Simple& src)
       {
         x=src.x;
         y=src.y;
         return *this;
       }
       Simple *operator&()
       {
         return this;
       }
       const Simple *operator&() const
       {
         return this;
       }
     private:
       int x,y;
   };
Nota che esistono dei casi in cui il compilatore non
crea in automatico l'operatore di assegnazione; questo
accade quando il codice generato in automatico di
assegnazione membro-a-membro non avrebbe senso (ad
esempio se la classe contiene dei reference).
HTH
Andrea
--
Andrea Griffini, Programmer
http://www.netservers.com/~agriff

l'oggetto possiede attributi membro di tipo puntatore o reference.
Non capisco questa frase... se ti preoccupi solo della memoria
cosa centrano i reference ? Se invece parli di funzionalita' che e'
comodo associare a costruttori/distruttori allora ci sono moltissimi
altri casi in cui vengono svolti compiti importanti (chiusura
file/canali di comunicazione, scrittura su log,
registrazione/cancellazione da elenchi pubblici ...)


registrazione/cancellazione da elenchi pubblici ...)
Hai anche ragione tu, ma il problema č che i distruttori possono provocare
errori subdoli o cmq codici un po' sporchi. Pensa, per esempio, se richiamo
in modo esplicito un distruttore su un oggetto locale ad una funzione.
Ciao.
-- 
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.
Outlook, non essendo soddisfatto degli scandali di OE Bill Gates ha deciso
di 
               rilasciare la versione completa in modo da poterli
aumentare.
Word, uno dei principali esponenti dei programmi ribatezzati MS 
Windows NET, se dicono che il buongiorno si vede dal mattino allora 
                         vedo nero nel futuro di questo OS.
Disse Bill Gates "Datemi un programma ch'io possa ribattezzarlo MS"
E a gran voce gli risposero "Fai attenzione a non fare la fine di Stargate"
 
 

 alla terminazione dell'oggetto.
Davide parlava del distruttore. E comunque anche il costruttore può
essere reso privato allo scopo di impedirne l'utilizzo.
EMG

 capisco perche' non posso definirlo privato.
Né il DJGPP né il BCC55 danno alcun problema a compilare il tuo esempio,
anche rendendo il distruttore privato. Quindi immagino sia una "feature"
del VC6.
EMG



Questo e' interessante... con BCC55 se si dichiara una istanza statica
locale di una funzione membro (statica o non) della classe e il
distruttore e' privato il compilatore si arrabbia; mentre questo non
succede con una istanza statica globale anche se le condizioni in cui
queste istanze vengono *distrutte* sono molto simili.
La cosa e' corretta secondo voi ?
Inoltre come mai e' permesso al codice "globale" di distruggere un
oggetto quando il distruttore e' dichiarato "privato" e come tale
dovrebbe essere invocato solamente da funzioni membro o friend ?
Se un costruttore e' dichiarato privato non e' ammesso ad esempio
definire delle istanze statiche globali (non dichiarate static
nella classe)... detto in altri termini il codice "globale" di
inizializzazione non ha il diritto di chiamare il costruttore
se questo non e' public...
Io non so cosa dice lo standard... ma la posizione del VC++ su
questa cosa mi sembra piu' coerente con la filosofia del
controllo di accesso (anche se questo non significa che sia
quella ufficiale... il C++ in certi punti non brilla certo per
la sua coerenza).
Che ne pensate ?


 La cosa e' corretta secondo voi ?
In una funzione membro della classe *stessa*? Mi pare un errore. Per
quel che riguarda l'istanza statica locale, ti sei assicurato che venga
effettivamente utilizzata? Non e' che il compilatore la "ottimizza"?
Nota che secondo me e' altrettanto un errore.
Ciao,
Nicola

        }
Secondo me questi sono chiamate all'operatore builtin e non richiedono
di essere sintetizzati.
Ciao,
Nicola
P.S. altrimenti ci sono anche * e ->

Cmq è sempre meglio evitare di usare i costruttori
Perche' ? 
p.s.: potresti accorciare la firma ?
--
Andrea Laforgia (ICQ 87230455)
http://www.geocities.com/AndreaLaforgia
"ci sono tre tipi di persone nel mondo : quelli che
 sono bravi in matematica e quelli che non lo sono."

oggetto quando il distruttore e' dichiarato "privato" e come tale
Mi fate un esempio in cui e' utile dichiarare costruttore e/o
distruttore come privati ?


Andrea Laforgia (ICQ 87230455)
Ciao Andrea,
quando vuoi che ci sia una sola instanziazione della tua classe ad esempio
dovresti dichiarare non pubblico il costruttore, il copy constructor e
l´operatore di assegnamento.
Mauro

 distruttore che non sia pubblico.
[...]
Un esempio importante di distruttore protetto si ha nei singleton
implementati con new.
(per i dettagli sull'implementazione vedi il thread sui singleton.)
se il distrutore non fosse privato, sarebbe leggittimo scrivere
qualcosa del genere:
Singleton *p = Singleton::instance();
delete p;
...
Singleton *q = Singleton::instance();
q->kaboom()!
/fabio
Sent via Deja.com
http://www.deja.com/

l´operatore di assegnamento.
Grazie ;)
Pero', scusa, se dichiaro un costruttore privato, come faccio ad
istanziare la classe (anche solo una volta) ?
--
Andrea Laforgia (ICQ 87230455)


istanziare la classe (anche solo una volta) ?
ti basta creare un metodo pubblico e statico che istanzia l'oggetto e
lo restituisce...
tale metodo può avere il controllo del numero di oggetti creati
attraverso l'uso di variabili static!!
sderinux

Da una funzione membro statica della classe medesima.
Ciao,
Nicola

attraverso l'uso di variabili static!!
Thanx :)
In gamba, come sempre...


p.s.: potresti accorciare la firma ?
Certamente.

> Da una funzione membro statica della classe medesima.
E da una funzione friend o membro di una classe friend, no? ;)
    Rony.
P.S. per Andrea... lo faccio proprio nel programma che ti dicevo nella mail
di un paio di giorni fa...
--
-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_
"Solo due cose sono infinite,
l'universo e la stupidita' umana,
e non sono sicuro della prima."
Albert Einstein

 distruttore come privati ?
Per il distruttore (come già detto da altri) non mi viene in mente. Per
quanto riguarda il costruttore, dato che di costruttori ne possono
esistere più di uno, posso magari rendere privato quello di default in
quanto voglio che chi usa la mia classe passi sempre un parametro di
inizializzazione al costruttore della stessa.
EMG

Nota che secondo me e' altrettanto un errore.
  class X
  {
    private:
      X(){};
      ~X(){};
    public:
      static void foo();
      void foo2();
  };
  void X::foo()  { static X x; }
  void X::foo2() { static X x; }
  int main()
  {
    return 0;
  }
BCC55 => "Error E2166 private.cpp 19: Destructor
          for 'X' is not accessible"
g++ => "private.cpp:9: warning: `class X' only defines
          a private destructor and has no friends
        private.cpp: In function `void __tcf_0()':
        private.cpp:5: `X::~X()' is private
        private.cpp:11: within this context
        private.cpp: In function `void __tcf_1()':
        private.cpp:5: `X::~X()' is private
        private.cpp:12: within this context"
(l'errore scompare spostando la dichiarazione
del distruttore nella parte public oppure rimuovendo
le due variabili static dalle funzioni)
g++ pero' diversamente da BCC55 genera lo stesso errore
anche se si tenta di dichiarare una istanza statica
di X con qualcosa come...
  class X
  {
    private:
      X(){};
      ~X(){};
    public:
      X the_one;
  };
  X X::the_one;
Io trovo che segnalare un errore come fa g++ sia in
questo caso piu' uniforme e sensato (ma questo ovviamente
non vuol dire che debba essere quello che si e' deciso
deve essere il comportamento standard)
Una cosa che mi stupisce un poco e' che questo discorso
non vale per g++ quando si parla del costruttore...
anche definendo il costruttore privato e' infatti
possibile dichiarare delle istanze statiche anche se in
questo caso il costruttore non viene chiamato da una
funzione membro della classe.
Riguardo al tuo dubbio sull'ottimizzazione non credo che
il compilatore possa essere autorizzato a fare una cosa
del genere per due ragioni... innanzitutto una istanza
statica deve essere comunque inizializzata e distrutta
(anche se lo standard e' un po' vago sul "quando") e in
secondo luogo anche se questo non comporta nessuna
operazione reale chi si occupa della cosa deve avere le
necessare autorizzazioni.


P.S. altrimenti ci sono anche * e ->
Veramente non concordo. Se provi a chiamare uno degli operatori
di dereferencing come "*" e "->" su una classe senza averlo
definito ottieni un errore. La cosa invece non accade con
l'operatore "address-of" o con gli altri metodi/operatori
sintetizzati automaticamente come il costruttore copia, il
distruttore o l'assegnazione.
Da quello che avevo letto su "Effective C++" ero portato a
pensare che inoltre l'operatore "&" non venisse ereditato
(come non vengono ereditati gli altri metodi/operatori
creati automaticamente) ma sia BCC55 che g++ non concordano
su questa mia supposizione e invece propagano
l'implementazione di operator&() dalla base alla derivata.
Questa differenza mi incuriosisce e indaghero' sulla cosa
non appena avro' un po' di tempo (hahaha... buona questa!)


 necessare autorizzazioni.
A me risulta che una variabile statica globale puo' tranquillamente
essere eliminata per ottimizzazione se non e' usata esplicitamente. Se
una funzione non e' utilizzata puo' anch'essa essere eliminata e per
conseguenza assumo che anche una variabile statica locale possa essere
eliminata.
Ciao,
Nicola
P.S. Ma non avevi posto tu un quesito del genere su c.l.c++.m qualche
mese fa?

 l'implementazione di operator&() dalla base alla derivata.
Non ho trovato un indicazione esplicita sullo standard, ma come sai
questa non e' una prova conclusiva :-)
Ciao,
Nicola

 inizializzazione al costruttore della stessa.
In questo caso, basta non dare alla classe un costruttore senza parametri:
se il compilatore vede anche un solo costruttore definito per una classe,
non va a generare quello di default, quindi sarà impossibile istanziare la
classe se non con il costruttore definito dall'utente.
Per i costruttori parametrizzati c'è poi l'opzione explicit per evitare
conversioni implicite di tipo...
Ciao
Domenico Barra

 del VC6.
no
se c'e` una cose del genere:
class A {
public:
	A();
private:
	~A();
};
int main() {
	A test;
	return 0;
}
il compilatore dovrebbe rifiutarsi di compilare, in quanto la classe
definisce solo un distruttore privato e non ha classi friend
ciao
Kronos
-- 
Home: 
http://kronoz.tsx.org
This message will self distruct in 5 seconds.

 classe se non con il costruttore definito dall'utente.
Vero. Esempio sballato...
EMG

mese fa?
In vero esiste un problemino su questa cosa... in
passato ho posto una domanda in c.l.c++.m riguardo a
compilation unit che erano *interamente racchiuse* in
un unnamed namespace e in cui il codice di
inizializzazione veniva utilizzato per registrare dei
fornitori di servizio su un pubblico registro gestito
in un singleton.
  namespace
  {
    class MyServiceProvider: public Provider
    {
      public:
        MyServiceProvider()
        {
          Registry::inst().Register("service",this);
        }
      ...
    } my_service_provider;
  }
Dalle parole dello standard sembra di capire che esiste
la garanzia che il codice sara' eseguito... ma l'esecuzione
*potrebbe* essere posticipata sino a quando si accede al
modulo (ovvero a mai, visto che nessuno puo' accedere a meno
che il codice venga eseguito e l'istanza sia registrata).
Nota che diversamente dall'inizializzazione delle statiche
locali di una funzione, dove e' *garantito* che la
costruzione viene posticipata sino a quando la funzione
viene invocata, in questo caso il posticipo e' semplicemente
una *eventualita' possibile*.
Quello che mi e' stato detto e' che ci sono ottime
probabilita' che le cose funzionino senza problemi
(inizializzando l'istanza) se si sta alla larga da librerie
dinamiche: la possibile posticipazione e' stata inserita
nello standard per lasciare aperta la possibilita' di usare
librerie dinamiche in C++.
Riassumendo la costruzione delle istanze statiche non
puo' essere ottimizzata, a meno che l'intera compilation
unit possa essere ignorata perche' nessuno vi fa
riferimento (la costruzione potrebbe anche non avvenire
se durante una specifica sessione di esecuzione del
programma nessuno facesse riferimento a qualcosa della
compilation unit).
In pratica e' molto difficile che le inizializzazioni
vengano saltate a meno che la compilation unit si trovi
in una libreria dinamica... il motivo e' molto semplice:
costa molto meno a chi scrive compilatori chiamare una
routine di inizializzazione per ogni modulo invece di
mettere delle sentinelle a vincolare l'accesso a tutte
le funzioni e, piu' difficile ancora, alle variabili del
modulo. Nel caso delle librerie dinamiche mi aspetto
anche che questa inizializzazione venga fatta all'atto
del caricamento della libreria dinamica e non al momento
dell'uso della funzione di un modulo che compone la libreria
(sempre per questioni di semplicita' implementativa).


questa non e' una prova conclusiva :-)
Forse mi sbaglio... ma dalla mancanza di documentazione di
dettaglio su questo operatore (sia su "The C++ Programming
Language" che nel draft dello standard) mi viene da sospettare
che si tratti di qualcosa di cui un po' il C++ si vergogna :DDD
Sul draft ho trovato solo una frase che dice che e' ammesso
usare "&" per avere l'indirizzo di un oggetto di tipo non
completo... ma che la cosa e' undefined se quell'oggetto
e' una classe che ha ridefinito operator&() (e su questa
violazione non e' richiesto nessun messaggio diagnostico).
Comunque anche con Comeau C++ operator&() viene ereditato...


 definisce solo un distruttore privato e non ha classi friend
Infatti non compila. Evidentemente nell'esempio dell'altro amico c'è
qualche differenza che il compilatore ritiene importante.
EMG

 autorizzato ad evitarne costruzione e distruzione.
Ho letto anche la dissertazione che seguiva, è veramente interessante.
Mi domando come la parola chiave "volatile", in un caso come questo,
modifichi i tempi di inizializzazione, ammesso e non concesso che lo faccia.
Può, per esempio, fornire garanzia che l'inizializzazione avvenga?
    Rony.

 q->kaboom()!
Vero... ho visto pero' che alcuni compilatori
prendono male il fatto che delle istanze
statiche locali abbiano un distruttore privato
e comunque e' importante non dimenticare che
il C++ cerca di proteggere dagli errori
*accidentali* e non da chi deliberatamente
vuole fare casini... Nulla ti proteggera' mai
da cose come
  char * p=(char *)Singleton::instance();
  p[3]='!';
Forse a questo punto e' giusto concludere che sono
preferibili le implementazioni di singleton che
tornano dei reference (in modo che fare la delete
possa venire in mente solo a un pazzo furioso).
Andrea
--
----------------------------------------------------------------
 <\___/>  Andrea        email: agriff at tin dot it
 / . . \  "6502"          irc: _6502_@EFNET#italia
(  (")  ) Griffini   homepage: 
http://www.netservers.com/~agriff


 (sempre per questioni di semplicita' implementativa).
Ho la sensazione che il compilatore Borland sia piu' drastico da questo
punto di vista, ovvero che probabilmente genera una funzione di
inizializzazione per ogni modulo, ma la chiamata a tale funzione e'
generata solo al primo riferimento a elementi del modulo stesso. Non
sono completamente sicuro, perche' avevo fatto delle prove tempo fa e
non ricordo bene i dettagli.
Ciao,
Nicola

non ricordo bene i dettagli.
Hmmm.. sulle funzioni la cosa richiederebbe un overhead forse
anche sopportabile; ma sulle variabili la cosa che dici non mi
convince molto... se ad esempio un modulo contenesse
   class X
   {
     public:
       static int y;
       X() { y=3; }
   };
   int X::y;
   X x; // Istanza statica
tutti gli usi della variabile intera X::y in altri moduli
dovrebbero prima controllare se il modulo e' stato
inizializzato e eventualmente inizializzarlo al volo in modo
da chiamare il costuttore di x prima di accedere a X::y ?


 da chiamare il costuttore di x prima di accedere a X::y ?
Mi riservo di fare delle verifiche prima di rispondere. Temo non
avverra' molto presto...
Ciao,
Nicola

una variabile statica definita in un'altra unita' di traduzione.
scusate la mia ignoranza ma mi sono perso; quando parli di variabile
statica a cosa ti riferisci? a una con linkage interno al modulo? o ad
una static di una classe? 
perchè nel primo caso chiaramente non avrebbe senso accedere ad essa
da un altro modo, dico bene? quindi stai parlando di una variabile
statica all'interno dello scope di classe?
oppure non ho capito niente?
Anto
--
Antonio Cuni, 18 anni, studente
Brainbench Certification: 
Master C++: 4.44, higher than 97% of all previous test takers.
Visual Basic 5: 3.06, higher than 77% of all previous test takers.
http://www.brainbench.com/transcript.jsp?pid=1301688

 una static di una classe?
In effetti "static" significa un po' troppe cose diverse. In
questo caso si stava parlando di variabili che hanno "static
duration" e quindi la visibilita' non e' importante (anche una
normale varibile "globale" cade in questa categoria):
sono quelle variabili che vivono quanto il programma; non
sono allocate sullo heap o sullo stack ma "staticamente".
Quando una variabile con questa caratteristica fa riferimento ad
un'altra variabile dello stesso genere nel suo costruttore allora
possono sorgere problemi in quanto il C++ non offre garanzie su
quale sara' l'ordine seguito nell'inizializzazione di queste
variabili se appartengono a compilation unit differenti e quindi
si corre il rischio di accedere a istanze in cui ancora il
costruttore non e' stato chiamato (con effetti disastrosi).
Lo stesso dicasi per variabili che fanno riferimento ad altre
nel codice del distruttore (le variabili a cui si accede
potrebbero gia' essere state distrutte).
HTH


del VC6.
Preferisco la posizione degli altri compilatori.
Anche se ad altri sembra piu' coerente la posizione del VC6, io trovo
la cosa molto contradittoria. Nel VC6 il costruttore dell'oggetto
membro statico e' considerato chiamato dal oggetto stesso, mentre il
distruttore e' considerato chiamato non dall'oggetto.
Queste regole di visibilita' non le capisco. In fondo il costruttore
costruisce qualcosa che non c'e'. Credo che un costruttore privato non
dovrebbe potere essere mai chiamato, se non da funzioni friend.
Il distruttore privato invece puo' essere richiamato in automatico dal
compilatore invece.
++++
Anche il MinGW (alias GCC per windows) accetta il distruttore privato
senza problemi.
-- 
Tieni per te il Papero se vuoi la mia email
Sito Papero -> 
http://utenti.tripod.it/papero

definisce solo un distruttore privato e non ha classi friend
Prova
class A {
public:
	A();
private:
	~A();
static A test;
};
A A::test;
int main()
{
   return 0;
}
e il MinGW smette di protestare.
Evidentemente (almeno per i cloni del GCC) le variabili statiche hanno
proprieta' diverse dalle variabili "automatiche".


compilatore invece.
Certamente il costruttore privato non puo' essere richiamato se non da
funzioni 
friend (o da funzioni che fanno parte della classe stessa). 
E', da vedersi se il costruttore di una statica di classe va considerato
come
chiamato dal contesto della classe o da un contesto globale (come detto
sopra).
Certamente pero' NON E' VERO che un distruttore privato puo' essere
richiamato
in automatico tout-court dal compilatore. Puo' essere richiamato (in
automatico
o meno) solo da un contesto che sia friend della classe o che sia nella
classe
stessa.
Anche in questo caso ovviamente resta aperta la solita questione:
qual'e' il 
contesto di costruzione/distruzione di una statica di classe ? Se la
risposta
a questa domanda e' che tale contesto e' esterno alla classe, allora una
statica come C::c1 e' un errore se il costruttore O il distruttore sono
privati.
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
 
-- 
Posted from 
adsl-21-135.38-151.net24.it
 [151.38.135.21] 
via Mailgate.ORG Server - 
http://www.Mailgate.ORG

A proposito di distruttori privati e VC++, ecco un caso in cui VC++
si comporta in maniera..."discutibile" ;-)
--------------8<---------------------------------------------------
#include <iostream>
class A {
   protected:
        A() {}
       ~A() {}
   public:
        virtual void f() const = 0;
};
class B : public A
{
   public:
       B(){}
      ~B(){}
     virtual void f() const { std::cout << "B::f()" << std::endl; }
};
main()
{
    try {
       throw B();
    }
    catch (const A& a)
    {
        a.f();
    }
    catch(...)
    {
        std::cout << "unexpected exception" <<std::endl;
    }
}
----------->8---------------------------------------------------
il compilatore gnu si comporta come ci si potrebbe aspettare, ma
indovinate col VC++ quale catch() viene eseguita...
C'e' voluto un pomeriggio intero per scoprire che tutto sta nel
dichiarare ~A() pubblico o protetto.
Ho cercato di darmi una spiegazione logica, ma il comportamento non
cambia se anziche' fare la throw di un temporano, "lancio" un'istanza
globale di B (in questo caso nella throw/catch non c'e' nessun oggetto
da distruggere).
Mah...


 da distruggere).
Con che sintassi "lanci" il tuo B globale? Perche' a meno di lanciare un
puntatore viene comunque fatta una copia.
Ciao,
Nicola

avverra' molto presto...
Forse in passato il compilatore borland ha tentato di implementare
quanto descritto dal draft (con costi notevoli).
Mi stupisce che pero' lo avessero fatto anche per le variabili
statiche... il check di controllo iniizalizzazione per le funzioni
credo sarebbe tollerabile (si tratta di pochi byte in piu' per
ogni funzione e un costo runtime modesto) ma per le variabili
statiche accedute dall'esterno sarebbe veramente un dramma.
Un trucco potrebbe essere anche verificare l'inizializzazione
di tutti i moduli a cui si fa *potenzialmente* riferimento e che
non si e' certi siano gia' stati inizializzati in ogni blocco di
istruzioni... sempre un overhead notevole, ma forse tollerabile
nella maggioranza dei casi.



La catch e' per reference, quindi perche' dovrebbe esserci una copia ?
class B : public A {...};
main()
{
   B b;
   try
   {
      throw b;
   }
   catch (A& a)
   {
      a.f();


 La catch e' per reference, quindi perche' dovrebbe esserci una copia ?
Perche' e' la throw che fa la copia.
Ciao,
Nicola

,

Accidenti, non lo sapevo... e' una cosa "insidiosissima".
Effettiamente ho fatto un paio di provette e si possono avere dei
comportamenti inaspettati:
Ad esempio c'e' una enorme differenza tra
catch(const Base &b) { ... ; throw b; }
e
catch(const Base &b) { ... ; throw; }
/fabio


Scott Meyers "More Effective C++", Addison Wesley. Obbligatorio. Per chi
non ama i propri occhi esiste anche in CD.
Ciao,
Nicola



Il formato CD non mi sembra affatto male... quasi non fa
rimpiangere la carta (quasi). Il CD pero' dalla sua ha
che costa poco e comprende 2 libri ("Effective C++" e
"More Effective C++" e una raccolta di articoli abbastanza
interessanti)


qual'e' il  contesto di costruzione/distruzione di una statica di classe ? 
Questo e' il punto.
Chi sa cosa dice lo standard?


Ho cercato di darmi una spiegazione logica,
Non c'e'. Questo codice funziona. Non so perche'.
class A {
   protected:
        A() {printf("A\n");}
       ~A() {printf("~A\n");}
   public:
        virtual void f() const = 0;
		  friend int main();
};
class B : public A
{
   public:
     virtual void f() const { printf("B::f()\n"); }
       B(){printf("B\n");}
      ~B(){printf("~B\n");}
};
int main()
{
    try 
	 {
       throw B();
    }
    catch (const A& a)
    {
        a.f();
    }
    catch(...)
    {
        printf("unexpected exception\n");
    }
	 return 1;


 Chi sa cosa dice lo standard?
Per il draft lo scope di costruzione di una statica di classe e'
esplicitamente la classe stessa. Pertanto la puoi costruire con un
costruttore dichiarato privato o protected.
Non dice nulla di speciale per la distruzione (tranne il fatto che
avviene con le stesse regole della distruzione degli oggetti a livello
namespace, ovvero al temine del programma e in ordine inverso alla
costruzione). Quindi sembrerebbe intendere che il distruttore deve
essere visibile nello scope di definizione della statica di classe (il
che in pratica significa che deve essere pubblico).
--


 >avverra' molto presto...
Nel draft il capitolo relativo e':
  3.6.2  Initialization of non-local objects
[basic.start.init]
Stando al draft il codice citato non da problemi perche' x e X::y sono
definiti nella stessa translation unit.
Diverso e' un caso come questo:
// file X.hpp
class X {
    public:
    static int y;
    X() { y=3; }
};
void f();
// file X.cpp
#include "x.hpp"
int X::y;
// file f.cpp
#include "x.hpp"
X x; // Istanza statica
void f(){}
// file main.cpp
#include "x.hpp"
int main()
{
    int i=X::y;
    f();
    return i;
}
In questo caso, stando al draft, main puo' ritornare 0 o 3 a seconda
dell'implementazione. Se e quanto le cose cambino nel definitivo ...
lo verifico appena ho il definitivo.


E' cosi'.
Ciao,
Nicola

Si, ma dove leggo di solito i libri, i CD son proprio scomodi.
Ciao,
Nicola
P.S. Cos'hai capito? In autobus, intendo :-)

 Si, ma dove leggo di solito i libri, i CD son proprio scomodi.
Io aggiungerei un prudente "...ancora.". ;-)
EMG