C ++

Hur man använder C ++ -mallar

Hur man använder C ++ -mallar

Introduktion

I grundläggande C ++ programmering, datatyp, t.ex.g., int eller char, måste anges i en deklaration eller en definition. Ett värde som 4 eller 22 eller -5 är ett int. Ett värde som 'A' eller 'b' eller 'c' är ett tecken. Mallmekanismen tillåter programmeraren att använda en generisk typ för en uppsättning faktiska typer. Till exempel kan programmeraren välja att använda identifieraren T för int eller char. Det är möjligt för en C ++ - algoritm att ha mer än en generisk typ. Med, säg, T för int eller char, kan U stå för flyt- eller pekartyp. En klass, som strängen eller vektorklassen, är som en datatyp och de instanserade objekten är som värden för datatypen, vilket är den angivna klassen. Så låter mallmekanismen också programmeraren använda en generisk typidentifierare för en uppsättning klasser.

En C ++ - mall skapar en algoritm oberoende av vilken typ av data som används. Så samma algoritm, med många förekomster av samma typ, kan använda olika typer vid olika körningar. Enheterna av variabel, funktion, struktur och klass kan ha mallar. Den här artikeln förklarar hur man deklarerar mallar, hur man definierar mallar och hur man tillämpar dem i C++. Du bör redan ha kunskap om de ovan nämnda enheterna för att förstå ämnena som omfattas av den här artikeln.

Typer

Skalär

Skalartyperna är ogiltiga, bool, char, int, float och pekare.

Klasser som typer

En viss klass kan betraktas som en typ och dess objekt som möjliga värden.

En generisk typ representerar en uppsättning skalartyper. Listan över skalartyper är omfattande. Int-typen har till exempel andra relaterade typer, såsom kort int, lång int, etc. En generisk typ kan också representera en uppsättning klasser.

Variabel

Ett exempel på en malldeklaration och definition är som följer:

mall
T pi = 3.14;

Innan du fortsätter, notera att denna typ av uttalande inte kan visas i huvudfunktionen () eller något blockområde. Den första raden är mallhuvuddeklarationen med det programmerade valda generiska typnamnet T. Nästa rad är definitionen av identifieraren, pi, som är av den generiska typen, T. Precision, oavsett om T är en int eller en flottör eller någon annan typ, kan göras i C ++ main () -funktionen (eller någon annan funktion). Sådan precision kommer att göras med variabeln pi och inte T.

Den första raden är mallhuvuddeklarationen. Denna deklaration börjar med det reserverade ordet, mallen och sedan de öppna och slutna vinkelparenteserna. Inom vinkelfästena finns det minst en generisk typidentifierare, såsom T, ovan. Det kan finnas mer än en generisk typidentifierare, var och en föregås av det reserverade ordet, typnamn. Sådana generiska typer i den positionen kallas mallparametrar.

Följande uttalande kan skrivas i huvud () eller i någon annan funktion:

cout << pi << '\n';

Och funktionen skulle visa 3.14. Uttrycket pi bestämmer den exakta typen av T för variabeln pi. Specialisering bestämmer den specifika datatypen för mallparametern. Instantiering är den interna C ++ - processen för att skapa den specifika typen, till exempel float, i det här fallet. Förväxla inte mellan att starta en mallparameter och att starta en klass. I mallämnet kan många datatyper ha ett generiskt typnamn, medan många klasser kan ha ett generiskt klassnamn. Emellertid kallas det generiska klassnamnet för klasser helt enkelt som en klass och inte som ett klassnamn. Ett värde är också en datatyp, såsom int, som ett instanserat objekt är till en klass, till exempel strängklassen.

Vid specialisering placeras den valda datatypen, som float, i vinkelparenteser efter variabeln. Om det finns mer än en mallparameter i mallhuvuddeklarationen kommer det att finnas ett motsvarande antal datatyper i samma ordning i specialiseringsuttrycket.

Vid specialisering är en typ känd som ett mallargument. Blanda inte mellan detta och funktionsargumentet för funktionsanrop.

Standardtyp

Om ingen typ anges vid specialisering antas standardtypen. Så från följande uttryck:

mall
U pi = "kärlek";
displayen från:
cout << pi<> << '\n';

är "kärlek" för den ständiga pekaren till röding. Notera i deklarationen att U = const char *. Vinkelfästena är tomma vid specialisering (ingen typ anges); den faktiska typen anses vara en const-pekare till char, standardtypen. Om någon annan typ behövdes vid specialisering, skulle typnamnet skrivas i vinkelparenteserna. När standardtyp önskas vid specialisering är det valfritt att upprepa typen i vinkelfästena, dvs.e., vinkelfästena kan lämnas tomma.

Obs: standardtypen kan ändras vid specialisering genom att ha en annan typ.

struct

