Menu
Coddy logo textTech

Funktionstemplates

Teil des Abschnitts Objektorientierte Programmierung der C++-Journey von Coddy. Lektion 64 von 104.

Stell dir vor, du schreibst eine Funktion, um das Maximum zweier Ganzzahlen zu finden, und stellst dann fest, dass du dieselbe Logik erneut für Gleitkommazahlen und nochmals für Zeichenketten benötigst. Ohne Vorlagen müsstest du für jeden Typ nahezu identische Funktionen schreiben. Funktionsvorlagen lösen dieses Problem, indem sie dir ermöglichen, die Logik einmal zu schreiben und den Compiler automatisch typspezifische Versionen erzeugen zu lassen.

Eine Funktionsvorlage verwendet das Schlüsselwort template, gefolgt von Vorlagenparametern in spitzen Klammern:

template <typename T>
T maximum(T a, T b) {
    return (a > b) ? a : b;
}

int main() {
    std::cout << maximum(5, 3) << std::endl;       // Verwendet int-Version
    std::cout << maximum(3.14, 2.71) << std::endl; // Verwendet double-Version
    std::cout << maximum('a', 'z') << std::endl;   // Verwendet char-Version
}

Der Compiler untersucht jeden Aufruf und generiert eine konkrete Funktion für diesen spezifischen Typ. Dieser Prozess wird als template instantiation bezeichnet. Du kannst den Typ bei Bedarf auch explizit angeben:

std::cout << maximum<double>(5, 3.14) << std::endl;  // Erzwingt die double-Version

Templates können mehrere Typparameter haben und dadurch noch flexiblere Designs ermöglichen:

template <typename T, typename U>
void printPair(T first, U second) {
    std::cout << first << ", " << second << std::endl;
}

printPair(42, "hello");    // T=int, U=const char*
printPair(3.14, 100);      // T=double, U=int

Funktionstemplates bieten Polymorphie zur Kompilierzeit – der Typ wird beim Kompilieren des Codes bestimmt, nicht zur Laufzeit. Das bedeutet keinen Laufzeit-Overhead im Vergleich zu virtuellen Funktionen, wodurch Templates ideal für performancekritischen generischen Code sind.

challenge icon

Aufgabe

Einfach

Erstellen wir ein Hilfswerkzeug, das Funktionsvorlagen verwendet, um wiederverwendbare Operationen zu erstellen, die mit jedem kompatiblen Typ funktionieren. Du organisierst deine generischen Funktionen in einer Header-Datei und demonstrierst ihre Flexibilität in deinem Hauptprogramm.

Du erstellst zwei Dateien:

  • MathUtils.h: Definiere eine Sammlung von Funktionsvorlagen, die häufige Operationen ausführen:

    minimum: eine Vorlagenfunktion, die zwei Werte desselben Typs entgegennimmt und den kleineren zurückgibt.

    clamp: eine Vorlagenfunktion, die drei Parameter entgegennimmt: einen Wert, eine untere Grenze und eine obere Grenze. Sie gibt den auf die Grenzen beschränkten Wert zurück (die untere Grenze, wenn der Wert kleiner als die untere Grenze ist, die obere Grenze, wenn der Wert größer als die obere Grenze ist, andernfalls den Wert selbst).

    swapValues: eine Vorlagenfunktion, die zwei Referenzen desselben Typs entgegennimmt und ihre Werte vertauscht.

  • main.cpp: Lies sechs Eingaben ein (jeweils in einer eigenen Zeile):

    1. Erste Ganzzahl
    2. Zweite Ganzzahl
    3. Ein double-Wert, der beschränkt werden soll
    4. Untere Grenze (double)
    5. Obere Grenze (double)
    6. Ein Zeichen

    Demonstriere deine Vorlagen, indem du:

    1. Das Minimum der beiden Ganzzahlen bestimmst und Folgendes ausgibst: Min of <a> and <b>: <result>
    2. Das Minimum des Zeichens 'm' und deines Eingabezeichens bestimmst und Folgendes ausgibst: Min of m and <char>: <result>
    3. Den double-Wert beschränkst und Folgendes ausgibst: Clamp <value> to [<low>, <high>]: <result>
    4. Die erste Ganzzahl auf den Bereich [0, 100] beschränkst und Folgendes ausgibst: Clamp <value> to [0, 100]: <result>
    5. Die beiden Ganzzahlen vertauschst und Folgendes ausgibst: After swapValues: <a>, <b>

Zum Beispiel bei den Eingaben 25, 10, 3.7, 1.0, 5.0 und z:

Min of 25 and 10: 10
Min of m and z: m
Clamp 3.7 to [1, 5]: 3.7
Clamp 25 to [0, 100]: 25
After swapValues: 10, 25

Beachte, wie jede Vorlagenfunktion nahtlos mit Ganzzahlen, double-Werten und Zeichen funktioniert: Der Compiler erzeugt für jeden von dir verwendeten Typ die passende Version. Deine Funktion swapValues sollte die ursprünglichen Variablen über Referenzen ändern und damit zeigen, dass Vorlagen genauso wie reguläre Funktionen mit Referenzparametern funktionieren.

Probier es selbst

#include <iostream>
#include "MathUtils.h"
using namespace std;

int main() {
    // Eingaben lesen
    int a, b;
    double value, low, high;
    char ch;
    
    cin >> a;
    cin >> b;
    cin >> value;
    cin >> low;
    cin >> high;
    cin >> ch;
    
    // TODO: Verwende das minimum-Template, um das Minimum von zwei Ganzzahlen zu finden
    // Ausgeben: "Min of <a> and <b>: <result>"
    
    // TODO: Verwende das minimum-Template, um das Minimum von 'm' und dem Eingabezeichen zu finden
    // Ausgeben: "Min of m and <char>: <result>"
    
    // TODO: Verwende das clamp-Template auf den double-Wert
    // Ausgeben: "Clamp <value> to [<low>, <high>]: <result>"
    
    // TODO: Verwende das clamp-Template auf die erste Ganzzahl mit dem Bereich [0, 100]
    // Ausgeben: "Clamp <value> to [0, 100]: <result>"
    
    // TODO: Verwende das swapValues-Template auf die beiden Ganzzahlen
    // Print: "After swapValues: <a>, <b>"
    
    return 0;
}
quiz iconTeste dich selbst

Diese Lektion enthält ein kurzes Quiz. Starte die Lektion, um es zu beantworten und deinen Fortschritt zu speichern.

Alle Lektionen in Objektorientierte Programmierung

Übe selbstständig: Online-C++-Compiler