So verwenden Sie C ++ - Vorlagen

So verwenden Sie C ++ - Vorlagen
In der grundlegenden C ++ - Programmierung des Datentyps e.G., int oder char muss in einer Erklärung oder einer Definition angegeben werden. Ein Wert wie 4 oder 22 oder -5 ist ein int int. Ein Wert wie 'a' oder 'b' oder 'c' ist ein Char. Mit dem Vorlagenmechanismus kann der Programmierer einen generischen Typ für eine Reihe von tatsächlichen Typen verwenden. Zum Beispiel kann der Programmierer entscheiden, die Kennung t für INT oder char zu verwenden. Es ist möglich, dass ein C ++ - Algorithmus mehr als einen generischen Typ hat. Mit beispielsweise t für den int oder char können Sie für den Float- oder Zeigertyp stehen. Eine Klasse wie die Zeichenfolge oder die Vektorklasse ist wie ein Datentyp, und die instanziierten Objekte sind wie Werte des Datentyps, der die angegebene Klasse ist. Mit dem Vorlagenmechanismus kann der Programmierer auch einen generischen Typ -Kennung für einen Satz von Klassen verwenden.

Eine C ++ - Vorlage erstellt einen Algorithmus unabhängig von der Art der verwendeten Daten. Daher kann der gleiche Algorithmus mit vielen Vorkommen desselben Typs unterschiedliche Typen bei verschiedenen Ausführungen verwenden. Die Entitäten von Variablen, Funktionen, Strukturen und Klasse können Vorlagen haben. In diesem Artikel erklärt++. Sie sollten bereits Kenntnisse der oben genannten Einheiten haben, um die in diesem Artikel behandelten Themen zu verstehen.

Typen

Skalar

Die Skalartypen sind nichtig, bool, char, int, float und Zeiger.

Klassen als Typen

Eine bestimmte Klasse kann als Typ und ihre Objekte als mögliche Werte betrachtet werden.

Ein generischer Typ repräsentiert einen Satz von Skalartypen. Die Liste der Skalartypen ist umfangreich. Der Int -Typ hat beispielsweise andere verwandte Typen wie Short Int, Long INT usw. Ein generischer Typ kann auch einen Satz von Klassen darstellen.

Variable

Ein Beispiel für eine Vorlagenerklärung und Definition lautet wie folgt:

Vorlage T pi = 3.14;

Beachten Sie, dass diese Art von Anweisung nicht in der Funktion main () oder in einem Blockbereich erscheinen kann. Die erste Zeile ist die Deklaration mit Vorlagenkopf, wobei der Programmierer ausgewählt wurde, generische Typnamen t. Die nächste Zeile ist die Definition des Kennung PI, der vom generischen Typ t ist, t. Präzision, ob das T ein int oder ein Schwimmer oder ein anderer Typ ist, kann in der Funktion c ++ main () (oder in einer anderen Funktion) erfolgen. Eine solche Präzision wird mit dem variablen pi und nicht t durchgeführt.

Die erste Zeile ist die Vorlagen-Kopf-Erklärung. Diese Erklärung beginnt mit dem reservierten Wort, der Vorlage und den offenen und geschlossenen Winkelklammern. Innerhalb der Winkelklammern gibt es mindestens einen generischen Typ -Kennung wie t oben t. Es kann mehr als einen generischen Typ -Kenner geben, wobei das reservierte Wort typername jeweils vorangegangen ist. Solche generischen Typen in dieser Position werden als Template -Parameter bezeichnet.

Die folgende Erklärung kann in main () oder in jeder anderen Funktion geschrieben werden:

Cout << pi << '\n';

Und die Funktion würde 3 angezeigt.14. Der Ausdruck PI entscheidet den genauen Typ von t für den Variablen PI. Spezialisierung entscheidet den bestimmten Datentyp für den Vorlageparameter. Die Instanziierung ist der interne C ++ - interne Prozess des Erstellens des jeweiligen Typs, wie z. B. in diesem Fall Float. Verwechseln. Im Template-Thema können viele Datentypen einen generischen Typnamen haben, während viele Klassen einen generischen Klassennamen haben können. Der generische Klassenname für Klassen wird jedoch einfach als Klasse bezeichnet und nicht als Klassenname. Außerdem ist ein Wert für einen Datentyp wie das int als instanziiertes Objekt für eine Klasse wie die String -Klasse.

Bei der Spezialisierung wird der ausgewählte Datentyp wie Float nach der Variablen in Winkelklammern platziert. Wenn in der Template-Head-Deklaration mehr als einen Vorlagenparameter vorhanden ist, gibt es in derselben Reihenfolge eine entsprechende Anzahl von Datentypen in derselben Reihenfolge im Spezialisierungsausdruck.

