Newsgroup: it.comp.lang.c++
Titolo: Impedire allocazione oggetto

Come posso impedire all'interno del costruttore di una classe che questa
venga allocata?
Mi spiego. Sto programmando una serie di classi per la gestione
dell'hardware del PC e vorrei che in ogni programma non sia possibile
instaziare più di un oggetto per ogni classe per evitare conflitti.
Normalmente con una riga del genere viene allocato spazio per l' oggetto e
viene chiamato il costruttore.
ptr = new Classe1(2, 3);
Vorrei che nel costruttore vi sia del codice che deallochi se stesso e
ritorni NULL a ptr. E' possibile fare cio?
Ciao e grazie a chi si interesserà, Giuseppe.


Credo che ti basta ridefinire l'operatore new. Se è la prima classe la
allochi normalmente, se no ritorni NULL.
ciao, Leo
-- 
NOSPAM: Change L.G With my 
firstname.name
 in the reply address !
    .--.     
   |o_o |    Why going, when you are able to fly?
   |:_/ |    
  //   \ \   
 (|     | )  
/'\_   _/`\  Leopoldo Ghielmetti, EPFL-DMA ROSE, SETI SwissTeam Member
\___)=(___/

ciao, Leo
Potresti farmi un esempio (ho tante idee in testa, ma non so distinguere tra
quelle giuste e quele sbagliate).
Grazie per l'intressamento
Ciao, Giuseppe

 instaziare piů di un oggetto per ogni classe per evitare conflitti.
Potresti inserire nella classe una variabile statica che faccia da
contatore di istanze.
EMG

contatore di istanze.
A questo avevo già pensato per tenere conto degli oggetti allocati. A me
interessava un metodo per impedire l'allocazione dell'oggetto una volta
constatato che già un oggetto era stato allocato.
Ciao, Giuseppe

allochi normalmente, se no ritorni NULL.
Questo metodo non permette comunque di controllare il numero
di istanze create "staticamente", ovvero con una dichiarazione diretta.
La soluzione definitiva al problema dovrebbe essere nel pattern
Singleton che assicura che ci sia al piu` una istanza di una certa
classe.
Una buona descrizione del pattern la si trova su Design Pattern
Paolo
-----------------------------------------------------------------
  Paolo Marotta
  Computer Science, University of Pisa
  home:   
http://www.cli.di.unipi.it/~marotta
-----------------------------------------------------------------

contatore di istanze.
Non credo sia sufficiente, un oggetto potrebbe essere allocato
anche sullo stack senza ricorrere a new.


venga allocata?
Non nel modo che intendi tu; ma si puo' impedire che un costruttore 
venga *chiamato*, dichiarandolo privato, e fornendo un metodo 
statico di factory che fornisce le istanze.. solo che fornisce 
sempre la stessa (o NULL dopo la prima chiamata). 
In questo modo, ogni new() dall'esterno della classe verra' 
intercettata dal compilatore come non valida, garantendoti che tutte 
le costruzioni del tuo oggetto passino dalla factory; e quest' 
ultima - che e' un metodo della classe - sara' l'unica a poter fare 
la new(). 
Guardati le implementazioni di "singleton" per una discussione
approfondita. 
-- 
God is Real, unless declared Integer.

Una buona descrizione del pattern la si trova su Design Pattern
Ho letto di questi "patterns" su un post in questo NG ma purtroppo non so
neanche lontanamente cosa siano.
Potresti darmi un'infarinatura generale in modo che io possa poi addentrarmi
nell'argomento?
Grazie e ciao, Giuseppe

anche sullo stack senza ricorrere a new.
Mi sarei limitato ad allocare gli oggetti solo dinamicamente. Non vedo altra
soluzione.... :-(
Ciao, Giuseppe

 anche sullo stack senza ricorrere a new.
Potresti essere piů preciso? Non ho capito bene cosa intendi.
EMG

 approfondita. 
... o il "named constructor idiom" (comp.lang.c++ FAQ list, 10.7)
-- 
Maurizio Loreti                      
http://wwwcdf.pd.infn.it/~loreti/mlo.html
Un. of Padova, Dept. of Physics - Padova, Italy          
lor...@padova.infn.it

... o il "named constructor idiom" (comp.lang.c++ FAQ list, 10.7)
Dovo posso trovare documentazione sui pattern Singleton (che mi avevano già
consigliato in questo thread (si dice così?)) e la FAQ di comp.lang.c++?
Grazie e ciao, Giuseppe

 ... o il "named constructor idiom" (comp.lang.c++ FAQ list, 10.7)
Mi daresti l'indirizzo dove prelevare queste FAQ?
EMG

 Ciao e grazie a chi si interesserà, Giuseppe.
Questo e' il tipico caso in cui viene usato il pattern Singleton.
Esempio :
class Classe1
{
   private:
     static Classe1 * instance_ ;
     // altri membri della classe
     Classe1() {} // costruttore privato
   public:
     static Classe1 * instance() 
     {
	if (instance_ == 0) instance_ = new Classe1;
	return instance_ ;
     }
     // altri metodi pubblici
};
Ricorda di istanziare il membro statico nel .cpp :
Classe1 * Classe1 :: instance_ = NULL ;
Quando devi accedere all' oggetto di Classe1 fai
Classe1 * ptr = Classe1 :: instance();
l'oggetto verra' costruito la prima volta e le volte successive 
verra' restituita sempre la stessa istanza.
il costruttore e' privato, quindi e' impossibile istanziare
esplicitamente un oggetto di classe
sul distruttore ci sono due possibilita'
1) Puoi farlo privato, se non vuoi che l'istanza venga distrutta
2) Puoi renderlo pubblico, ma deve contenere l'istruzione 
   instance_ = 0;
   in modo che alla successiva istanziazione (si dice cosi ? ;)
   venga creata una nuova istanza.
Questo e' un pattern, nel senso che non e' un pezzo di codice che puoi
"tagliare" e "incollare" ma un idea da applicare ed adattare alle tue 
esigenze.
Ciao
*Fabio*
-- 
Lots of girls can be had for a song.  Unfortunately, it often turns out to
be the wedding march.

nell'argomento?
Detto in parole povere un pattern sarebbe una "soluzione assodata ad un
problema ricorrente". Esistono molti problemi che si presentano con
frequenza rilevante all'interno di tantissime applicazioni, i pattern sono
soluzioni collaudate per questi problemi.


Potresti essere più preciso? Non ho capito bene cosa intendi.
Con una banale dichiarazione:
TObject Object(/* ... */);
L'uso di un semplice contatore non impedirebbe questo...
e ricorrere al meccanismo delle eccezioni per abortire la
creazione dell'oggetto non sarebbe una buona soluzione.


consigliato in questo thread (si dice così?)) e la FAQ di comp.lang.c++?
Sul pattern singleton... (il singleton e` uno dei pattern piu` conosciuti).
Per info vedi "Design Pattern elements of object oriented software" di
Gamma, Helm, Johnson e Vlissides, Addison Wesley


 creazione dell'oggetto non sarebbe una buona soluzione.
Infatti avevo interpretato male io il problema sottopostoci.
EMG

 consigliato in questo thread (si dice così?)) e la FAQ di comp.lang.c++?
Per i pattern Singleton ti hanno gia' risposto; tutte le FAQ, e quella
di c.l.c++ in particolare sono su 
rtfm.mit.edu
, disponibili per
anonymous ftp; guarda in pub/usenet/comp.lang.c++/ .
Le FAQ sono disponibili anche in forma HTML (browsabile) sotto:
http://www.cerfnet.com/~mpcline/c++-faq-lite/
 ; da questo indirizzo si
possono anche prelevare, in formato .zip. .tar.Z o .tar.gz .
Come per quelle di comp.lang.c [*], si tratta di un subset del libro
che l'autore (Marshall Cline) ha pubblicato per Addison-Wesley (e che
val la pena di comperare IMHO; l'unica controindicazione a questi
acquisti `era la rapida evoluzione del linguaggio che rendeva obsoleti
manuali e FAQ in un batter d'occhio - ma adesso che abbiamo lo
standard...  yum, yum :-)
[*] che sono un subset del libro di Steve Summit per Addison-Wesley


> >... o il "named constructor idiom" (comp.lang.c++ FAQ list, 10.7)
... comunque, per completezza, ecco il testo:
========================================================================
[10.7] What is the "Named Constructor Idiom"?
A technique that provides more intuitive and/or safer construction operations
for users of your class.
The problem is that constructors always have the same name as the class.
Therefore the only way to differentiate between the various constructors of a
class is by the parameter list.  But if there are lots of constructors, the
differences between the constructors becomes somewhat subtle and error prone.
With the Named Constructor Idiom, you declare all the class's constructors in
the private: or protected: sections, and you provide public static methods that
return an object.  These static methods are the so-called "Named Constructors."
In general there is one such static method for each different way to construct
an object.
For example, suppose we are building a Point class that represents a position
on the X-Y plane.  Turns out there are two common ways to specify a 2-space
coordinate: rectangular coordinates (X+Y), polar coordinates (Radius+Angle).
(Don't worry if you can't remember these; the point isn't the particulars of
coordinate systems; the point is that there are several ways to create a Point
object).  Unfortunately the parameters for these two coordinate systems are the
same: two floats.  This would create an ambiguity error in the overloaded
constructors:
    class Point {
    public:
      Point(float x, float y);     // Rectangular coordinates
      Point(float r, float a);     // Polar coordinates (radius and angle)
      // ERROR: Overload is Ambiguous: Point::Point(float,float)
    };
    main()
    {
      Point p = Point(5.7, 1.2);   // Ambiguous: Which coordinate system?
    }