Följande exempel visar hur en mallparameter kan användas med en struct:

mall struct Åldrar

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

Dessa är åldrar av studenter i en klass (klass). Den första raden är malldeklarationen. Kroppen i hängslen är den faktiska definitionen av mallen. Åldrarna kan anges i huvudfunktionen () med följande:

Åldrar Klass 7;
cout << grade7.John << " << grade7.Mary << '\n';

Utgången är: 11 13. Det första uttalandet här utför specialiseringen. Lägg märke till hur det har gjorts. Det ger också ett namn för ett objekt av strukturen: grad7. Det andra uttalandet har vanliga strukturobjektuttryck. En struktur är som en klass. Här är åldrar som ett klassnamn, medan grad 7 är ett objekt i klassen (struct).

Om vissa åldrar är heltal och andra är flytande, behöver strukturen två generiska parametrar enligt följande:

mall struct Åldrar

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

En relevant kod för huvudfunktionen () är som följer:

Åldrar Klass 7;
cout << grade7.John << " << grade7.Peter << '\n';

Utgången är: 11 12.3. Vid specialisering måste typordningen (argumenten) motsvara ordningen på de generiska typerna i deklarationen.

Malldeklarationen kan skiljas från definitionen enligt följande:

mall struct Åldrar

T John;
U Peter;
T Mary;
U Joy;
;
Åldrar grad 7 = 11, 12.3, 13, 14.6;

Det första kodsegmentet är enbart en malldeklaration (det finns inga tilldelningar). Det andra kodsegmentet, som bara är ett uttalande, är definitionen av identifieraren, grad 7. Den vänstra sidan är deklarationen för identifieraren, grad 7. Den högra sidan är initialiserarlistan som tilldelar motsvarande värden till struct-medlemmarna. Det andra segmentet (uttalande) kan skrivas i huvudfunktionen (), medan det första segmentet förblir utanför huvudfunktionen ().

Icke-typ

Exempel på icke-datatyper inkluderar int, pekare till objekt, pekare att fungera och autotyper. Det finns andra icke-typer som denna artikel inte behandlar. En icke-typ är som en ofullständig typ vars värde ges senare och inte kan ändras. Som en parameter börjar den med en viss icke-typ, följt av en identifierare. Värdet på identifieraren ges senare vid specialisering och kan inte ändras igen (som en konstant vars värde ges senare). Följande program illustrerar detta:

#omfatta
använder namnrymd std;
mall struct Åldrar

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

Åldrar Klass 7;
cout << grade7.John << " << grade7.Joy << '\n';
returnera 0;

Vid specialisering är den första typen, int, i vinkelparenteserna mer för formalitet, för att se till att antalet och ordningen på parametrarna motsvarar antalet och ordningen på typerna (argument). Värdet av N har givits vid specialisering. Utgången är: 11 14.6.

Delvis specialisering

Låt oss anta att en mall har fyra generiska typer och att det bland de fyra typerna finns behov av två standardtyper. Detta kan uppnås med hjälp av den partiella specialiseringskonstruktionen, som inte använder uppdragsoperatören. Så, den partiella specialiseringskonstruktionen ger standardvärden till en delmängd av generiska typer. I det partiella specialiseringsschemat behövs dock en basklass (struct) och en partiell specialiseringsklass (struct). Följande program illustrerar detta för en generisk typ av två generiska typer:

#omfatta
använder namnrymd std;
// basmallklass
mall
struct Åldrar

;
// delvis specialisering
mall
struct Åldrar

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

Åldrar Klass 7;
cout << grade7.John << " << grade7.Joy << '\n';
returnera 0;

Identifiera basklassdeklarationen och dess partiella klassdefinition. Mallklassdeklarationen för basklassen har alla nödvändiga generiska parametrar. Malldeklarationen för den partiella specialiseringsklassen har endast den generiska typen. Det finns en extra uppsättning vinkelfästen som används i schemat som kommer strax efter klassens namn i definitionen av partiell specialisering. Det är det som faktiskt gör den partiella specialiseringen. Den har standardtyp och icke-standardtyp, i den ordning som skrivs i basklassen. Observera att standardtypen fortfarande kan ges en annan typ i huvudfunktionen ().

Den relevanta koden i huvudfunktionen () kan vara följande:

Åldrar Klass 7;
cout << grade7.John << " << grade7.Joy << '\n';

Utgången är: 11 14.6.

Mallparameterpaket

Ett parameterpaket är en mallparameter som accepterar noll eller flera mallgeneriska typer för motsvarande datatyper. Parameterpaketparametern börjar med det reserverade ordet typnamn eller klass. Detta följs av tre punkter och sedan identifieraren för paketet. Följande program illustrerar hur ett mallparameterpaket kan användas med en struktur:

#omfatta
använder namnrymd std;
mall struct Åldrar

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