Bei der Spezialisierung wird ein Typ als Vorlagenargument bezeichnet. Verwechseln Sie nicht zwischen diesem und dem Funktionsargument für den Funktionsaufruf.

Standardtyp

Wenn bei der Spezialisierung kein Typ angegeben ist, wird der Standardtyp angenommen. Aus dem folgenden Ausdruck:

Vorlage U pi = "Liebe";

Diese CAM wird als solcher mit einem Standardtyp verwendet:

Cout << pi << '\n';

Wobei „Liebe“ für den ständigen Zeiger auf char als standardmäßig aus der Vorlage verwendet wird. Hinweis in der Erklärung, dass u = const char*. Die Winkelklammern sind bei Spezialisierung leer (kein Typ angegeben); Der tatsächliche Typ wird als Const -Zeiger auf char angesehen, den Standardtyp. Wenn bei der Spezialisierung ein anderer Typ benötigt würde, wird der Typname in den Winkelklammern geschrieben. Wenn der Standardtyp bei der Spezialisierung gewünscht wird, ist es optional, den Typ in den Winkelklammern zu wiederholen.e., Die Winkelklammern können leer bleiben.

Hinweis: Der Standardtyp kann bei Spezialisierung weiterhin geändert werden, indem ein anderer Typ aufgetreten ist.

Struktur

Das folgende Beispiel zeigt, wie ein Vorlagenparameter mit einer Struktur verwendet werden kann:

Vorlage Strukturalter

T John = 11;
T Peter = 12;
T Mary = 13;
T Joy = 14;
;

Dies sind das Alter von Schülern in einer Klasse (Klasse). Die erste Zeile ist die Vorlagenerklärung. Der Körper in Zahnspangen ist die tatsächliche Definition der Vorlage. Das Alter kann in der Funktion main () mit folgendem ausgeben werden:

Alter Klasse 7;
Cout << grade7.John << " << grade7.Mary << '\n';

Die Ausgabe ist: 11 13. Die erste Aussage hier führt die Spezialisierung durch. Beachten Sie, wie es gemacht wurde. Es gibt auch einen Namen für ein Objekt der Struktur: Klasse 7. Die zweite Aussage hat gewöhnliche Ausdrücke von Strukturenobjekten. Eine Struktur ist wie eine Klasse. Hier ist das Alter wie ein Klassenname, während Grad7 ein Objekt der Klasse ist (Struktur).

Wenn einige Altersgruppen Ganzzahlen sind und andere Schwimmer sind, benötigt die Struktur zwei generische Parameter wie folgt:

Vorlage Strukturalter

T John = 11;
U Peter = 12.3;
T Mary = 13;
U Joy = 14.6;
;

Ein relevanter Code für die Funktion main () lautet wie folgt:

Alter Klasse 7;
Cout << grade7.John << " << grade7.Peter << '\n';

Die Ausgabe ist: 11 12.3. Bei der Spezialisierung muss die Reihenfolge der Typen (Argumente) der Reihenfolge der generischen Typen in der Erklärung entsprechen.

Die Vorlagenerklärung kann wie folgt von der Definition getrennt werden:

Vorlage Strukturalter

T John;
U Peter;
T Mary;
U Freude;
;
Alter Klasse7 = 11, 12.3, 13, 14.6;

Das erste Codesegment ist nur eine Erklärung einer Vorlage (es gibt keine Zuordnungen). Das zweite Code -Segment, das nur eine Aussage ist, ist die Definition des Kennung, Grad7. Die linke Seite ist die Erklärung der Kennung, Grad7. Die rechte Seite ist die Initialisiererliste, die den Strukturmitgliedern entsprechende Werte zuweist. Das zweite Segment (Anweisung) kann in der Funktion main () geschrieben werden, während das erste Segment außerhalb der Funktion main () bleibt.

Nicht-Typ

Beispiele für Nicht-Daten-Typen sind int, Zeiger auf Objekt, Zeiger auf die Funktion und Autotypen. Es gibt andere Nicht-Typen, die dieser Artikel nicht behandelt. Ein Nicht-Typ ist wie ein unvollständiger Typ, dessen Wert später angegeben ist und nicht geändert werden kann. Als Parameter beginnt es mit einem bestimmten Nicht-Typ, gefolgt von einer Kennung. Der Wert der Kennung wird später bei Spezialisierung angegeben und kann nicht erneut geändert werden (wie eine Konstante, deren Wert später angegeben ist). Das folgende Programm zeigt dies:

#enthalten
Verwenden von Namespace STD;
Vorlage Strukturalter

T John = n;
U Peter = 12.3;
T Mary = n;
U Joy = 14.6;
;
int main ()

Alter Klasse 7;
Cout << grade7.John << " << grade7.Joy << '\n';
Rückkehr 0;