One way to solve this ambiguity is to use the Named Constructor Idiom:
    #include <math.h>              // To get sin() and cos()
    class Point {
    public:
      static Point rectangular(float x, float y);      // Rectangular coord's
      static Point polar(float radius, float angle);   // Polar coordinates
      // These static methods are the so-called "named constructors"
      // ...
    private:
      Point(float x, float y);     // Rectangular coordinates
      float x_, y_;
    };
    inline Point::Point(float x, float y)
    : x_(x), y_(y) { }
    inline Point Point::rectangular(float x, float y)
    { return Point(x, y); }
    inline Point Point::polar(float radius, float angle)
    { return Point(radius*cos(angle), radius*sin(angle)); }
Now the users of Point have a clear and unambiguous syntax for creating Points
in either coordinate system:
    main()
    {
      Point p1 = Point::rectangular(5.7, 1.2);   // Obviously rectangular
      Point p2 = Point::polar(5.7, 1.2);         // Obviously polar
    }
Make sure your constructors are in the protected: section if you expect Fred to
have derived classes.
The Named Constructor Idiom can also be used to make sure your objects are
always created via new[16.19].
========================================================================
All'ultimo commento puoi aggiungere che lo stesso trucco puo' servire
a creare un'unica istanza della classe (che era il problema originale).


> Dovo posso trovare documentazione sui pattern Singleton
Prova a leggere il tutorial
http://www.csc.calpoly.edu/~dbutler/tutorials/winter96/patterns/
e' semplificato, ma puo' servirti come introduzione.
Il libro che ti e' stato gia' indicato resta comunque la sorgente
fondamentale per studiare i pattern.
MM
Sent via Deja.com 
http://www.deja.com/
Share what you know. Learn what you don't.

 [snip]
A me era venuta un'altra idea, che è funzionalmente simile al codice da te
postato:
utilizzare una classe istanziatrice con membri statici che allocasse a
richiesta la mia classe.
Ho scelto questa strada perchè ciò che voglio implementare io è più
complesso e non limita l'instanziazione di un solo oggetto, bensì fa
controlli approfonditi su molte altre condizioni.
Ecco il codice:
class Allocatore
{
  friend Classe1;
Allocatore() : contatore(0) {};
static Classe1 *Alloca()
{
if(contatore==0) return new Classe1;  // Posso fare tutti i controlli che
voglio
return NULL;
};
static void Dealloca(Classe1 *Obj)
{
  delete Obj;
};
  int contatore;
};
class Classe1
{
 private:
  Classe1() { snip };
  ~Classe1() { snip };
public:
// ecc ecc
};
Grazie tante, Ciao