logo

Mallar i C++ med exempel

A mall är ett enkelt men mycket kraftfullt verktyg i C++. Den enkla idén är att skicka datatypen som en parameter så att vi inte behöver skriva samma kod för olika datatyper. Till exempel kan ett mjukvaruföretag behöva sortera() för olika datatyper. Istället för att skriva och underhålla flera koder kan vi skriva en sort() och skicka datatypen som en parameter.

C++ lägger till två nya nyckelord för att stödja mallar: 'mall' och 'typnamn' . Det andra nyckelordet kan alltid ersättas med nyckelordet 'klass' .



Hur fungerar mallar?

Mallar utökas vid kompilatorn. Det här är som makron. Skillnaden är att kompilatorn gör typkontroll innan mallexpansion. Tanken är enkel, källkoden innehåller endast funktion/klass, men kompilerad kod kan innehålla flera kopior av samma funktion/klass.

mallar-cpp

Funktionsmallar

Vi skriver en generisk funktion som kan användas för olika datatyper. Exempel på funktionsmallar är sort(), max(), min(), printArray().

För att veta mer om ämnet se Generika i C++ .



Exempel:

C++
// C++ Program to demonstrate // Use of template #include  using namespace std; // One function works for all data types. This would work // even for user defined types if operator '>' är överbelastad mallT myMax(T x, T y) { return (x> y) ? x: y; } int main() {// Ring myMax för int cout<< myMax (3, 7)<< endl;  // call myMax for double  cout << myMax(3,0, 7,0)<< endl;  // call myMax for char  cout << myMax('g', 'e')<< endl;  return 0; }>

Produktion
7 7 g>

Exempel: Genomförande Bubblesort använda mallar i C++

ascii-tabell i c
C++
// C++ Program to implement // Bubble sort // using template function #include  using namespace std; // A template function to implement bubble sort. // We can use this for any data type that supports // comparison operator  template void bubbleSort(T a[], int n) { for (int i = 0; i< n - 1; i++)  for (int j = n - 1; i < j; j--)  if (a[j] < a[j - 1])  swap(a[j], a[j - 1]); } // Driver Code int main() {  int a[5] = { 10, 50, 30, 40, 20 };  int n = sizeof(a) / sizeof(a[0]);  // calls template function  bubbleSort (en);  cout<< ' Sorted array : ';  for (int i = 0; i < n; i++)  cout << a[i] << ' ';  cout << endl;  return 0; }>

Produktion
 Sorted array : 10 20 30 40 50>

Klass mallar

Klassmallar som funktionsmallar, klassmallar är användbara när en klass definierar något som är oberoende av datatypen. Kan vara användbart för klasser som LinkedList, BinaryTree, Stack, Queue, Array, etc.



Exempel:

C++
// C++ Program to implement // template Array class #include  using namespace std; template klass Array { privat: T* ptr;  int storlek; public: Array(T arr[], int s);  void print(); }; mallArray::Array(T arr[], int s) { ptr = new T[s];  storlek = s;  för (int i = 0; i< size; i++)  ptr[i] = arr[i]; } template void Array::print() { för (int i = 0; i< size; i++)  cout << ' ' << *(ptr + i);  cout << endl; } int main() {  int arr[5] = { 1, 2, 3, 4, 5 };  Array a(arr, 5);  a.print();  returnera 0; }>

Produktion
 1 2 3 4 5>

Kan det finnas mer än ett argument för mallar?

Ja, som vanliga parametrar kan vi skicka mer än en datatyp som argument till mallar. Följande exempel visar detsamma.

Exempel:

C++
// C++ Program to implement // Use of template #include  using namespace std; template klass A { T x;  U y; offentlig: A() { cout<< 'Constructor Called' << endl; } }; int main() {  Aa;  A b;  returnera 0; }>

Produktion
Constructor Called Constructor Called>

Kan vi ange ett standardvärde för mallargument?

Ja, som vanliga parametrar kan vi ange standardargument till mallar. Följande exempel visar detsamma.

Exempel:

C++
// C++ Program to implement // Use of template #include  using namespace std; template klass A { public: T x;  U y;  A() { cout<< 'Constructor Called' << endl; } }; int main() {  // This will call A  Aa;  returnera 0; }>

Produktion
Constructor Called>

Vad är skillnaden mellan funktionsöverbelastning och mallar?

Både funktionsöverbelastning och mallar är exempel på polymorfifunktioner hos OOP. Funktionsöverbelastning används när flera funktioner gör ganska lika (inte identiska) operationer, mallar används när flera funktioner gör identiska operationer.

Vad händer när det finns en statisk medlem i en mallklass/funktion?

Varje instans av en mall innehåller sin egen statiska variabel. Ser Mallar och statiska variabler för mer detaljer.

Vad är mallspecialisering?

Mallspecialisering gör att vi kan ha olika koder för en viss datatyp. Ser Mallspecialisering för mer detaljer.

sql beställ efter datum

Kan vi skicka icke-typparametrar till mallar?

Vi kan skicka icke-typargument till mallar. Icke-typparametrar används huvudsakligen för att specificera max- eller minvärden eller något annat konstant värde för en viss instans av en mall. Det viktiga att notera om parametrar av icke-typ är att de måste vara const. Kompilatorn måste känna till värdet av parametrar av icke-typ vid kompilering. Eftersom kompilatorn behöver skapa funktioner/klasser för ett specificerat icke-typvärde vid kompilering. I programmet nedan, om vi ersätter 10000 eller 25 med en variabel, får vi ett kompilatorfel.

Exempel:

C++
// C++ program to demonstrate // working of non-type parameters // to templates in C++ #include  using namespace std; template int arrMin(T arr[], int n) { int m = max;  för (int i = 0; i< n; i++)  if (arr[i] < m)  m = arr[i];  return m; } int main() {  int arr1[] = { 10, 20, 15, 12 };  int n1 = sizeof(arr1) / sizeof(arr1[0]);  char arr2[] = { 1, 2, 3 };  int n2 = sizeof(arr2) / sizeof(arr2[0]);  // Second template parameter  // to arrMin must be a  // constant  cout << arrMin (arr1, n1)<< endl;  cout << arrMin(arr2, n2);    returnera 0; }>

Produktion
10 1>

Här är ett exempel på ett C++-program för att visa olika datatyper med hjälp av en konstruktor och mall. Vi kommer att utföra några åtgärder

  • skicka teckenvärde genom att skapa ett objekt i main()-funktionen.
  • skicka ett heltalsvärde genom att skapa ett objekt i main()-funktionen.
  • skicka flytvärde genom att skapa ett objekt i main()-funktionen.

Exempel:

C++
// C++ program to show different data types using a // constructor and template. #include  using namespace std; // defining a class template template class info { public: // konstruktör av typen mall info(T A) { cout<< '
'  << 'A = ' << A  << ' size of data in bytes:' << sizeof(A);  }  // end of info() }; // end of class // Main Function int main() {  // clrscr();  // passing character value by creating an objects  infop('x');  // skickar heltalsvärde genom att skapa en objektinfo q(22);  // skicka flytvärde genom att skapa en objektinfor(2,25);  returnera 0; }>

Produktion
A = x size of data in bytes:1 A = 22 size of data in bytes:4 A = 2.25 size of data in bytes:4>

Mallargumentavdrag

Mallargumentavdrag härleder automatiskt datatypen för argumentet som skickas till klass- eller funktionsmallarna. Detta gör att vi kan instansiera mallen utan att explicit specificera datatypen.

gör medan loop java

Tänk till exempel på funktionsmallen nedan för att multiplicera två tal:

template  t multiply (t num1,t num2) { return num1*num2; }>

I allmänhet, när vi vill använda multiply()-funktionen för heltal, måste vi kalla det så här:

multiply (25, 5);>

Men vi kan också kalla det:

multiply(23, 5);>

Vi anger inte uttryckligen typen, dvs 1,3 är heltal.

