C++-manual
Förutgående | Kapitel 23. Typparametrisering | Nästa

# Ett konkret exempel

Vi skall nu visa hur man kan typparametrisera vår klass `Stack` så att den accepterar vilken datatyp som helst:

    template<class T>
    class Stack {
    public:
      // exceptions
      enum Exception { Underflow };

      // konstruktor
      Stack () : Top(0) { };
      ~Stack ();

      // metoder för stackmanipulation
      void push (const T & Data);
      T pop ();

    private:
      // ett element i stacken
      struct Element {
        // data för detta element
        T Data;
        // nästa element under detta i stacken
        Element * Previous;
      };

      // stackens topp
      Element * Top;
    };

    // destruktor
    template<class T>
    Stack<T>:~Stack () {
      // radera alla element
      try {
    	while ( pop () );
      }
      catch ( Exception E ) {
    	// stacken tom
      }
    }

    // push:a ett element på stacken
    template<class T>
    void Stack<T>::push (const T & Data) {
      // skapa nytt element
      Element * New = new Element;
      New->Data = Data;
      New->Previous = Top;

      // nytt toppelement
      Top = New;
    }

    // pop:a ett element från stacken
    template<class T>
    T Stack<T>::pop () {
      // är stacken tom?
      if ( Top == 0 ) {
        // stacken tom
        throw Underflow;
      }

      // spara data som är lagret i elementet
      T Data = Top->Data;

      // spara pekare till det element som blir nytt topp-element
      Element * Tmp = Top;
      Top = Top->Previous;

      // frigör minne och återvänd
      delete Tmp;
      return Data;
    }

Man definierar en templateklass genom att placera `template<class T>` framför klassdeklarationen. Parametern `T` kan heta vad som helst, men ofta används `T` eller `Type`. Här är `T` en parameter som representerar den datatyp som stacken skall använda. Det är en helt generisk typ, d.v.s. den kan vara vilken datatyp som helst. Alla förekomster av `char` har ersatts med vår nya typ `T`. Samma `template<class T>` måste även placeras före metoddefinitionerna, samt även ett `<T>` mellan klassens namn och `::`. Det hela ser tyvärr ganska fult ut. Man kan om man vill skriva `template<class T>` på samma rad som själva metod- eller klasdefintionen, men detta sätt är det som förekommer mest. Datatypen `T` används som parameter, returvärde, lokala värden och som del i den `struct` som definierats. Man kan tolka `T` som en helt vanlig datatyp.

## Instantiering av templateklasser

Nu har vi alltså definierat en första templateklass, nu är det dags att använda den också. Som man kunde gissa är även där syntaxen lite speciell. För att instantiera en `Stack` som fungerar på datatypen `int` kan vi använda följande sats:

    Stack<int> IntStack;

Denna kan sedan användas efter deklarationen precis som en vanlig stack utan extra "påhäng". Om man vill skicka stacken som en parameter till en funktion el.dyl. måste man använda det fulla namnet `Stack<int>`. Vi kan även instantiera en strängstack och en floatstack:

    Stack<string> S1;
    Stack<float> Values;

Vikan göra ett enkelt program som använder sig av en stack av `int` enligt följande (det är en adaption av programmet i Kapitel 12):

    int main () {
      Stack<int> S;
      char Choice = ' ';
      int Data;

      // iterera tills användaren vill avsluta
      while ( Choice != '3' ) {
        cout << "Välj: " << endl << "1 - push" << endl << "2 - pop" << endl;
        cout << "3 - sluta " << endl << "-> ";

        // läs in ett menyval
        cin >> Choice;

        // vad vill användaren göra
        switch ( Choice ) {
        case '1' :
           cout << "Elementets värde: ";
           cin >> Data;
           S.push ( Data );
           break;

        case '2' :
          // försök poppa ett element
          try {
            Data = S.pop ();
            cout << "Poppade: " << Data << endl;
          }
          catch ( Stack<int>::Exception E ) {
            // stacken top
            cout << "Stacken tom!" << endl;
          }
          break;
        }
      }
    }

Notera att stacken är definierad som `Stack<int> S;` och att vi således måste även använda samma typdefinition då vi fångar en excaption, alltså `Stack<int>::Exception E`.

Vi kan själv klart använda oss av olika instatieringar av vår `Stack`-klass i samma program, även samma funktion eller metod.

Förutgående | Hem | Nästa
Typparametrisering | Upp | Multipla parametrar