C ++

Sådan bruges C ++ skabeloner

Sådan bruges C ++ skabeloner

Introduktion

I grundlæggende C ++ programmering er datatypen f.eks.g., int eller char, skal angives i en erklæring eller en definition. En værdi som 4 eller 22 eller -5 er en int. En værdi som 'A' eller 'b' eller 'c' er et tegn. Skabelonmekanismen giver programmøren mulighed for at bruge en generisk type til et sæt aktuelle typer. For eksempel kan programmøren beslutte at bruge identifikatoren T til int eller char. Det er muligt for en C ++ - algoritme at have mere end en generisk type. Med for eksempel T for int eller char kan U muligvis stå for float- eller pointer-typen. En klasse, såsom streng eller vektorklasse, er som en datatype, og de instantierede objekter er som værdier af datatypen, hvilket er den angivne klasse. Så skabelonmekanismen giver også programmøren mulighed for at bruge en generisk type-id til et sæt klasser.

En C ++ skabelon opretter en algoritme uafhængig af den anvendte datatype. Så den samme algoritme, med mange forekomster af samme type, kan bruge forskellige typer ved forskellige udførelser. Enhederne af variabel, funktion, struktur og klasse kan have skabeloner. Denne artikel forklarer, hvordan man erklærer skabeloner, hvordan man definerer skabeloner, og hvordan man anvender dem i C++. Du bør allerede have kendskab til de førnævnte enheder for at forstå de emner, der er omfattet af denne artikel.

Typer

Skalar

De skalære typer er ugyldige, bool, char, int, float og pointer.

Klasser som typer

En bestemt klasse kan betragtes som en type og dens objekter som mulige værdier.

En generisk type repræsenterer et sæt skalartyper. Listen over skalartyper er omfattende. Int-typen har for eksempel andre relaterede typer, såsom kort int, lang int osv. En generisk type kan også repræsentere et sæt klasser.

Variabel

Et eksempel på en skabelondeklaration og definition er som følger:

skabelon
T pi = 3.14;

Inden du fortsætter, skal du bemærke, at denne form for udsagn ikke kan vises i hovedfunktionen () eller noget blokområde. Den første linje er skabelon-head-erklæringen med det programmør-valgte generiske typenavn, T. Den næste linje er definitionen af ​​identifikatoren, pi, som er af den generiske type, T. Præcision, uanset om T er en int eller en float eller en anden type, kan gøres i C ++ main () -funktionen (eller en anden funktion). En sådan præcision udføres med variablen pi og ikke T.

Den første linje er skabelonhovederklæringen. Denne erklæring begynder med det reserverede ord, skabelon og derefter de åbne og lukkede vinkelparenteser. Inden for vinkelparenteserne er der mindst en generisk typeidentifikator, såsom T, ovenfor. Der kan være mere end en generisk typeidentifikator, med hver forud for det reserverede ord, typenavn. Sådanne generiske typer i denne position kaldes skabelonparametre.

Følgende udsagn kan skrives i hoved () eller i en hvilken som helst anden funktion:

cout << pi << '\n';

Og funktionen ville vise 3.14. Udtrykket pi bestemmer den nøjagtige type T for variablen pi. Specialisering bestemmer den specifikke datatype for skabelonparameteren. Instantiering er den C ++ interne proces til oprettelse af den bestemte type, såsom float, i dette tilfælde. Forveks ikke med at instantere en skabelonparameter og at starte en klasse. I skabelonemnet kan mange datatyper have et generisk typenavn, mens mange klasser kan have et generisk klassenavn. Dog kaldes det generiske klassenavn for klasser simpelthen en klasse og ikke et klassenavn. En værdi er også til en datatype, såsom int, som et instantieret objekt er til en klasse, såsom String-klassen.

Ved specialisering placeres den valgte datatype, såsom float, i vinkelparenteser efter variablen. Hvis der er mere end én skabelonparameter i skabelonhoveddeklarationen, vil der være et tilsvarende antal datatyper i samme rækkefølge i specialiseringsudtrykket.

Ved specialisering er en type kendt som et skabelonargument. Forveks ikke mellem dette og funktionsargumentet for funktionsopkald.

Standardtype

Hvis der ikke gives nogen type ved specialisering, antages standardtypen. Så fra følgende udtryk:

skabelon
U pi = "kærlighed";
displayet fra:
cout << pi<> << '\n';

er "kærlighed" til den konstante markør til char. Bemærk i erklæringen, at U = const char *. Vinkelbeslagene vil være tomme ved specialisering (ingen type angivet); den faktiske type betragtes som en const pointer til char, standardtypen. Hvis der var brug for en anden type ved specialisering, ville typenavnet blive skrevet i vinkelparenteserne. Når standardtypen ønskes ved specialisering, er det valgfrit at gentage typen i vinkelbeslagene, dvs.e., vinkelbeslagene kan efterlades tomme.

Bemærk: standardtypen kan stadig ændres ved specialisering ved at have en anden type.

struct

Følgende eksempel viser, hvordan en skabelonparameter kan bruges med en struktur:

skabelon struct Ages

T John = 11;
T Peter = 12;
T Mary = 13;
T Glæde = 14;
;

Disse er aldre for studerende i en klasse (klasse). Den første linje er skabelonerklæringen. Kroppen i seler er den egentlige definition af skabelonen. Alderne kan sendes i hovedfunktionen () med følgende:

Alder klasse7;
cout << grade7.John << " << grade7.Mary << '\n';

Outputtet er: 11 13. Den første erklæring her udfører specialiseringen. Bemærk hvordan det er lavet. Det giver også et navn til et objekt i strukturen: grade7. Den anden erklæring har almindelige strukturerede objektudtryk. En struktur er som en klasse. Her er Ages som et klassenavn, mens grade7 er et objekt i klassen (struct).

Hvis nogle aldre er heltal, og andre er flydende, har strukturen brug for to generiske parametre som følger:

skabelon struct Ages

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

En relevant kode for hovedfunktionen () er som følger:

Alder klasse7;
cout << grade7.John << " << grade7.Peter << '\n';

Outputtet er: 11 12.3. Ved specialisering skal rækkefølgen af ​​typerne (argumenterne) svare til rækkefølgen af ​​de generiske typer i erklæringen.

Skabelondeklarationen kan adskilles fra definitionen som følger:

skabelon struct Ages

T John;
U Peter;
T Mary;
U glæde;
;
Alder klasse7 = 11, 12.3, 13, 14.6;

Det første kodesegment er rent en erklæring af en skabelon (der er ingen tildelinger). Det andet kodesegment, som kun er en sætning, er definitionen af ​​identifikatoren, grade7. Venstre side er erklæringen om identifikatoren, klasse 7. Højre side er initialiseringslisten, som tildeler de tilsvarende værdier til struct-medlemmerne. Det andet segment (sætning) kan skrives i hovedfunktionen (), mens det første segment forbliver uden for hovedfunktionen ().

Ikke-type

Eksempler på ikke-datatyper inkluderer int, markør til objekt, markør til funktion og autotyper. Der er andre ikke-typer, som denne artikel ikke behandler. En ikke-type er som en ufuldstændig type, hvis værdi er angivet senere og ikke kan ændres. Som parameter begynder det med en bestemt ikke-type efterfulgt af en identifikator. Værdien af ​​identifikatoren gives senere ved specialisering og kan ikke ændres igen (som en konstant, hvis værdi er angivet senere). Følgende program illustrerer dette:

#omfatte
ved hjælp af namespace std;
skabelon struct Ages

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

Alder klasse7;
cout << grade7.John << " << grade7.Joy << '\n';
returnere 0;

Ved specialisering er den første type int i vinkelparenteserne mere for formalitet for at sikre, at antallet og rækkefølgen af ​​parametre svarer til antallet og rækkefølgen af ​​typer (argumenter). Værdien af ​​N er givet ved specialisering. Outputtet er: 11 14.6.