Detsamma gäller för mallklasserna (endast C++17). Anta att vi definierar mallklassen som:

template class student{  private:  t total_marks;  public:  student(t x) : total_marks(x) {} };>

Om vi ​​vill skapa en instans av den här klassen kan vi använda någon av följande syntax:

student stu1(23);    or  student stu2(24);>

Notera: Det är viktigt att notera att mallargumentavdraget för klasser endast är tillgängligt sedan C++17, så om vi försöker använda det automatiska mallargumentavdraget för en klass i tidigare version kommer det att ge ett fel.

Exempel på mallargumentavdrag

Exemplet nedan visar hur STL-vektorklassmallen härleder datatypen utan att vara explicit specificerad.

C++
// C++ Program to illustrate template arguments deduction in // STL #include  #include  using namespace std; int main() {  // creating a vector object without specifying  // type  vector v1{ 1.1, 2.0, 3.9, 4.909 };  cout << 'Elements of v1 : ';  for (auto i : v1) {  cout << i << ' ';  }  // creating a vector object without specifying type  vector v2{ 1, 2, 3, 4 };  cout << endl << 'Elements of v2 : ';  for (auto i : v2) {  cout << i << ' ';  } }>


Produktion

Elements of v1 : 1.1 2 3.9 4.909  Elements of v2 : 1 2 3 4>

Notera: Ovanstående program kommer att misslyckas med kompilering i C++14 och nedan kompilatorn eftersom klassmallsargumentavdrag lades till i C++17.

Funktion Mall Argument Avdrag

Funktionsmallargumentavdrag har varit en del av C++ sedan C++98-standarden. Vi kan hoppa över att deklarera typen av argument vi vill skicka till funktionsmallen och kompilatorn kommer automatiskt att härleda typen med hjälp av argumenten vi skickade i funktionsanropet.

Javascript laddas upp

Exempel: I följande exempel visar vi hur funktioner i C++ automatiskt härleder sin typ av sig själva.

C++
// C++ program to illustrate the function template argument // deduction #include  using namespace std; // defining function template template t multiplicera(t första, t andra) { returnera första * sekund; } // drivrutinskod int main() { auto resultat = multiplicera(10, 20);  std::cout<< 'Multiplication OF 10 and 20: ' << result  << std::endl;  return 0; }>

Produktion
Multiplication OF 10 and 20: 200>

Notera: För funktionsmallarna som har samma typ för argumenten som mall void function(t a1, t a2){}, kan vi inte skicka argument av olika typer.

Avdrag för klassmallargument (C++17 och framåt)

Klassmallens argumentavdrag lades till i C++17 och har sedan dess varit en del av språket. Det tillåter oss att skapa klassmallsinstanserna utan att uttryckligen definiera typerna precis som funktionsmallar.

Exempel: I följande exempel visar vi hur kompilatorn automatiskt klassar mallar i C++.

C++
// C++ Program to implement Class Template Arguments // Deduction #include  #include  #include  using namespace std; // Defining class template template klass elev { privat: sträng elev_namn;  T total_marks; public: // Parameteriserad konstruktor student(sträng n, T m) : student_name(n) , total_marks(m) { } void getinfo() {// skriver ut informationen om studentcout<< 'STUDENT NAME: ' << student_name << endl;  cout << 'TOTAL MARKS: ' << total_marks << endl;  cout << 'Type ID: ' << typeid(total_marks).name()  << endl;  } }; int main() {  student s1('Vipul', 100); // Deduces student  student s2('Yash', 98.5); // Deduces student  s1.getinfo();  s2.getinfo();  return 0; }>


Produktion

STUDENT NAME: Vipul TOTAL MARKS: 100 Type ID: i STUDENT NAME: Yash TOTAL MARKS: 98.5 Type ID: d>

Här betyder i int och d betyder dubbel.

För mallmetaprogrammering, r efter följande artikel - Mall Metaprogrammering .

insättningssort i java

Ta en Frågesport om mallar . Java stöder även dessa funktioner. Java kallar det generika .