Bei der Spezialisierung ist der erste Typ, Int, in den Winkelklammern mehr für die Formalität da, um sicherzustellen, dass die Anzahl und Reihenfolge der Parameter der Anzahl und Reihenfolge der Typen (Argumente) entsprechen (Argumente). Der Wert von n wurde bei Spezialisierung angegeben. Die Ausgabe ist: 11 14.6.

Teilspezialisierung

Nehmen wir an, dass eine Vorlage vier generische Typen enthält und dass unter den vier Typen zwei Standardtypen erforderlich sind. Dies kann anhand des Teilspezialisierungskonstrukts erreicht werden, das den Zuordnungsbetreiber nicht verwendet. Das teilweise Spezialisierungskonstrukt gibt also Standardwerten für eine Teilmenge generischer Typen an. Im teilweisen Spezialisierungsschema sind jedoch eine Basisklasse (Struktur) und eine Teilspezialisierungsklasse (Struktur) erforderlich. Das folgende Programm zeigt dies für einen generischen Typ von zwei generischen Typen:

#enthalten
Verwenden von Namespace STD;
// Basisvorlagenklasse
Vorlage
Strukturalter

;
// partielle Spezialisierung
Vorlage
Strukturalter

T1 John = 11;
Float Peter = 12.3;
T1 Mary = 13;
Float Joy = 14.6;
;
int main ()

Alter Klasse 7;
Cout << grade7.John << " << grade7.Joy << '\n';
Rückkehr 0;

Identifizieren Sie die Erklärung der Basisklassen und ihre teilweise Klassendefinition. Die Vorlagenkopfdeklaration der Basisklasse hat alle generischen Parameter erforderlich. Die Deklaration der Template-Head-Erklärung der Teilspezialisierungsklasse hat nur den generischen Typ. In dem Schema wird eine zusätzliche Reihe von Winkelklammern verwendet, die kurz nach dem Namen der Klasse in der Teilspezialisierungsdefinition erfolgt. Es ist das, was die teilweise Spezialisierung tatsächlich macht. Es verfügt über den Standardtyp und den Nicht-Default-Typ in der in der Basisklasse geschriebenen Reihenfolge. Beachten Sie, dass der Standardtyp weiterhin einen anderen Typ in der Funktion main () erhalten kann.

Der relevante Code in der Funktion main () kann wie folgt sein:

Alter Klasse 7;
Cout << grade7.John << " << grade7.Joy << '\n';

Die Ausgabe ist: 11 14.6.

Vorlageparameterpack

Ein Parameterpaket ist ein Vorlagenparameter, der generische Typen null oder mehr Vorlagen für die entsprechenden Datentypen akzeptiert. Der Parameter des Parameterpacks beginnt mit dem reservierten Word -Typenamen oder der Klasse. Darauf folgen drei Punkte und dann die Kennung für das Paket. Das folgende Programm zeigt, wie ein Vorlagenparameterpaket mit einer Struktur verwendet werden kann:

#enthalten
Verwenden von Namespace STD;
Vorlage Strukturalter

int John = 11;
Float Peter = 12.3;
int Mary = 13;
Float Joy = 14.6;
;
int main ()

Alter Note B;
Cout << gradeB.John << " << gradeB.Mary << '\n';
Alter Gradec;
Cout << gradeC.Peter << " << gradeC.Joy << '\n';
Alter bewertet;
Cout << gradeD.John << " << gradeD.Joy << '\n';
Altersgrada; // Standardeinstellung
Cout << gradeA.John << " << gradeA.Joy << '\n';
Rückkehr 0;

Die Ausgabe ist:

11 13
12.3 14.6
11 14.6
11 14.6

Funktionsvorlagen

Die oben genannten Vorlagenfunktionen gelten ähnlich wie Funktionsvorlagen. Das folgende Programm zeigt eine Funktion mit zwei generischen Vorlagenparametern und drei Argumenten:

#enthalten
Verwenden von Namespace STD;
Vorlage void func (t no, u cha, const char *str)
Cout << "There are " << no << " books worth " << cha << str << " in the store." << '\n';

int main ()
Func (12, '$', "500");
Rückkehr 0;

Die Ausgabe ist wie folgt:

Es gibt 12 Bücher im Wert von 500 US -Dollar im Laden.

Trennung vom Prototyp

Die Funktionsdefinition kann von ihrem Prototyp getrennt werden, wie das folgende Programm zeigt:

#enthalten
Verwenden von Namespace STD;
Vorlage void func (t no, u cha, const char *str);
Vorlage void func (t no, u cha, const char *str)
Cout << "There are " << no << " books worth " << cha << str << " in the store." << '\n';

int main ()
Func (12, '$', "500");
Rückkehr 0;

Notiz: Die Deklaration der Funktionsvorlage kann in der Funktion main () oder in einer anderen Funktion nicht angezeigt werden.

