Twitter und Facebook-Anbindung
X
Tweet Follow @twitterapi
!!! Anbindung an twitter und facebook öffnen !!!

Wenn Ihnen mein Online-Buch gefällt,
dann bedanken Sie sich doch mit einer kleinen Spende...

24.3 Funktionstemplates

24.3 Funktionstemplates

Als erstes fange ich mit Funktionstemplates an, weil man hier am schnellsten zeigen kann, was eigentlich im Hintergrund passiert. Im ersten Schritt werde ich also ein ganz kleines Template entwerfen, welches nichts anderes macht, als zwei Datentypen zu addieren. Das macht zwar in der Realität absolut keinen Sinn, weil man für so etwas keine Funktion braucht, aber man sieht sehr schön was passiert und wie es gemacht wird. Schauen wir uns mal an, wie so ein kleines Projekt mit einem solchen Template aussehen könnte.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
					
#include <stdio.h>

// Funktionstemplate //////////////////////////////////////////////////////////
template<typename TResultDataType, typename TParameterDataType>
TResultDataType Addiere(TParameterDataType tElement1, TParameterDataType tElement2) {
	return static_cast<TResultDataType>(tElement1) + static_cast<TResultDataType>(tElement2);
} // Addieren /////////////////////////////////////////////////////////////////



// Hauptfunktion der Anwendung ////////////////////////////////////////////////
int main(int argc, char** argv) {
	int iValue1		= 10;
	int iValue2		= 20;
	long int iErgebnis	= Addiere<long int, int>(iValue1, iValue2);

	double dValue1		= 1.5;
	double dValue2		= 2.7;
	float fErgebnis	= Addiere<float, double>(dValue1, dValue2);

	printf("Ergebnis der Addition ist %li\n", iErgebnis);
	printf("Ergebnis der Addition ist %g\n", fErgebnis);

	return 0;
} // main /////////////////////////////////////////////////////////////////////
					

Ausgabe:

Ergebnis der Addition ist 30
Ergebnis der Addition ist 4.2
		

In Zeile 4 bis 7 siehen Sie, wie man ein Funktionstemplate implementiert. Jedes Template wird mit dem Schlüsselwort "template" eingeleitet, gefolgt von einer geöffneten spitzen Klammer, danach eine Parameterliste, einer schließenden spitzen Klammer und abschließend der Definition der Funktion oder Klasse (letzteres erkläre ich später). Was ist mit Parameterliste gemeint? Sie beinhaltet meistens eines der drei Schlüsselwörter "typename", "class" oder "template", gefolgt von einem frei wählbaren Typenbezeichner, welchen man innerhalb des Templates benutzt. Anschließend kann man mit Komma getrennt, weitere dieser Paare definieren. Den Unterschied zwischen "typename" und "class", werde ich im nächsten Unterkapitel erläutern. Auf den Parametertyp "template" werde ich nicht weiter eingehen, da man es zum einen selten benutzt und es zum anderen die ganze Sache nicht leichter macht. Gemeint ist aber, dass man innerhalb eines Templates, ein existierendes Template einbinden kann. Somit erreicht man eine Verschachtlung.

Nach der geschlossenen Spitzen Klammer in Zeile 4, steht nun der eigentliche Funktionskopf in Zeile 5. Normalerweise schreibt man dies in eine Zeile, aber mit einem Zeilenumbruch, sieht es übersichtlicher aus. Zuerst steht der erste definierte Datentypbezeichner als Rückgabewert, dann der Funktionsname und abschließend, in den runden Klammern, die Übergabeparameter, jeweils vom zweiten definierten Typenbezeichner und natürlich noch die Variablennamen.

Zeile 6 ist nicht weiter spannend, da hier nichts atemberaubendes passiert. Ich caste lediglich die zwei übergebenen Parameter, in den Ergebnistyp um, bevor ich sie miteinander addiere. Bei der Addition spielt dies keine große Rolle, aber im Falle einer Division wäre dies wichtiger.

Interessanter wird es dann aber wieder in der "main", in den Zeilen 12 bis 25. Hier benutze ich nun das eben definierte Template. In den Zeilen 15 und 19 rufe ich das Funktinstemplate auf und wie Sie sehen können, muss man auch hier wieder die spitzen Klammern verwenden. Innerhalb dieser Klammern, gibt man jetzt den Ergebnisdatentyp und den Parameterdatentyp an, mit welcher das Template arbeiten soll (Sie erinnern sich vielleicht noch, dass diese Syntax auch bei den verschiedenen Castings benutzt wurde). Dies hat zur Folge, dass einmal jedes "TResultDataType" in "long int" und jedes "TParameterDataType" in "int" umgewandelt wird und das andere mal jedes "TResultDataType" durch "float" und "TParameterDataType" durch "double" ersetzt wird. Der Compiler generiert also folgenden Quelltext im Hintergrund, wobei die eigentliche Templatedefinition restlos verschwindet.

 1
 2
 3
 4
 5
 6
 7
					
long int Addiere(int tElement1, int tElement2) {
	return static_cast<long int>(tElement1) + static_cast<long int>(tElement2);
}

float Addiere(double tElement1, double tElement2) {
	return static_cast<float>(tElement1) + static_cast<float>(tElement2);
}
					

Hier sehen Sie jetzt, dass das Template wirklich als Kopiervorlage benutzt wurde und das für "TResultDataType" und "TParameterDataType" die gewünschten Typen ersetzt wurden. Ich betone noch einmal an dieser Stelle, dass diese Ersetzung nur stattfindet, wenn man das Template benutzt. Vergisst man also innerhalb des Templates z.B. ein Semikolon oder ähnliches, ohne das Template einzubinden, wird der Compiler keinen Fehler erkennen, da das Template schlicht und einfach, genauso wie Kommentare, weggelassen bzw. rausgeschmissen wird.

Wie gesagt, dieses Beispiel macht nicht viel Sinn, aber man sieht schön, dass ich aus einer händisch geschriebenen Funktion, unterm Strich zwei verschiedene generiert bekommen habe. Würde ich dieses Template noch für zehn andere Datentypen verwenden, würden entsprechend noch zehn weitere Funktionen generiert werden.

Ein denkbarer Anwendungsfall für Funktionstemplates ist z.B., dass man Elemente aus einer Binärdatei entnehmen, sortieren und anschließend wieder in eine andere Datei speichern will, denn um auf Binärdateien zugreifen zu können, benötigt man immer einen speziellen Datentyp. Falls es nun Dateien geben könnte mit Integern und welche mit Floats, kann man sich ein Template bauen, welches den Typen erst einmal rein formal behandelt und anschließend ruft man das Funktionstemplate mit dem entsprechenden Datentyp auf.

Zum Seitenanfang
Zum Inhaltsverzeichnis

© Copyright by Thomas Weiß, 2009 - 2012