Delvis specialisering

Lad os antage, at en skabelon har fire generiske typer, og at der blandt de fire typer er behov for to standardtyper. Dette kan opnås ved hjælp af den delvise specialiseringskonstruktion, som ikke anvender tildelingsoperatøren. Så den delvise specialiseringskonstruktion giver standardværdier til et undersæt af generiske typer. Imidlertid er der behov for en basisklasse (struct) og en delvis specialiseringsklasse (struct) i den delvise specialiseringsordning. Følgende program illustrerer dette for en generisk type ud af to generiske typer:

#omfatte
ved hjælp af namespace std;
// base skabelon klasse
skabelon
struct Ages

;
// delvis specialisering
skabelon
struct Ages

T1 John = 11;
flyde Peter = 12.3;
T1 Mary = 13;
flyde glæde = 14.6;
;
int main ()

Alder klasse7;
cout << grade7.John << " << grade7.Joy << '\n';
returnere 0;

Identificer baseklassedeklarationen og dens delvise klassedefinition. Basisklassens skabelonhoveddeklaration har alle de nødvendige generiske parametre. Skabelonhovederklæringen for den delvise specialiseringsklasse har kun den generiske type. Der er et ekstra sæt vinkelbeslag, der anvendes i skemaet, der kommer lige efter navnet på klassen i definitionen af ​​delvis specialisering. Det er, hvad der faktisk gør den delvise specialisering. Den har standardtypen og den ikke-standardtype i den rækkefølge, der er skrevet i basisklassen. Bemærk, at standardtypen stadig kan gives en anden type i hovedfunktionen ().

Den relevante kode i hovedfunktionen () kan være som følger:

Alder klasse7;
cout << grade7.John << " << grade7.Joy << '\n';

Outputtet er: 11 14.6.

Skabelonparameterpakke

En parameterpakke er en skabelonparameter, der accepterer nul eller flere generiske skabeloner for de tilsvarende datatyper. Parameterpakke-parameteren begynder med det reserverede ord typenavn eller klasse. Dette efterfølges af tre prikker og derefter identifikatoren for pakken. Følgende program illustrerer, hvordan en skabelonparameterpakke kan bruges med en struktur:

#omfatte
ved hjælp af namespace std;
skabelon struct Ages

int John = 11;
flyde Peter = 12.3;
int Mary = 13;
flyde glæde = 14.6;
;
int main ()

Alder klasseB;
cout << gradeB.John << " << gradeB.Mary << '\n';
Alder klasse C;
cout << gradeC.Peter << " << gradeC.Joy << '\n';
Alder klasse D;
cout << gradeD.John << " << gradeD.Joy << '\n';
Alder <> klasse A; // som standard
cout << gradeA.John << " << gradeA.Joy << '\n';
returnere 0;

Outputtet er:

11 13
12.3 14.6
11 14.6
11 14.6

Funktionsskabeloner

De ovennævnte skabelonfunktioner gælder på samme måde som funktionsskabeloner. Følgende program viser en funktion med to generiske skabelonparametre og tre argumenter:

#omfatte
ved hjælp af namespace std;
skabelon ugyldig funk (T no, U cha, const char * str)

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

int main ()

func (12, '$', "500");
returnere 0;

Outputtet er som følger:

Der er 12 bøger til en værdi af $ 500 i butikken.

Adskillelse fra prototype

Funktionsdefinitionen kan adskilles fra prototypen, som følgende program viser:

#omfatte
ved hjælp af namespace std;
skabelon ugyldig funk (T no, U cha, const char * str);
skabelon ugyldig funk (T no, U cha, const char * str)

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

int main ()

func (12, '$', "500");
returnere 0;

Bemærk: Funktionsskabelondeklarationen kan ikke vises i hovedfunktionen () eller i nogen anden funktion.

Overbelastning

Overbelastning af den samme funktion kan finde sted med forskellige erklæringer om skabelonhoved. Følgende program illustrerer dette:

