domenica, novembre 05, 2006

Sulle classi.

Piuttosto che la data, ho scelto un esempio simile, cioe' l'orario: solo perche' e' piu' facile sommare minuti e secondi piuttosto che giorni, visto che i mesi hanno lunghezze diverse in modo irregolare. La classe che ho riportato e' semplicemente un esempio, con tutti i limiti del caso.
Provo a fare una lista di commenti.


  • Come in ogni altra dichiarazione in C++, la dichiarazione di una classe deve contenere tutte a definizione della classe. Vale a dire, tutte le sue variabili e tutte le funzioni che si vogliono utilizzare.
  • Se non viene indicato nulla, il C++ inerpreta gli elementi di una classe come fossero di tipo "private". Per questo, e' sempre meglio indicare sempre le parole chiave "public" e "private" lungo la definizione della classe.
  • Rispondendo ad una domanda, si possono mettere vettori nelle classi (ad esempio per un istogramma), in una classe si puo' mettere qualunque cosa sia gia' stata definita (anche un'altra classe). Tuttavia, nel caso specifico di questo esempio non serve: anche se ore, minuti e secondi hanno due cifre, rimangono un solo numero.
  • e' buona norma cercare di dividere sempre in 3 file distinti il codice:

    • orario.h e' la definizione della classe, senza implementazioni (salvo eccezioni particolari che si vedranno in seguito);
    • orario.cce' dove la classe viene implementata, cioe' dove vengono scritti i suoi metodi (funzioni);
    • i programmmi che usano la classe.

    Sia l'implementazione (orario.cc) che i programmi che usano la classe
    includono la definizione, con #include "orario.h". Per evitare che la definizione venga fatta due volte (che per il compilatore e' un errore), si utilizzano le seguenti istruzioni al pre-processore.





    #ifndef orario_h

    controlla se e' gia' definita una variabile con nome "orario_h" (if), se NON e' definita fa quello che e' scritto sopra, altrimenti va fino all'#endif

    #define orario_h

    definisce la variabile "orario_h", sicche' al secondo tentativo di definizione il pre-compilatore salta

    #endif

    fine dell'if


Ecco i codici. Come al solito, si compilano con:

prompt> c++ -o testOra orario.cc testOra.cpp

orario.h

//! questo serve per garantire l'unicita' della definizione
//! lungo tutto il programma
#ifndef orario_h
#define orario_h

//! il prototipo della classe deve contenere _tutte_ le definizioni
//! della classe: variabili (membri), funzioni (metodi), contruttori,
//! distruttore
class orario
{
//! questa e' la parte della classe che il programma puo' vedere
public :

orario () ;

orario (const int & secondi,
const int & minuti,
const int & ore) ;

~orario () ;

void stampa () ;
void avanti (int ore,
int minuti,
int secondi) ;

//! questa e' la parte della classe accessibile solo alla classe stessa,
//! cioe' che solo le funzioni della classe possono vedere
//! ci possono stare sia variabili che funzioni
private :

//! le variabili di una classe sono spesso identificate con
//! un codice per comodita', in questo caso c'e' "m_" davanti a tutte
int m_secondi ;
int m_minuti ;
int m_ore ;

} ; //! questo punto-e-virgola e' necessario!


#endif

orario.cc
//! nel fine ".cc" vengono scritte tutte le implementazioni
//! delle funzioni di una classe.
//! per fare in modo che il C++ riconosca l'appartenenza alla classe,
//! si mette "nomeclasse::" davanti (in questo caso, "orario::")

#include <iomanip>
#include <iostream>
//! questo serve per leggere le definizioni della classe
#include "orario.h"

//! questo e' il costruttore: viene chiamato ogni volta che
//! un oggetto viene creato nel seguente modo:
//! orario nuovoOggetto ;
orario::orario () :
// questa e' la lista di inizializzazione"
// e' la prima cosa che viene fatta ed inizializza i membri della classe
// ai valori messi in parentesi
m_secondi (0) ,
m_minuti (0) ,
m_ore (0)
{
std::cout << "orario impostata: " ;
stampa () ;
}


// ----------------------------------------------------------------


//! in una classe possono essere definiti piu' di un costruttore:
//! nel nostro caso, quello sopra di chiama "di default" ed e' quello
//! che viene chiamato quando l'oggetto e' definito senza argomenti,
//! mentre questo sotto e' usato quando all'oggetto viene dato un
//! valore iniziale (es: "orario adesso (23,27,13) ;")
orario::orario (const int & secondi,
const int & minuti,
const int & ore) :
m_secondi (secondi) ,
m_minuti (minuti) ,
m_ore (ore)
{
std::cout << "orario impostata: " ;
stampa () ;

}


// ----------------------------------------------------------------


//! questo e' il distruttore della classe,
//! nel nostro caso non fa niente
orario::~orario () {} ;


// ----------------------------------------------------------------


void orario::stampa ()
{
std::cout << std::setfill ('0') << std::setw (2) << m_ore << ":"
<< std::setfill ('0') << std::setw (2) << m_minuti << ":"
<< std::setfill ('0') << std::setw (2) << m_secondi << std::endl ;
}


// ----------------------------------------------------------------


void orario::avanti (int ore,
int minuti,
int secondi)
{
m_secondi += secondi ;
m_minuti += m_secondi / 60 ;
m_secondi %= 60 ;

m_minuti += minuti ;
m_ore += m_minuti / 60 ;
m_minuti %= 60 ;

m_ore %= 24 ;
}

testOra.cpp
#include <iostream>
#include "orario.h"

int main ()
{
//! uso il costruttore di default
orario prima ;
//! uso il costruttore con 3 argomenti
orario unPoDopo (10,0,0) ;

std::cout << "stampo prima:\n" ;
prima.stampa () ;
std::cout << "stampo unPoDopo:\n" ;
unPoDopo.stampa () ;
std::cout << "mando avanti unPoDopo....:\n" ;
unPoDopo.avanti (1,3,56) ;
std::cout << "stampo unPoDopo:\n" ;
unPoDopo.stampa () ;

return 0 ;
}

Nessun commento: