Newsgroup: it.comp.lang.c++
Titolo: Costruttore correttore

Vorrei fare una domanda: si può in qualche modo "interrompere" il
costruttore? Come al solito, per spiegarmi ricorro ad un esempio:
class Numero
{
 private:
  int     x;
 public:
    Numero (int y)
    {
     if (y >= 0 && y <= 16)
      x = y;            //  OK
     else
      x = -1;          //  ERRORE
    }
};
..............
Number *n = new Number (-4);
Tralasciando la dubbia utilità pratica di questo codice, volevo sapere se
c'é un modo per restituire (tramite costruttore) alla variabile n il valore
NULL, nel caso in cui il parametro passato sia non valido (nel caso il
valore deve essere tra 0 e 16). Avevo pensato di usare un'istruzione del
tipo:
this = NULL;
ma non è possibile farlo. Come posso fare? Grazie e ciao
                                    Marchisio Stefano
P.S.: non importa se il codice che ho scritto fosse inesatto, l'ho scritto
di botto, solo per rendere l'idea.

 NULL, nel caso in cui il parametro passato sia non valido
Il costruttore non può avere valore di ritorno e, come hai potuto
constatare, this è passato per valore (e meno male, perché, se fossi
riuscito ad impostarlo a NULL, avresti avuto seri problemi). Un approccio al
problema prevede le eccezioni:
#include <new>
class Numero
{
 private:
  int     x;
 public:
    Numero (int y) throw(int)
    {
     if (y >= 0 && y <= 16)
      x = y;            //  OK
     else
        throw -1;
    }
};
int main(int, char *[])
{
    Numero *n;
    try{
        n=new Numero(-4);
    }catch(std::bad_alloc){
        return -1;
    }
    //...
    delete n; //n.~Numero() non viene eseguito
    return 0;
}
Questo metodo ha però ha l'inconveniente di lasciare l'istanza in uno stato
"comatoso" che ha la conseguenza di impedire, per sicurezza, il richiamo
automatico del distruttore su un'istanza inconsitente al termine della sua
vita.
Proverei con:
class Numero
{
 private:
  int     x;
 public:
    bool state()
    {return x!=-1;}
    Numero (int y)
    {
     if (y >= 0 && y <= 16)
      x = y;            //  OK
     else
      x = -1;          //  ERRORE
    }
};
int main(int, char *[])
{
    Numero n(-4);
    if(!n.getstate())
        return -1;
    //...
    return 0;
}//n.~Numero() viene eseguito
E' più sicuro dell'approccio precedente ed è più comodo.
Saluti

valore deve essere tra 0 e 16).
No. Quello che puoi fare e' lanciare una exception.
Il costruttore non sa se e' stato chiamato da new, da una
costruzione esplicita in-place oppure da una allocazione
su stack o in memoria statica.
L'unico che puo' fare in modo di restituire il puntatore
nullo e' chi alloca la memoria che pero' per contro non
sa quale e' l'oggetto in fase di allocazione.
In realta' e' anche possibile fare in modo che una
chiamata di new (se non specificato altrimenti) usi
una funzione della classe stessa per ottere la memoria...
ma in ogni caso questa funzione non riceve i parametri
del costruttore.
Se veramente per te e' importante usare puntatori
e tornare il puntatore nullo invece di lanciare una
exception puoi usare un approccio di questo tipo...
  class MyClass
  {
    private:
      MyClass(int x);  // Costruttore *privato*
      bool is_valid(); // Check riuscita costruzione
    public:
      // Funzione *static* pubblica di allocazione
      static MyClass *New(int x)
      {
        MyClass *m = new MyClass(x);
        if (!m->is_valid())
        {
          delete m;
          m=0;
        }
        return m;
      }
  };
  void foo()
  {
    ...
    MyClass *p = MyClass::New(x);
    if (p)
    {
      ... Ok ...
      delete p;
    }
    else
    {
      ... Problemi ...
    }
  }
HTH
Andrea

 costruttore? Come al solito, per spiegarmi ricorro ad un esempio:
non esattamente, pero` questo e` uno dei casi in cui utilizzare 
proficuamente le eccezioni:
class Prova {
public:
        class Cannot_construct { };
        Prova() {
                if (...)
                        throw Cannot_construct();
        }
};
void f()
{
        try {
                Prova p;
        }
        catch(Prova::Cannot_construct) {
                ...
        }
}
ciao Anto
-- 
Antonio Cuni, 19 anni, studente
Brainbench C++ Master: 4.73, higher than 99% of all previous test takers.
C Language: 3.79, higher than 92% of all previous test takers.
Guida C/C++ di Programmazione.it: 
http://cpp.programmazione.it

 E' piů sicuro dell'approccio precedente ed č piů comodo.
Non mi pare una gran soluzione, perche' in questo modo tutti i metodi di
Numero devono controllare lo stato prima di compiere qualsiasi
operazione e prevedere la possibilita' di segnalare un errore.
La soluzione migliore e' quella basata sulle eccezioni.
Ciao,
Nicola
[1] In realta' le cose sono un po' piu' complesse, ma non in questo
caso.

Andrea,
questa è proprio la soluzione che cercavo!!! Grazie e complimenti per
l'ottima pensata del "costruttore privato - similcostruttore pubblico". Ciao
                                            Marchisio Stefano