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:
skabelonT 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 << piOg funktionen ville vise 3.14. Udtrykket pi
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:
skabelonU 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:
skabelonT 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:
Aldercout << 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:
skabelonT John = 11;
U Peter = 12.3;
T Mary = 13;
U Joy = 14.6;
;
En relevant kode for hovedfunktionen () er som følger:
Aldercout << 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:
skabelonT John;
U Peter;
T Mary;
U glæde;
;
Alder
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:
#omfatteved hjælp af namespace std;
skabelon
T John = N;
U Peter = 12.3;
T Mary = N;
U Joy = 14.6;
;
int main ()
Alder
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:
#omfatteved 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
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:
Aldercout << 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:
#omfatteved hjælp af namespace std;
skabelon
int John = 11;
flyde Peter = 12.3;
int Mary = 13;
flyde glæde = 14.6;
;
int main ()
Alder
cout << gradeB.John << " << gradeB.Mary << '\n';
Alder
cout << gradeC.Peter << " << gradeC.Joy << '\n';
Alder
cout << gradeD.John << " << gradeD.Joy << '\n';
Alder <> klasse A; // som standard
cout << gradeA.John << " << gradeA.Joy << '\n';
returnere 0;
Outputtet er:
11 1312.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:
#omfatteved hjælp af namespace std;
skabelon
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:
#omfatteved hjælp af namespace std;
skabelon
skabelon
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:
#omfatteved hjælp af namespace std;
skabelon
cout << "There are " << no << " books worth " << cha << str << " in the store." << '\n';
skabelon
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:
#omfatteved 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:
#omfatteved hjælp af namespace std;
skabelon
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.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:
skabelonskabelon
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:
#omfatteved hjælp af namespace std;
skabelon
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
int main ()
TheCla
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.