Überlastung

Überladung derselben Funktion kann mit unterschiedlichen Vorlagenkopfdeklarationen stattfinden. Das folgende Programm zeigt dies:

#enthalten
Verwenden von Namespace STD;
Vorlage void func (t no, u cha, const char *str)
Cout << "There are " << no << " books worth " << cha << str << " in the store." << '\n';

Vorlage void func (t no, const char *str)
Cout << "There are " << no << " books worth $" << str << " in the store." << '\n';

int main ()

Func (12, '$', "500");
Func (12, "500");
Rückkehr 0;

Die Ausgabe ist:

Es gibt 12 Bücher im Wert von 500 US -Dollar im Laden.

Es gibt 12 Bücher im Wert von 500 US -Dollar im Laden.

Klassenvorlagen

Die Merkmale der oben genannten Vorlagen gelten ähnlich wie Klassenvorlagen. Das folgende Programm ist die Erklärung, Definition und Verwendung einer einfachen Klasse:

#enthalten
Verwenden von Namespace STD;
Klasse Thecla

öffentlich:
int num;
statischer Char Ch;
void func (char cha, const char *str)
Cout << "There are " << num << " books worth " << cha << str << " in the store." << '\n';

statischer void Fun (char ch)
if (ch == 'a')
Cout << "Official static member function" << '\n';

;
int main ()

Thecla obj;
obj.Num = 12;
obj.func ('$', "500");
Rückkehr 0;

Die Ausgabe ist wie folgt:

Es gibt 12 Bücher im Wert von 500 US -Dollar im Laden.

Das folgende Programm ist das obige Programm mit einer Vorlagen-Kopf-Erklärung:

#enthalten
Verwenden von Namespace STD;
Vorlage Klasse Thecla

öffentlich:
T num;
statisch u ch;
void func (u cha, const char *str)
Cout << "There are " << num << " books worth " << cha << str << " in the store." << '\n';

statischer void Fun (u ch)
if (ch == 'a')
Cout << "Official static member function" << '\n';

;
int main ()

Thecla obj;
obj.Num = 12;
obj.func ('$', "500");
Rückkehr 0;

Anstelle des Wortes Typename in der Vorlagenparameterliste kann die Wortklasse verwendet werden. Beachten Sie die Spezialisierung in der Erklärung des Objekts. Die Ausgabe ist immer noch der gleiche:

Es gibt 12 Bücher im Wert von 500 US -Dollar im Laden.

Erklärung von Trennung

Die Erklärung der Klassenvorlage kann wie folgt vom Klassencode getrennt werden:

Vorlage Klasse Thecla;
Vorlage Klasse Thecla
öffentlich:
T num;
statisch u ch;
void func (u cha, const char *str)
Cout << "There are " << num << " books worth " << cha << str << " in the store." << '\n';

statischer void Fun (u ch)
if (ch == 'a')
Cout << "Official static member function" << '\n';

;

Umgang mit statischen Mitgliedern

Das folgende Programm zeigt, wie man auf ein statisches Datenmitglied und eine statische Mitgliedsfunktion zugreift:

#enthalten
Verwenden von Namespace STD;
Vorlage Klasse Thecla
öffentlich:
T num;
statisch u ch;
void func (u cha, const char *str)
Cout << "There are " << num << " books worth " << cha << str << " in the store." << '\n';

statischer void Fun (u cha)
if (ch == 'a')
Cout << "Official static member function" << cha << '\n';

;
Vorlage U Thecla:: ch = 'a';
int main ()

Thecla::Spaß('.');
Rückkehr 0;

Das Zuweisen eines Wertes einem statischen Datenmitglied ist eine Deklaration und kann nicht in Main () sein (). Beachten Sie die Verwendung und Positionen der generischen Typen und den generischen Datentyp in der Zuordnungsanweisung. Beachten Sie außerdem, dass die Funktion der statischen Datenmember in Main () mit den tatsächlichen Vorlagendatentypen aufgerufen wurde. Die Ausgabe ist Folgendes:

Offizielle statische Mitgliedsfunktion.

Kompilieren

Die Erklärung (Header) und die Definition einer Vorlage müssen in einer Datei sein. Das heißt, sie müssen in derselben Übersetzungseinheit sein.

Abschluss

C ++ - Vorlagen machen einen Algorithmus unabhängig von der Art der verwendeten Daten. Die Entitäten von Variablen, Funktionen, Strukturen und Klasse können Vorlagen haben, die eine Erklärung und Definition beinhalten. Das Erstellen einer Vorlage beinhaltet auch Spezialisierung, wenn ein generischer Typ einen tatsächlichen Typ nimmt. Die Erklärung und die Definition einer Vorlage müssen beide in einer Übersetzungseinheit enthalten sein.