| C++-manual | ||
|---|---|---|
| Förutgående | Kapitel 23. Typparametrisering | Nästa |
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.
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 |