Dubbio costruttori

di il
13 risposte

Dubbio costruttori

Salve a tutti, avrei un dubbio riguardo questa classe che dovrebbe emulare un dado e il suo relativo main

Main:

#include <iostream>
#include <cstdlib>
#include <ctime>

#include "dado.h"

#define MAX_LANCI 10000000
#define LANCIO_BUONO 3
#define SEQ 10

using namespace std;

int main()
{
    Dado d;//creo istanza di Dado
    long int c=0;
    int i = 0; 
    srand(time(0));

    while (i++<MAX_LANCI && c<SEQ)
       {       
	  //uno o due lanci
	  //si vince quando 
         d.effettuaLancio(); 
          
         if (d.getUltimoLancio() == LANCIO_BUONO)
	    c++;
	else{
	  //cout << d.getUltimoLancio() << endl; 
	  c=0;
	}
       }

      cout << "Tot Lanci="  << (c==SEQ ? i : i-1) << ", c=" << c << endl; 
      cout << (c==SEQ ? "Hai vinto" : "Non hai vinto") << endl;       
}

Mentre questo codice riguarda la classe dado:




#include <iostream>
#include <cstdlib>
#include "dado.h"
#include <ctime>

Dado::Dado()
{
    srand(time(0)); // usa un seme di default
    effettuaLancio();
}

Dado::Dado(time_t seed) // il costruttore ha lo stesso nome della classe
{
    srand(seed);
    effettuaLancio(); 
}

void Dado::effettuaLancio ()
   {
      valoreUltimoLancio = //accesso ad una variabile che rappresenta parte dello stato dell'oggetto
          (short) (1 + rand()%6);
   }

short int Dado::getUltimoLancio () const
   {
      //commentaLancio(); metodo const, invocazione ok
      //valoreUltimoLancio = (1 + rand()%6); // non permesso
      //effettuaLancio(); // metodo non const, invocazione non permessa
      return  valoreUltimoLancio;
   }

ostream &operator<< (ostream &stream, Dado d)
   {
      stream << "Il dado attualmente presenta la faccia "
             << d.getUltimoLancio() << ".\n";
      return stream;  
   }   

e infine qui c'è header


#ifndef DADO_H //Se DADO_H non è definito. Serve per evitare di richiamare 2 volte lo stesso header (incluso in più file cpp) e quindi evitare un errore di ridefinizione.
#define DADO_H //definisci DADO_H altrimenti salta a endif

#include <string>
using namespace std;


class Dado {
      
public:  //***************************

   Dado();

   Dado (time_t seed);  

   //Cosa significa const dopo la dichiarazione del metodo? 
    //getUltimoLancio() NON potra' contenere codice che "modifica" oggetto
    //istanza di dado
   short int getUltimoLancio() const;  
   
   void effettuaLancio();
 
   void commentaLancio() const;  // anche questo e' const

   friend ostream &operator<< (ostream &stream, Dado d); //overloading operatore '<<'


private: //***************************
        
   short int valoreUltimoLancio; //membro privato, accessibile solo dal codice dei metodi della classe

};   // end class Dado

#endif
La mia domanda riguarda la classe dado in particolare questi costruttori:

Dado::Dado()
{
    srand(time(0)); // usa un seme di default
    effettuaLancio();
}

Dado::Dado(time_t seed) // il costruttore ha lo stesso nome della classe
{
    srand(seed);
    effettuaLancio(); 
}
come mai vi sono due costruttori?
Se il primo costruttore Dado::Dado() setta il seme e richiama la funzione lancio il secondo cosa fa?

