C++

So verwenden Sie C++-Vorlagen

So verwenden Sie C++-Vorlagen

Einführung

In der grundlegenden C++-Programmierung ist der Datentyp, z.G., int oder char, muss in einer Deklaration oder Definition angegeben werden. Ein Wert wie 4 oder 22 oder -5 ist ein int. Ein Wert wie 'A' oder 'b' oder 'c' ist ein char. Der Template-Mechanismus ermöglicht es dem Programmierer, einen generischen Typ für eine Reihe von tatsächlichen Typen zu verwenden. Zum Beispiel kann der Programmierer entscheiden, den Bezeichner 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 int oder char kann U für den Float- oder Pointer-Typ stehen. Eine Klasse, wie die String- oder Vektorklasse, ist wie ein Datentyp, und die instanziierten Objekte sind wie Werte des Datentyps, der die angegebene Klasse ist. Der Template-Mechanismus ermöglicht es dem Programmierer also auch, einen generischen Typbezeichner für eine Reihe von Klassen zu verwenden.

Eine C++-Vorlage erstellt einen Algorithmus unabhängig von der Art der verwendeten Daten. Derselbe Algorithmus mit vielen Vorkommen desselben Typs kann also unterschiedliche Typen bei verschiedenen Ausführungen verwenden. Die Entitäten von Variable, Funktion, Struktur und Klasse können Vorlagen haben. In diesem Artikel wird erläutert, wie Sie Vorlagen deklarieren, Vorlagen definieren und in C anwenden++. Sie sollten bereits über Kenntnisse der oben genannten Entitäten verfügen, um die in diesem Artikel behandelten Themen zu verstehen.

Typen

Skalar

Die Skalartypen sind void, bool, char, int, float und pointer.

Klassen als Typen

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

Ein generischer Typ repräsentiert eine Menge von skalaren Typen. 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 eine Menge von Klassen darstellen.

Variable

Ein Beispiel für eine Vorlagendeklaration und -definition ist wie folgt:

Vorlage
Tpi = 3.14;

Bevor Sie fortfahren, beachten Sie, dass diese Art von Anweisung nicht in der main()-Funktion oder in einem Blockbereich vorkommen kann. Die erste Zeile ist die Template-Head-Deklaration mit dem vom Programmierer gewählten generischen Typnamen T. Die nächste Zeile ist die Definition des Bezeichners pi, der vom generischen Typ T . ist. Die Genauigkeit, ob das T ein Int oder ein Float oder ein anderer Typ ist, kann in der C++-Funktion main() (oder einer anderen Funktion) vorgenommen werden. Eine solche Genauigkeit wird mit der Variablen pi erreicht und nicht mit T.

Die erste Zeile ist die Template-Head-Deklaration. Diese Deklaration beginnt mit dem reservierten Wort, der Vorlage und dann den offenen und geschlossenen spitzen Klammern. Innerhalb der spitzen Klammern gibt es mindestens einen generischen Typbezeichner, z. B. T, oben,. Es kann mehr als einen generischen Typbezeichner geben, wobei jedem das reservierte Wort Typname vorangestellt ist. Solche generischen Typen an dieser Position werden Vorlagenparameter genannt.

Die folgende Anweisung kann in main() oder in jeder anderen Funktion geschrieben werden:

cout << pi << '\n';

Und die Funktion würde 3 . anzeigen.14. Der Ausdruck pi bestimmt den genauen Typ von T für die Variable pi. Die Spezialisierung entscheidet über den jeweiligen Datentyp für den Vorlagenparameter. Instanziierung ist der C++-interne Prozess zum Erstellen des bestimmten Typs, in diesem Fall beispielsweise float float. Verwechseln Sie nicht die Instanziierung eines Vorlagenparameters mit der Instanziierung einer Klasse. Im Vorlagenthema 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 gehört ein Wert zu einem Datentyp wie dem int, wie ein instanziiertes Objekt zu einer Klasse wie der String-Klasse.

Bei der Spezialisierung wird der gewählte Datentyp, z. B. float, in spitzen Klammern hinter die Variable gesetzt. Wenn die Template-Head-Deklaration mehr als einen Template-Parameter enthält, gibt es im Spezialisierungsausdruck eine entsprechende Anzahl von Datentypen in derselben Reihenfolge order.

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

Standardtyp

Wenn bei der Spezialisierung kein Typ angegeben ist, wird der Standardtyp angenommen. Also aus folgendem Ausdruck:

