C++-manual
Förutgående |  | Nästa

# Kapitel 23. Typparametrisering

I detta avsnitt redogörs för grunderna i hantering av generiska klasser, s.k. template-klasser.

# Iden med templates

De flesta program behöver spara data i någon form under sin körtid. Vanligen används någon form av datastruktur för detta data, t.ex. en vektor, lista, kö, stack, hashtabell el.dyl. Det är relativt vanligt att dessa datastrukturer inkapslas i en klass så att de skall vara lättare att använda och utvidga eller specialisera via ärvning. Vi kan ta som exempel den stack som fungerade som exempel i Kapitel 12. Vi moderniserar den så att vi får en en Stack-klass:

    class Stack {
    public:
      // exceptions
      enum Exception { Underflow };

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

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

    private:

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

      // stackens topp
      Element * Top;
    };

    // push:a ett element på stacken
    void Stack::push (const char 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
    char Stack:: pop () {
      // är stacken tom?
      if ( Top == 0 ) {
    	// stacken tom
    	throw Underflow;
      }

      // spara data som är lagret i elementet
      char 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;
    }

Denna stack är totalt dynamisk och enkel att använda. De enda metoderna som finns är metoder för att lägga till ett element och ta bort det översta elementet. Den använder sig av en exception (se Kapitel 20) för att rapportera ett fel om man försöker poppa ett element ur en tom stack. Denna stack fungerar dock endast med data av typen `char`. Det är inte svårt att ändra om den att fungera med olika datatyper, det enda som behöver ändras är själva datatypen, all övrig kod hålls intakt. Vi kunde skapa olika versioner för olika datatyper, t.ex. `CharStack`, `IntStack` och `StringStack`. Låter det som slöseri med tid och minne, eftersom de olika klasserna är i princip identiska? Blir det inte problem med att hålla alla klasser uppdaterade om det blir ändringar?

Det hela går att sköta enklare och elegantare med templates (typparametrisering). Med typparametrisering menas att man gör den datatyp som en klass opererar på som en parameter. Vi kan alltså skapa en `Stack` och ge den typ vi vill ha som en parameter. Kompilatorn genererar sedan åt oss en stack som använder sig av just den datatyp vi vill använda. Vi kan således enkelt använda stackar för olika datatyper i samma program, men använda endast en version av koden.

Templates används oftast för att skapa containers, d.v.s. klasser som är menade att innehålla objekt av någon typ. I och med att containers vanligen är ganska generiska och olika typer inte kräver speciellt mycket olika kod (om alls) används templates i hög grad. Man kan även använda templates för att kapsla in t.ex. generiska algoritmer. Templates är det närmaste C++ kommer då det gäller att skriva kod som är typoberoende, d.v.s. där samma kod kan användas för olika datatyper. Vi kommer senare att se på en hel del olika fördefinierade templates i Kapitel 24.

Förutgående | Hem | Nästa
Serialisering |  | Ett konkret exempel