C++ – Le classi modello: i template

Scritto da Gianjey | 17 ottobre, 2010 17:47

cplusplus

Nella stesura dell’ultima versione del programma di gestione prestiti, si è avuta l’esigenza di adattare la classe libreria in modo da contenere oggetti di tipo libSocio e non più di tipo libro per come era stata definita originariamente. Il problema è stato risolto sostituendo brutalmente, nella classe, le ricorrenze di libro con libSocio. È però importante osservare che si trattava, come anche evidenziato, di una soluzione temporanea. La biblioteca potrebbe avere necessità di gestire oltre che libri anche, per esempio, riviste o altro da poter prestare ai propri soci.

In pratica si tratterebbe di avere la possibilità di gestire nello stesso modo cose diverse: aggiungi, estrai, aggiorna, vanno bene perché soddisfano le necessità di gestione dei servizi della biblioteca, ma, come nel mondo reale, questi servizi dovrebbero poter essere applicabili a tutti gli oggetti disponibili nella biblioteca.

Il linguaggio C++ permette di definire classi che gestiscono elementi generici, caratteristica molto utile per la definizione di classi aggregato di oggetti, per esempio la libreria. Utilizzando questa caratteristica, una volta definita la classe libreria si avranno a disposizione i metodi per la gestione di oggetti generici e, se si dichiara che libreria contiene oggetti di tipo libro, il metodo estrai permetterà di estrarre un oggetto di tipo libro, se invece contiene oggetti di tipo libSocio, il metodo restituirà un oggetto di tipo libSocio.

// Definizione della classe modello libreria

#ifndef C_LIBRERIA4
#define C_LIBRERIA4

#include <vector>
using namespace std;

namespace biblioteca{
  template <class tag>	/*1*/
  class libreria{
  public:
    int aggiungi(tag);
    bool estrai(int, tag&) const;
    bool aggiorna(int, tag);
    int dotazione() const {return bib.size();};
  protected:
    vector<tag> bib;	/*2*/
  };

  // Aggiunge nella libreria un elemento generico

  template <class tag>	/*1*/
  int libreria<tag>::aggiungi(tag elem)	/*3*/
  {
    bib.push_back(elem);
    return dotazione()-1;
  };

  // Estrae le informazioni di un elemento

  template <class tag>	/*1*/
  bool libreria<tag>::estrai(int quale,tag& elem) const	/*3*/
  {
    bool estrattoOK=false;

    if(quale>=0 && quale<dotazione()){
      elem = bib.at(quale);
      estrattoOK=true;
    }

    return estrattoOK;
  };

  // Aggiorna i dati di un elemento esistente

  template <class tag>	/*1*/
  bool libreria<tag>::aggiorna(int quale,tag elem)	/*3*/
  {
    bool eseguito=false;

    if(quale>=0 && quale<dotazione()){
      bib.at(quale)=elem;
      eseguito = true;
    }
    return eseguito;
  };
}

#endif

Le righe 1 che precedono tutte le definizioni, specificano, appunto, che si tratta di una classe modello. Fra parentesi angolari (<>) è contenuta la parola chiave class e tag il nome, scelto dal programmatore, per identificare il tipo di classe trattato. Si tratta, sostanzialmente, di un segnaposto che verrà sostituito dal tipo effettivo quando la classe sarà utilizzata e che permette, alla classe stessa, la possibilità di riferirsi ad oggetti diversi. La 2 definisce un vettore che conterrà elementi di tipo tag.

Nella definizione dei metodi (3), il nome della classe è seguito dalle parentesi angolari con il segnaposto.

 Indice corso: C++ Appunti di Programmazione Fonte: prof. Nunzio Brugaletta 

Lascia un Commento