Vorlage
U pi = "Liebe";
die Anzeige von:
cout << pi<> << '\n';

ist „Liebe“ für den ständigen Zeiger auf char. Beachten Sie in der Deklaration, dass U = const char*. Die spitzen Klammern sind bei der Spezialisierung leer (kein Typ angegeben); der tatsächliche Typ wird als const-Zeiger auf char betrachtet, den Standardtyp. Wenn bei der Spezialisierung ein anderer Typ benötigt wird, wird der Typname in die spitzen Klammern geschrieben. Wenn der Standardtyp bei der Spezialisierung gewünscht wird, ist die Wiederholung des Typs in den spitzen Klammern optional, d.e., die spitzen Klammern können leer bleiben.

Hinweis: Der Standardtyp kann bei der Spezialisierung immer noch geändert werden, indem ein anderer Typ verwendet wird.

strukturieren

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

Vorlage struct Ages

TJohn = 11;
TPeter = 12;
T Maria = 13;
T Freude = 14;
;

Dies sind die Altersstufen der Schüler in einer Klasse (Klasse). Die erste Zeile ist die Vorlagendeklaration. Der Körper in geschweiften Klammern ist die eigentliche Definition der Vorlage. Die Altersangaben können in der Funktion main() wie folgt ausgegeben werden:

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

Die Ausgabe ist: 11 13. Die erste Anweisung hier führt die Spezialisierung durch. Beachten Sie, wie es gemacht wurde. Es gibt auch einen Namen für ein Objekt der Struktur: grade7. Die zweite Anweisung hat gewöhnliche Strukturobjektausdrücke. Eine Struktur ist wie eine Klasse. Ages ist hier wie ein Klassenname, während grade7 ein Objekt der Klasse (struct) ist.

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

Vorlage struct Ages

TJohn = 11;
U Peter = 12.3;
T Maria = 13;
U Freude = 14.6;
;

Ein relevanter Code für die main()-Funktion 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 Deklaration entsprechen.

Die Vorlagendeklaration kann wie folgt von der Definition getrennt werden:

Vorlage struct Ages

T. John;
U Peter;
T Maria;
U Freude;
;
Alter Klasse 7 = 11, 12.3, 13, 14.6;

Das erste Codesegment ist eine reine Deklaration einer Vorlage (es gibt keine Zuordnungen). Das zweite Codesegment, das nur eine Aussage ist, ist die Definition des Identifikators, grade7. Die linke Seite ist die Deklaration des Bezeichners, grade7. Auf der rechten Seite befindet sich die Initialisierungsliste, die den Strukturmitgliedern entsprechende Werte zuweist. Das zweite Segment (Anweisung) kann in der main()-Funktion geschrieben werden, während das erste Segment außerhalb der main()-Funktion bleibt.

Nicht-Typ

Beispiele für Nicht-Datentypen sind int, Zeiger auf Objekt, Zeiger auf Funktion und Auto-Typen. Es gibt andere Nicht-Typen, auf die dieser Artikel nicht eingeht. Ein Nicht-Typ ist wie ein unvollständiger Typ, dessen Wert später angegeben wird und nicht geändert werden kann. Als Parameter beginnt er mit einem bestimmten Nicht-Typ, gefolgt von einem Bezeichner. Der Wert des Bezeichners wird später bei der Spezialisierung angegeben und kann nicht mehr geändert werden (wie eine Konstante, deren Wert später angegeben wird). Das folgende Programm veranschaulicht dies:

#einschließen
Verwenden von Namespace-Std;
Vorlage struct Ages

T John = N;
U Peter = 12.3;
T Maria = N;
U Freude = 14.6;
;
int main()

Alter Klasse 7;
cout << grade7.John << " << grade7.Joy << '\n';
0 zurückgeben;

Bei der Spezialisierung dient der erste Typ, int, in den spitzen Klammern eher der Formalität, um sicherzustellen, dass die Anzahl und Reihenfolge der Parameter der Anzahl und Reihenfolge der Typen (Argumente) entspricht. Der Wert von N wurde bei der Spezialisierung angegeben. Die Ausgabe ist: 11 14.6.

Teilspezialisierung

