Newsgroup: it.comp.lang.c++
Titolo: Che si fa in questi casi?

Salve, ancora io, purtroppo.
C'č un esempio in "Thinking in C++", che riporto qui sotto.
In questi casi cosa si fa?
Anche perchč avrei l'esigenza di passare dei valori diversi al costruttore
per istanziare un oggetto in base al valore della condizione nello switch
(cioč creare differenti istanze della stessa classe mediante una scelta
condizionale di tipo switch).
// C06:Nojump.cpp
// Can't jump past constructors
class X {
public:
  X();
};
X::X() {}
void f(int i) {
  if(i < 10) {
  //! goto jump1; // Error: goto bypasses init
  }
  X x1;  // Constructor called here
 jump1:
  switch(i) {
    case 1 :
      X x2;  // Constructor called here
      break;
  //! case 2 : // Error: case bypasses init
      X x3;  // Constructor called here
      break;
  }
}
int main() {
  f(9);
  f(11);
}///:~

 }///:~
Non vedo il problema; basta fare, ad esempio:
void f(int i)
{
  X tmp;     // inizializza la classe
  if(i < 10)
  {
    goto jump1;
  }
  tmp = X(/*...*/);
  jump1:
  switch(i)
  {
    case 1 :
      tmp = X(/*...*/);
      break;
    case 2 :
      tmp = X(/*...*/);
      break;
  }
}
Oppure, meglio, calcolare in base a switch il parametro del costruttore e solo alla
fine istanziare la classe.

In definitiva dichiaro una variabile di tipo X , ma definisco questa
variabile in base al valore del parametro dello switch?

Dico una stupidaggine !!! Se dichiaro prima una variabile di tipo X,
X tmp;
stò chiamando il costruttore di default per tmp...
per cui se tento di chiamarlo ancora per lo stesso tmp mi ritrovo un errore
del compilatore che mi dice:
Error:  prova.cpp(xxx,yyy):Multiple declaration for 'tmp'
Ma, perdonami...
tmp = X(/*...*/);
questa istruzione proprio non la capisco !!! Assegni ad una variabile la
chiamata del costruttore col nome della classe????
Non capisco, invece perchè non può essere facente parte dello standard una
cosa di questo tipo:
void CLASSE_1:: Metodo_1(int NUMERO,   UL_int first_l_e,UL_int first_r_e,
                                                       UL_int
second_l_e,UL_int second_r_e,
                                                       UL_int
third_l_e,UL_int third_r_e){
               // X   tmp;  X è una classe, chiaramente
               for(int i=0; i<NUMERO; i++)
                {
                  switch(i)
                   {
                     case 0:
                            X   tmp (first_l_e,first_r_e);
                            sack_list.push_front(tmp);
                          break;
                     case 1:
                            X   tmp (second_l_e,second_r_e);
                            sack_list.push_front(tmp);
                            break;
                     case 3:
                            X   tmp (third_l_e,third_r_e);
                            sack_list.push_front(tmp);
                            break;
                     }
                  }
               }
In questo caso non è assicurata in ogni caso la chiamata ad un costruttore
???
Non capisco qual'è l'errore logico che si commetterebbe nell'accettare una
dicitura di questo genere.
Bye,
Sebastiano
P.S.
Mi dici:
---------------------
Oppure, meglio, calcolare in base a switch il parametro del costruttore e
solo alla
fine istanziare la classe.
--------------------
ma a me serve creare tre oggetti diversi....
Potrei fare di usare dei parametri temporanei, che sono assegnati in base al
valore del parametro dello switch, e poi chiamare il costruttore alla fine.
In definitiva, una soluzione del genere:
void CLASSE_1:: Metodo_1(int NUMERO,   UL_int first_l_e,UL_int first_r_e,
                                                       UL_int
second_l_e,UL_int second_r_e,
                                                       UL_int
third_l_e,UL_int third_r_e){
               /* X   tmp;  X è una classe, chiaramente*/
               for(int i=0; i<NUMERO; i++)
                {
                  switch(i)
                   {
                     case 0:
                            edge_1=first_l_e;
                            edge_2=first_r_e;
                            break;
                     case 1:
                            edge_1=second_l_e;
                            edge_2=second_r_e;
                            break;
                     case 2:
                            edge_1=third_l_e;
                            edge_2=third_r_e;
                            break;
                     }
                  X tmp(edge_1,edge_2);
                  sack_list.push_front(tmp);
                   /* Cosi sarei riuscito a creare tre oggetti diversi ed a
metterli tutti quanti in una lista.*/
                  }
               }
Che ne pensi?


E' quello che ti avevo suggerito!
Comunque ora che hai scritto quello che vuoi fare la soluzione migliore è:
    for(int i = 0; i < NUMERO;  i++)
   {
       switch(i)
       {
          case 0:
             sack_list.push_front(  X(first_l_e, first_r_e) );
             break;
          case 1:
             sack_list.push_front(  X(second_l_e, second_r_e)  );
             break;
          case 3:
             sack_list.push_front(  X(third_l_e, third_r_e)  );
             break;
        }
   }
Non hai alcun motivo di creare delle variabili temporanee nello scope del switch.
Ti domandi perchè non è possibile fare come volevi.
Ecco un esempio in cui si avrebbero problemi:
  switch(i)
  {
     case 0:
       X tmp;
       // non uso break
     case 1:
       X tmp;
       break;
    };
Manlio Perillo

 wrote :
[...]
| tmp = X(/*...*/);
|
| questa istruzione proprio non la capisco !!! Assegni ad una variabile la
| chiamata del costruttore col nome della classe????
la chiamata X(/*params*/) crea un oggetto temporaneo di classe X, che poi
viene copiato sull'oggetto tmp.
e' meglio (e piu' chiaro rispetto a cosa succede in realta'), dello
scrivere
tmp(params);
| P.S.
| Mi dici:
| ---------------------
| Oppure, meglio, calcolare in base a switch il parametro del costruttore e
| solo alla
| fine istanziare la classe.
| --------------------
|
| ma a me serve creare tre oggetti diversi....
|
| Potrei fare di usare dei parametri temporanei, che sono assegnati in base
al
| valore del parametro dello switch, e poi chiamare il costruttore alla
fine.
[...]
| Che ne pensi?
che sarebbe meglio il pattern builder, o abstract factory.


...
Perche' non un banale
   sack_list.push_front( X(first_l_e,  first_r_e)  );
   sack_list.push_front( X(second_l_e, second_r_e) );
   sack_list.push_front( X(third_l_e,  third_r_e)  );
Andrea
--
Andrea Griffini, Programmer
http://www.netservers.com/~agriff

 che sarebbe meglio il pattern builder, o abstract factory.
Scusa, ma che cosa sono il "pattern builder" e "abstract factory"?
Non ha mica a che fare con la costruzione (e distruzione) di un oggetto in due fasi?
( tipo   X tmp; tmp.init(); // ...; tmp.destroy(); )
Manlio Perillo

 wrote :
| > che sarebbe meglio il pattern builder, o abstract factory.
|
| Scusa, ma che cosa sono il "pattern builder" e "abstract factory"?
| Non ha mica a che fare con la costruzione (e distruzione) di un oggetto
in due fasi?
| ( tipo   X tmp; tmp.init(); // ...; tmp.destroy(); )
|
No. detto in breve ( e percio' male ) i pattern sono soluzioni ad un
problema in un contesto. Non sono ne' programmi, ne' librerie, ma metodi di
risolvere i problemi. Questi due disaccoppiano la creazione di una classe,
affidandola ad un Builder, od una Factory, le quali hanno un'interfaccia
verso cui i programmi client chiedono una istanza della classe, e il tipo
concreto si occupa del creare la classe, a seconda dei parametri passati.
In pratica tu scrivi
Obj* oggetto = Fatcory->GetObj(params, mode);
ed e' la factory ad occuparsi della creazione classe. Se la classe cambia
Obj, cambi solo la factory e non il client.
Esiste tutto un movimento sui pattern, e una qualsiasi ricerca con OOP e
Pattern su di un motore, ti dara' miriadi di link.