13 Risposte

  • Re: Dubbio costruttori

    Uno non ha argomenti l'altro ha un argomento. Cosa non comprendi?
  • Re: Dubbio costruttori

    oregon ha scritto:


    Uno non ha argomenti l'altro ha un argomento. Cosa non comprendi?
    é proprio questo il problema perché farne 2?

    il primo inizializza il seme e richiama la funzione "effettualancio" mentre il secondo inizializza il seme e richiama anch'esso la funzione "effettualancio"
    perché farne 2 inoltre che significa l'argomento time_t seed?
  • Re: Dubbio costruttori

    Il costruttore con argomento si aspetta un seme dal chiamante. Quello senza argomento usa time(0) come seme. Mi pare semplice...
  • Re: Dubbio costruttori

    Io proprio non capisco il motivo di mettere un seme a che serve? scuami, se in questa parte di codice:
    
    
     while (i++<MAX_LANCI && c<SEQ)
           {       
    	  //uno o due lanci
    	  //si vince quando 
             d.effettuaLancio(); 
              
             if (d.getUltimoLancio() == LANCIO_BUONO)
    	    c++;
    	else{
    	  //cout << d.getUltimoLancio() << endl; 
    	  c=0;
    	}
           }
    
    
    io richiamo la funzione pubblica effettuaLancio quindi lui va qui (dado.cpp):
    
    void Dado::effettuaLancio ()
       {
          valoreUltimoLancio = //accesso ad una variabile che rappresenta parte dello stato dell'oggetto
              (short) (1 + rand()%6);
       }
    
    ed effettua il lancio con un dato a 6 facce come ci consiglia il 1+rand()%6 e lo fa i-volte ora mi chiedo a che serve questa parte:
    
    Dado::Dado()
    {
        srand(time(0)); // usa un seme di default
        effettuaLancio();
    }
    
    Dado::Dado(time_t seed) // il costruttore ha lo stesso nome della classe
    {
        srand(seed);
        effettuaLancio(); 
    }
    
    Non serve a nulla, però se la tolgo mi da errore io proprio non capisco.
  • Re: Dubbio costruttori

    Ma come non serve a nulla? Lo sai a cosa serve la funzione srand?
  • Re: Dubbio costruttori

    oregon ha scritto:


    Ma come non serve a nulla? Lo sai a cosa serve la funzione srand?

    Certo serve a settare un seme in questo caso srand(time(0)) lo setta a partire dal 1 Gen 1970 e da qui vi è la generazioni di numeri casuali, ma che senso ha se già lo abbiamo qui:
    
    
    void Dado::effettuaLancio ()
       {
          valoreUltimoLancio = //accesso ad una variabile che rappresenta parte dello stato dell'oggetto
              (short) (1 + rand()%6);
       }
    
    
    
  • Re: Dubbio costruttori

    Ma che dici? Non ti capisco... una è la funzione srand l'altra è la rand...
  • Re: Dubbio costruttori

    Se non inizializzi il seme tramite srand, la funzione rand ne usa uno predefinito e quindi produce sempre la stessa sequenza di numeri pseudo casuali ogni volta che riavvii il programma. Puoi usare come seme l'ora corrente, restituita da time(0), oppure in seme a tua scelta.

    time_t è il tipo di dato restituito da time(). Se gli dai un seme a tua scelta, come nel secondo costruttore, deve essere dello stesso tipo.

    https://en.cppreference.com/w/cpp/chrono/c/tim
    https://en.cppreference.com/w/cpp/chrono/c/time_
    https://en.cppreference.com/w/cpp/numeric/random/sran
    https://en.cppreference.com/w/cpp/numeric/random/ran
  • Re: Dubbio costruttori

    Ok in base a quello che mi hai detto ho fatto così: ho commentato il primo costruttore e nel main ho dato io un seme:
    
    #include <iostream>
    #include <cstdlib>
    #include "dado.h"
    #include <ctime>
    
    //Dado::Dado()
    //{
     //   srand(time(0)); // usa un seme di default
     //   effettuaLancio();
    //}
    
    Dado::Dado(time_t seed) // il costruttore ha lo stesso nome della classe
    {
        srand(seed);
        effettuaLancio(); 
    }
    
    Questo è il main:
    
    #include <iostream>
    #include <cstdlib>
    #include <ctime>
    
    #include "dado.h"
    
    #define MAX_LANCI 10000000
    #define LANCIO_BUONO 3
    #define SEQ 10
    
    using namespace std;
    
    int main()
    {
        Dado d(1234);//creo istanza di Dado
        long int c=0;
        int i = 0; 
        srand(time(0));
    
        while (i++<MAX_LANCI && c<SEQ)
           {       
    	  //uno o due lanci
    	  //si vince quando 
             d.effettuaLancio(); 
              
             if (d.getUltimoLancio() == LANCIO_BUONO)
    	    c++;
    	else{
    	  //cout << d.getUltimoLancio() << endl; 
    	  c=0;
    	}
           }
    
          cout << "Tot Lanci="  << (c==SEQ ? i : i-1) << ", c=" << c << endl; 
          cout << (c==SEQ ? "Hai vinto" : "Non hai vinto") << endl;       
    }
    
    
    Quindi in teoria dovrebbe darmi sempre lo stesso risultato, ma non lo guarda, questi sono i rusultati:
    
     Tot Lanci=10000000, c=0
      Non hai vinto
    
    Tot Lanci=10000000, c=0
    Non hai vinto
    
    Tot Lanci=10000000, c=1
    Non hai vinto
    
    Tot Lanci=10000000, c=0
    Non hai vinto
    
    Tot Lanci=3192983, c=10
    Hai vinto
    
    Tot Lanci=10000000, c=0
    Non hai vinto
    
    
    come puoi ben vedere non sono gli stessi in uno risulta adirittura che ho vinto.
  • Re: Dubbio costruttori

    Ma esegui la srand nel main! Ovvio che i valori cambiano!

    Ma scusa, ci prendi in giro?
  • Re: Dubbio costruttori

    Ripeto che, a parità di seme, non da sempre lo stesso risultato, ma sempre la stessa sequenza di risultati ogni volta che riavvii il programma.
    Prova ad eliminare tutte le srand e vedi che succede.
  • Re: Dubbio costruttori

    oregon ha scritto:


    Ma esegui la srand nel main! Ovvio che i valori cambiano!

    Ma scusa, ci prendi in giro?

    Non ci ho fatto caso è vero adesso non cambiano.
    Non mi era chiaro il motivo di srand() in questo specifico caso nel costruttore.
    Sono qui per imparare, non mi permetteri mai di prendervi in giro, certo, su cose nuove non sono un fulmine ad assimilare.
  • Re: Dubbio costruttori

    Ok ma se dici che non comprendi la presenza dal stand e poi la metti dicendo che non funziona come dovrebbe, cosa si deve pensare? Va bene imparare ma sono 4 righe in croce...
Devi accedere o registrarti per scrivere nel forum
13 risposte