Nehmen wir an, eine Vorlage hat vier generische Typen und unter den vier Typen sind zwei Standardtypen erforderlich. Dies kann mit dem partiellen Spezialisierungskonstrukt erreicht werden, das den Zuweisungsoperator nicht verwendet. Das partielle Spezialisierungskonstrukt gibt also einer Untermenge von generischen Typen Standardwerte. Im Schema der partiellen Spezialisierung werden jedoch eine Basisklasse (struct) und eine partielle Spezialisierungsklasse (struct) benötigt. Das folgende Programm veranschaulicht dies für einen generischen Typ von zwei generischen Typen:

#einschließen
Verwenden von Namespace-Std;
//Basis-Template-Klasse
Vorlage
struct Ages

;
//teilweise Spezialisierung
Vorlage
struct Ages

T1 Johannes = 11;
Schwimmer Peter = 12.3;
T1 Maria = 13;
schweben Freude = 14.6;
;
int main()

Alter Klasse 7;
cout << grade7.John << " << grade7.Joy << '\n';
0 zurückgeben;

Identifizieren Sie die Basisklassendeklaration und ihre partielle Klassendefinition. Die Template-Head-Deklaration der Basisklasse hat alle notwendigen generischen Parameter. Die template-head-Deklaration der partiellen Spezialisierungsklasse hat nur den generischen Typ. Es gibt einen zusätzlichen Satz spitzer Klammern, die im Schema verwendet werden, das direkt nach dem Namen der Klasse in der partiellen Spezialisierungsdefinition steht. Es ist das, was die Teilspezialisierung tatsächlich bewirkt. Es hat den Standardtyp und den Nicht-Standardtyp, in der Reihenfolge, die in der Basisklasse geschrieben ist. Beachten Sie, dass dem Standardtyp in der Funktion main() immer noch ein anderer Typ zugewiesen werden kann.

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

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

Die Ausgabe ist: 11 14.6.

Vorlagen-Parameterpaket

Ein Parameterpaket ist ein Vorlagenparameter, der null oder mehr generische Vorlagentypen für die entsprechenden Datentypen akzeptiert. Der Parameterpaketparameter beginnt mit dem reservierten Wort typename oder class. Darauf folgen drei Punkte und dann die Kennung für das Paket. Das folgende Programm veranschaulicht, wie ein Vorlagenparameterpaket mit einer Struktur verwendet werden kann:

#einschließen
Verwenden von Namespace-Std;
Vorlage struct Ages

int John = 11;
Schwimmer Peter = 12.3;
int Mary = 13;
schweben Freude = 14.6;
;
int main()

Alter Note B;
cout << gradeB.John << " << gradeB.Mary << '\n';
Alter KlasseC;
cout << gradeC.Peter << " << gradeC.Joy << '\n';
Alter benotetD;
cout << gradeD.John << " << gradeD.Joy << '\n';
Alter<> GradA; //wie Standard
cout << gradeA.John << " << gradeA.Joy << '\n';
0 zurückgeben;

Die Ausgabe ist:

11 13
12.3 14.6
11 14.6
11 14.6

Funktionsvorlagen

Die oben genannten Template-Features gelten in ähnlicher Weise für Funktions-Templates. Das folgende Programm zeigt eine Funktion mit zwei generischen Vorlagenparametern und drei Argumenten:

#einschließen
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");
0 zurückgeben;

Die Ausgabe ist wie folgt:

Es gibt 12 Bücher im Wert von 500 $ im Laden.

Trennung vom Prototyp

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

#einschließen
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");
0 zurückgeben;

Hinweis: Die Deklaration der Funktionsvorlage kann nicht in der main()-Funktion oder in einer anderen Funktion vorkommen.

Überlastung

Das Überladen der gleichen Funktion kann mit unterschiedlichen Template-Head-Deklarationen erfolgen. Das folgende Programm veranschaulicht dies:

#einschließen
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 nein, const char *str )

cout << "There are " << no << " books worth $" << str << " in the store." << '\n';

int main()

func(12, '$', "500");
func(12, "500");
0 zurückgeben;

Die Ausgabe ist:

Es gibt 12 Bücher im Wert von 500 $ im Laden.

Es gibt 12 Bücher im Wert von 500 $ im Laden.

Klassenvorlagen

Die Funktionen der oben genannten Vorlagen gelten in ähnlicher Weise für Klassenvorlagen. Das folgende Programm ist die Deklaration, Definition und Verwendung einer einfachen Klasse:

#einschließen
Verwenden von Namespace-Std;
Klasse TheCla

