#include <iostream>
using namespace std;

class Numero {

public:
  // Costruttore 1: senza parametri.
  Numero();
  
  // Costruttore 2: con parametro
  Numero(const int&);
  
  // Distruttore
  ~Numero();
  
  // Metodo per impostare il valore
  void set_valore(const int&);
  
  // Metodo per ottenere il valore
  int get_valore() const;

private:
  int valore;
};


/* Implementazione dei metodi */

// Costruttore 1:
// - notare l'assenza di un tipo di ritorno (neanche void)
// - c'è una lista di inizializzazione prima del corpo
// - il corpo puo' essere vuoto, ma deve per forza esistere
Numero::Numero()
  : valore(0) // Lista di inizializzazione
{
  cout << "Richiamato il costruttore 1" << endl;
}


// Costruttore 2
Numero::Numero(const int& v)
  : valore(v)
{
  cout << "Richiamato il costruttore 2" << endl;
}

// Distruttore: in questo caso non ha niente di
// importante da fare.
// Non ci sono mai parametri.
Numero::~Numero()
{
  cout << "Richiamato il distruttore" << endl;
}

void Numero::set_valore(const int& v)
{
  valore = v;
}

int Numero::get_valore() const
{
  return valore;
}

/* Fine dell'implementazione dei metodi */


int main()
{
  Numero n1; // Viene richiamato il costruttore 1, senza parametri
  Numero n2(3); // Viene richiamato il costruttore 2, con il parametro 3
  
  // Viene richiamato il secondo costruttore su un oggetto temporaneo senza nome.
  // Una volta costruito l'oggetto, si richiama su di esso il metodo get_valore().
  // Alla fine dell'istruzione, l'oggetto temporaneo viene distrutto: si
  // richiama quindi il suo distruttore.
  cout << Numero(-5).get_valore() << endl;
  
  cout << n1.get_valore() << endl;
  n2.set_valore(15);
  cout << n2.get_valore() << endl;
  
  // Con questa istruzione si esce dalla funzione attuale: tutti gli oggetti
  // creati al suo interno vengono distrutti richiamando il loro distruttore.
  return 0;
}