Cerca nel sito:
ricerca
avanzata

Frasi Celebri...

Bont? divina, che bei diamanti. La bont? divina non ha nulla a che vedere con tutto questo, carino.

Mae West 

Sondaggio:

Chi vorreste come pilota alla Ferrari?

Montoya
Trulli
Fisichella
Alesi
R.Schumacher
Villeneuve
Hakkinen
Coultard

visualizza risultati


 

Classi template

 

La definizione di codice generico e in particolare di una classe template (le classi generiche vengono dette template class) non e` molto complicata, la prima cosa che bisogna fare e` dichiarare al compilatore la nostra intenzione di scrivere un template utilizzando appunto la keyword template:

    template < class T >
Questa semplice dichiarazione (che non deve essere seguita da ";") dice al compilatore che la successiva dichiarazione utilizzera` un generico tipo T che sara` noto solo quando tale codice verra` effettivamente utilizzato, il compilatore deve quindi memorizzare quanto segue un po' cose se fosse il codice di una funzione inline per poi istanziarlo nel momento in cui T sara` noto.
Vediamo come avremmo fatto per il caso della lista vista sopra:


  template < class TInfo >
  class TList {
    public:
      TList();
      ~TList();
      void Store(TInfo& Object);
      /* ... */

    private:
      class TCell {
        public:
          TCell(TInfo& Object, TCell* Next);
          ~TCell();
          TInfo& GetObject();
          TCell* GetNextCell();
        private:
          TInfo& StoredObject;
          TCell* NextCell;
      };

      TCell* FirstCell;
  };


Al momento l'esempio e` limitato alle sole dichiarazioni, vedremo in seguito come definire i metodi del template.
Intanto, si noti che e` sparita la dichiarazione della classe TInfo, la keyword template dice al compilatore che TInfo rappresenta un nome di tipo qualsiasi (anche un tipo primitivo come int o long double). Le dichiarazioni quindi non fanno piu` riferimento ad un tipo esistente, la` dove e` stato utilizzato il nome fittizio TInfo. Inoltre il contenitore non memorizza piu` tipi puntatore, ma riferimenti alle istanze di tipo.
Supponendo di aver fornito anche le definizioni dei metodi, vediamo come istanziare la generica lista:


  TList < double > ListOfReal;
  double* AnInt = new double(5.2);
  ListOfReal.Store(*AnInt);

  TList < Student > MyClass;
  Student* Pippo = new Student(/* ... */);
  ListOfReal.Store(*Pippo);                 // Errore!
  MyClass.Store(*Pippo);                    // Ok!


La prima riga istanzia la classe template TList sul tipo double in modo da ottenere una lista di double; si noti il modo in cui e` stata istanziato il template ovvero tramite la notazione

  NomeTemplate < Tipo >
(si noti che Tipo va specificato tra parentesi angolate).

Il tipo di ListOfReal e` dunque TList < double >. Successivamente viene mostrato l'inserzione di un double e il tentativo di inserimento di un valore di tipo non opportuno, l'errore sara` ovviamente segnalato in fase di compilazione.

La definizione dei metodi di TList avviene nel seguente modo:


  template < class TInfo >
  TList < TInfo >::
    TCell::TCell(TInfo& Object, TCell* Next)
         : StoredObject(Object), NextCell(Next) {}

  template < class TInfo >
  TList < TInfo >::TCell::~TCell() {
    delete &StoredObject;
  }

  template < class TInfo >
  TInfo& TList < TInfo >::TCell::GetObject() {
    return StoredObject;
  }

  template < class TInfo >
    TList < TInfo >::TCell*
      TList < TInfo >::TCell::GetNextCell() {
        return NextCell;
      }

  template < class TInfo >
  TList < TInfo >::TList() : FirstCell(0) {}

  template < class TInfo >
  TList < TInfo >::~TList() {
    TCell* Iterator = FirstCell;
    while (Iterator) {
      TCell* Tmp = Iterator;
      Iterator = Iterator -> GetNextCell();
      delete Tmp;
    }
  }

  template < class TInfo >
  void TList < TInfo >::Store(TInfo& Object) {
    FirstCell = new TCell(Object, FirstCell);
  }


Cioe` bisogna indicare per ogni membro che si tratta di codice relativo ad un template e contemporaneamente occorre istanziare la classe template utilizzando il parametro del template.

Un template puo` avere un qualsiasi numero di parametri non c'e` un limite prestabilito; supponete ad esempio di voler realizzare un array associativo, l'approccio da seguire richiederebbe un template con due parametri e una soluzione potrebbe essere la seguente:


  template < class Key, class Value >
  class AssocArray {
    public:
      /* ... */
    private:
      static const int Size;
      Key KeyArray[Size];
      Value ValueArray[Size];
  };

  template < class Key, class Value >
  const int AssociativeArray < Key, Value >::Size = 100;


Questa soluzione non pretende di essere ottimale, in particolare soffre di un limite: la dimensione dell'array e` prefissata. Fortunatamente un template puo` ricevere come parametri anche valori di un certo tipo:


  template < class Key, class Value, int size >
  class AssocArray {
    public:
      /* ... */
    private:
      static const int Size;
      Key KeyArray[Size];
      Value ValueArray[Size];
  };

  template < class Key, class Value, int size >
  const int AssocArray < Key, Value, size >::Size = size;


 

successivo
–«  INDICE  »–

 

 

 

 
Powered by paper&pencil (carta&matita ) - Copyright © 2001-2019 Cataldo Sasso