Parametrisierte funktionen und klassen
Parametrisierte Funktionen und Klassen
1 Allgemein
Templates = Schablone
Typen als Parameter
Compiler generiert automatisch mehrere Funktions- bzw. Klassen-Definitionen
= parametrisierte Funktionen, Funktions-Schablonen, generische Funktionen
Beispiel: Funktion max soll das Maximum zweier Werte bestimmen
ohne Template
int max(int a, int b)
{
return a > b ? a : b;
}
float max(float a, float b)
{
return a > b ? a : b;
}
TYP max(TYP a, TYP b)
{
return a > b ? a : b;
}
mit Template
template <class TPar>
TPar max (TPar a, TPar b)
{
return a > b ? a : b;
}
ist noch keine Funktions-Definition!
wird vom Compiler benutzt, um bei "Bedarf" eine echte Funktions-Definition zu erstellen (=Instanzierung)
"Bedarf" = 1. Aufruf
void main()
{
...
cout << max (3, 17);
.
..
cout << max (17, 25);
...
cout << max (3.
14, 0.81);
...
}
cout << max (3, 17); erzeugt erste Instanz (TPar = int):
int max (int a, int b)
{ ..
.}
cout << max (17, 25); erzeugt keine weitere Instanz (TPar = int), da Template für int bereits existiert!
cout << max (3.14, 0.81); erzeugt zweite Instanz (TPar = double):
double max (double a, double b)
{ ...
}
Typen muessen exakt uebereinstimmen, keine automatische Konvertierungen!
... max (10, 3.14) ..
. fuehrt zu Fehler (Could not find a match for 'max(int, double)')
jeder Template-Parameter muss auch als Funktions-Parameter vorkommen
Template-Parameter eines Funktions-Templates muessen Typ-Parameter (class) sein
Funktion kann neben Template-Parametern auch "normale" Parameter haben
template <class T>
T mittel (T *a, int n)
{
T summe = 0;
for (int i=0; i<n; i++) summe+=a[i];
return summe/n;
}
....
int feld[] = {1, 2, 4, 10, 12};
cout << mittel (feld, 6);
float feld2[] = {1.
2, 2.4, 3.6};
cout << mittel (f2, 3);
3 Klassen-Templates
= parametrisierte Klassen, Klassen-Schablonen, generische Klassen
wichtige Anwendung: Container-Klassen (z.B. BIDS von Borland)
Beispiel:
Deklaration
template <class ElTyp>
class STACK
{
ElTyp *top;
ElTyp *bottom;
ElTyp *current;
public:
STACK (int gr=100);
~STACK();
void push(ElTyp e);
ElTyp pop();
int empty();
int full();
};
Implementierung der Element-Funktionen als Funktions-Templates
template <class ElTyp>
STACK <class ElTyp>::STACK (int gr)
{
bottom = current = new ElTyp [gr];
top=bottom+gr;
}
template <class ElTyp>
STACK <class ElTyp>::~STACK ()
{
delete [] bottom;
}
template <class ElTyp>
STACK <class ElTyp>::void push (ElTyp e)
{
if (current!=top) *current++=e;
}
template <class ElTyp>
STACK <class ElTyp>::ElTyp pop ()
{
if (current>bottom) current--;
return *current;
}
template <class ElTyp>
STACK <class ElTyp>::int empty ()
{
return current==bottom;
}
template <class ElTyp>
STACK <class ElTyp>::int full ()
{
return current==top;
}
main()
..
..
STACK<int> iStack(10);
STACK<float> fStack;
typedef STACK<char*> szSTACK;
szSTACK sSTACK;
...
iStack.
push(17);
sStack.push("Karli");
....
bei Klassen-Templates können auch "normale" Parameter (nicht class) als Template-Parameter angegeben werden.
Beispiel: Default-Stackgroesse
template <class ElTyp, int defge>
class STACK
{
ElTyp *top;
...
public
STACK (int gr=grdef);
...
};
main()
....
STACK<int, 100>
..
..
Hinweis: Klasse zuerst mit konkretem Typ entwickeln und testen, erst danach parametrisieren!
Anmerkungen: |
| impressum | datenschutz
© Copyright Artikelpedia.com