Åldrar gradB;
cout << gradeB.John << " << gradeB.Mary << '\n';
Åldrar klass C;
cout << gradeC.Peter << " << gradeC.Joy << '\n';
Åldrar grad D;
cout << gradeD.John << " << gradeD.Joy << '\n';
Åldrar <> klass A; // som standard
cout << gradeA.John << " << gradeA.Joy << '\n';
returnera 0;

Utgången är:

11 13
12.3 14.6
11 14.6
11 14.6

Funktionsmallar

Mallfunktionerna som nämns ovan gäller på samma sätt som funktionsmallar. Följande program visar en funktion med två generiska mallparametrar och tre argument:

#omfatta
använder namnrymd std;
mall void func (T no, U cha, const char * str)

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

int main ()

funk (12, '$', "500");
returnera 0;

Utgången är som följer:

Det finns 12 böcker värda $ 500 i butiken.

Separation från prototyp

Funktionsdefinitionen kan separeras från sin prototyp, som följande program visar:

#omfatta
använder namnrymd std;
mall void func (T no, U cha, const char * str);
mall void func (T no, U cha, const char * str)

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

int main ()

funk (12, '$', "500");
returnera 0;

Obs! Funktionsmalldeklarationen kan inte visas i huvudfunktionen () eller i någon annan funktion.

Överbelastning

Överbelastning av samma funktion kan ske med olika mallhuvuddeklarationer. Följande program illustrerar detta:

#omfatta
använder namnrymd std;
mall void func (T no, U cha, const char * str)

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

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

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

int main ()

funk (12, '$', "500");
funk (12, "500");
returnera 0;

Utgången är:

Det finns 12 böcker värda $ 500 i butiken.

Det finns 12 böcker värda $ 500 i butiken.

Klassmallar

Funktionerna i mallarna som nämns ovan gäller på samma sätt som klassmallar. Följande program är deklarationen, definitionen och användningen av en enkel klass:

#omfatta
använder namnrymd std;
klass TheCla

offentlig:
int num;
statisk char ch;
void func (char cha, const char * str)

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

statisk tomrumskul (char ch)

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

;
int main ()

TheCla invände;
obj.num = 12;
obj.funk ('$', "500");
returnera 0;

Utgången är som följer:

Det finns 12 böcker värda $ 500 i butiken.

Följande program är ovanstående program med en mall-huvuddeklaration:

#omfatta
använder namnrymd std;
mall klass TheCla

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

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

statisk tomrumskul (U ch)

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

;
int main ()

TheCla obj;
obj.num = 12;
obj.funk ('$', "500");
returnera 0;

I stället för ordet typnamn i mallparameterlistan kan ordklassen användas. Observera specialiseringen i deklarationen av objektet. Utgången är fortfarande densamma:

Det finns 12 böcker värda $ 500 i butiken.

Separat deklaration

Klassmalldeklarationen kan separeras från klasskoden enligt följande:

mall klass TheCla;
mall klass TheCla

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

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

statisk tomrumskul (U ch)

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

;

Att hantera statiska medlemmar

Följande program visar hur du får åtkomst till en statisk datamedlem och en statisk medlemsfunktion:

#omfatta
använder namnrymd std;
mall klass TheCla

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

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

statisk tomrumskul (U cha)

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

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

TheCla::roligt('.');
returnera 0;

Tilldela ett värde till en statisk datamedlem är en deklaration och kan inte vara i huvudsak (). Notera användningen och positionerna för de generiska typerna och den generiska datatypen i tilldelningsuttalandet. Observera dessutom att den statiska datamedelfunktionen har anropats i huvudsak () med de faktiska malldatatyperna. Resultatet är följande:

Officiell statisk medlemsfunktion.

Sammanställning

Deklarationen (rubriken) och definitionen av en mall måste vara i en fil. Det vill säga de måste vara i samma översättningsenhet.

Slutsats

C ++ - mallar gör en algoritm oberoende av vilken typ av data som används. Enheterna av variabel, funktion, struktur och klass kan ha mallar som involverar deklaration och definition. Att skapa en mall innebär också specialisering, det vill säga när en generisk typ tar en faktisk typ. Deklarationen och definitionen av en mall måste båda vara i en översättningsenhet.

SuperTuxKart för Linux
SuperTuxKart är en fantastisk titel som är utformad för att ge dig Mario Kart-upplevelsen gratis på ditt Linux-system. Det är ganska utmanande och rol...
Battle for Wesnoth Tutorial
Slaget om Wesnoth är ett av de mest populära open source-strategispel som du kan spela just nu. Det här spelet har inte bara utvecklats under mycket l...
0 A.D. Handledning
Av de många strategispelen där ute, 0 A.D. lyckas framstå som en omfattande titel och ett mycket djupt, taktiskt spel trots att det är öppen källkod. ...