Öffentlichkeit:
int-Zahl;
statisches Zeichen ch;
void func (char cha, const char *str)

cout << "There are " << num << " books worth " << cha << str << " in the store." << '\n';

statischer Leerspaß (char ch)

if (ch == 'a')
cout << "Official static member function" << '\n';

;
int main()

TheCla obj;
obj.Anzahl = 12;
obj.func('$', "500");
0 zurückgeben;

Die Ausgabe ist wie folgt:

Es gibt 12 Bücher im Wert von 500 $ im Laden.

Das folgende Programm ist das obige Programm mit einer Template-Head-Deklaration:

#einschließen
Verwenden von Namespace-Std;
Vorlage Klasse TheCla

Öffentlichkeit:
T-Zahl;
statische U ch;
void func (U cha, const char *str)

cout << "There are " << num << " books worth " << cha << str << " in the store." << '\n';

statischer Leerspaß (U ch)

if (ch == 'a')
cout << "Official static member function" << '\n';

;
int main()

TheCla obj;
obj.Anzahl = 12;
obj.func('$', "500");
0 zurückgeben;

Anstelle des Worttypnamens in der Vorlagenparameterliste kann die Wortklasse verwendet werden. Beachten Sie die Spezialisierung in der Deklaration des Objekts. Die Ausgabe ist immer noch dieselbe:

Es gibt 12 Bücher im Wert von 500 $ im Laden.

Trennerklärung

Die Klassenvorlagendeklaration kann wie folgt vom Klassencode getrennt werden:

Vorlage Klasse TheCla;
Vorlage Klasse TheCla

Öffentlichkeit:
T-Zahl;
statische U ch;
void func (U cha, const char *str)

cout << "There are " << num << " books worth " << cha << str << " in the store." << '\n';

statischer Leerspaß (U ch)

if (ch == 'a')
cout << "Official static member function" << '\n';

;

Umgang mit statischen Mitgliedern

Das folgende Programm zeigt, wie Sie auf einen statischen Datenmember und eine statische Memberfunktion zugreifen:

#einschließen
Verwenden von Namespace-Std;
Vorlage Klasse TheCla

Öffentlichkeit:
T-Zahl;
statische U ch;
void func (U cha, const char *str)

cout << "There are " << num << " books worth " << cha << str << " in the store." << '\n';

statischer Leerspaß (U cha)

if (ch == 'a')
cout << "Official static member function" << cha << '\n';

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

TheCla::Spaß('.');
0 zurückgeben;

Das Zuweisen eines Werts zu einem statischen Datenmember ist eine Deklaration und kann nicht in main() enthalten sein. Beachten Sie die Verwendung und Position der generischen Typen und des generischen Datentyps in der Zuweisungsanweisung. Beachten Sie außerdem, dass die statische Datenmemberfunktion in main() mit den tatsächlichen Vorlagendatentypen aufgerufen wurde. Die Ausgabe ist die folgende:

Offizielle statische Memberfunktion.

Kompilieren

Die Deklaration (Header) und die Definition einer Vorlage müssen in einer Datei vorliegen. Das heißt, sie müssen sich in derselben Übersetzungseinheit befinden.

Fazit

C++-Templates machen einen Algorithmus unabhängig von der Art der verwendeten Daten. Die Entitäten von Variable, Funktion, Struktur und Klasse können Vorlagen haben, die Deklaration und Definition beinhalten. Das Erstellen einer Vorlage beinhaltet auch eine Spezialisierung, wenn ein generischer Typ einen tatsächlichen Typ annimmt. Die Deklaration und die Definition einer Vorlage müssen sich in einer Übersetzungseinheit befinden.

So verwenden Sie die GameConqueror-Cheat-Engine unter Linux
Der Artikel enthält eine Anleitung zur Verwendung der GameConqueror-Cheat-Engine unter Linux. Viele Benutzer, die Spiele unter Windows spielen, verwen...
Beste Spielkonsolen-Emulatoren für Linux
Dieser Artikel listet beliebte Spielekonsolen-Emulationssoftware auf, die für Linux verfügbar ist. Emulation ist eine Softwarekompatibilitätsschicht, ...
Beste Linux-Distributionen für Gaming im Jahr 2021
Das Linux-Betriebssystem hat sich weit von seinem ursprünglichen, einfachen, serverbasierten Aussehen entfernt. Dieses Betriebssystem hat sich in den ...