#omfatte
ved hjælp af namespace std;
skabelon ugyldig funk (T no, U cha, const char * str)

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

skabelon void func (T no, const char * str)

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

int main ()

func (12, '$', "500");
funk (12, "500");
returnere 0;

Outputtet er:

Der er 12 bøger til en værdi af $ 500 i butikken.

Der er 12 bøger til en værdi af $ 500 i butikken.

Klasseskabeloner

Funktionerne i de ovennævnte skabeloner gælder på samme måde som klasseskabeloner. Følgende program er erklæring, definition og brug af en simpel klasse:

#omfatte
ved hjælp af namespace std;
klasse TheCla

offentlig:
int num;
statisk char ch;
ugyldig funk (char cha, const char * str)

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

statisk tomrums sjov (char ch)

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

;
int main ()

TheCla protesterer;
obj.num = 12;
obj.func ('$', "500");
returnere 0;

Outputtet er som følger:

Der er 12 bøger til en værdi af $ 500 i butikken.

Følgende program er ovenstående program med en skabelon-head-erklæring:

#omfatte
ved hjælp af namespace std;
skabelon klasse TheCla

offentlig:
T num;
statisk U ch;
ugyldig funk (U cha, const char * str)

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

statisk tomrums sjov (U ch)

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

;
int main ()

TheCla obj;
obj.num = 12;
obj.func ('$', "500");
returnere 0;

I stedet for ordet typenavn i skabelonparameterlisten kan ordklassen bruges. Bemærk specialiseringen i objektets erklæring. Outputtet er stadig det samme:

Der er 12 bøger til en værdi af $ 500 i butikken.

Separat erklæring

Klasseskabelonerklæringen kan adskilles fra klassekoden som følger:

skabelon klasse TheCla;
skabelon klasse TheCla

offentlig:
T num;
statisk U ch;
ugyldig funk (U cha, const char * str)

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

statisk tomrums sjov (U ch)

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

;

Beskæftiger sig med statiske medlemmer

Følgende program viser, hvordan du får adgang til et statisk datamedlem og en statisk medlemsfunktion:

#omfatte
ved hjælp af namespace std;
skabelon klasse TheCla

offentlig:
T num;
statisk U ch;
ugyldig funk (U cha, const char * str)

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

statisk tomrums sjov (U cha)

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

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

TheCla::sjovt('.');
returnere 0;

Tildeling af en værdi til et statisk datamedlem er en erklæring og kan ikke være i hoved (). Bemærk brugen og placeringen af ​​de generiske typer og den data generiske type i tildelingserklæringen. Derudover skal du bemærke, at den statiske datamedlemfunktion er blevet kaldt i main () med de aktuelle skabelondatatyper. Outputtet er følgende:

Officiel statisk medlemsfunktion.

Kompilering

Erklæringen (overskrift) og definitionen af ​​en skabelon skal være i en fil. Det vil sige, de skal være i samme oversættelsesenhed.

Konklusion

C ++ skabeloner gør en algoritme uafhængig af den anvendte datatype. Enhederne af variabel, funktion, struktur og klasse kan have skabeloner, der involverer erklæring og definition. Oprettelse af en skabelon indebærer også specialisering, hvilket er, når en generisk type tager en faktisk type. Erklæringen og definitionen af ​​en skabelon skal begge være i en oversættelsesenhed.

Sådan vises OSD-overlay i fuldskærms Linux-apps og -spil
Afspilning af fuldskærmsspil eller brug af apps i distraktionsfri fuldskærmstilstand kan afskære dig fra relevante systemoplysninger, der er synlige i...
Top 5 spiloptagelseskort
Vi har alle set og elsket streaming af gameplay på YouTube. PewDiePie, Jakesepticye og Markiplier er kun nogle af de bedste spillere, der har tjent mi...
Sådan udvikler du et spil på Linux
For et årti siden ville ikke mange Linux-brugere forudsige, at deres foretrukne operativsystem en dag ville være en populær spilplatform til kommercie...