logo

Skabeloner i C++ med eksempler

EN skabelon er et simpelt, men meget kraftfuldt værktøj i C++. Den enkle idé er at videregive datatypen som en parameter, så vi ikke behøver at skrive den samme kode for forskellige datatyper. For eksempel kan en softwarevirksomhed være nødt til at sortere() efter forskellige datatyper. I stedet for at skrive og vedligeholde flere koder, kan vi skrive én sort() og videregive datatypen som en parameter.

C++ tilføjer to nye nøgleord til at understøtte skabeloner: 'skabelon' og 'typenavn' . Det andet søgeord kan altid erstattes af nøgleordet 'klasse' .



Hvordan virker skabeloner?

Skabeloner udvides på kompileringstidspunktet. Det er ligesom makroer. Forskellen er, at compileren udfører typekontrol før skabelonudvidelse. Ideen er enkel, kildekoden indeholder kun funktion/klasse, men kompileret kode kan indeholde flere kopier af samme funktion/klasse.

skabeloner-cpp

Funktionsskabeloner

Vi skriver en generisk funktion, som kan bruges til forskellige datatyper. Eksempler på funktionsskabeloner er sort(), max(), min(), printArray().

For at vide mere om emnet henvises til Generisk i C++ .



Eksempel:

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 '>' er overbelastet skabelonT myMax(T x, T y) { return (x> y) ? x: y; } int main() {// Kald myMax for 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>

Eksempel: Implementerer Boble sortering ved hjælp af skabeloner 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 (a, n);  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>

Klasse skabeloner

Klasseskabeloner som funktionsskabeloner, klasseskabeloner er nyttige, når en klasse definerer noget, der er uafhængigt af datatypen. Kan være nyttigt til klasser som LinkedList, BinaryTree, Stack, Queue, Array osv.



Eksempel:

C++
// C++ Program to implement // template Array class #include  using namespace std; template klasse Array { privat: T* ptr;  int størrelse; public: Array(T arr[], int s);  void print(); }; skabelonArray::Array(T arr[], int s) { ptr = new T[s];  størrelse = s;  for (int i = 0; i< size; i++)  ptr[i] = arr[i]; } template void Array::print() { for (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();  retur 0; }>

Produktion
 1 2 3 4 5>

Kan der være mere end ét argument for skabeloner?

Ja, ligesom normale parametre kan vi sende mere end én datatype som argumenter til skabeloner. Følgende eksempel viser det samme.

Eksempel:

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

Produktion
Constructor Called Constructor Called>

Kan vi angive en standardværdi for skabelonargumenter?

Ja, ligesom normale parametre kan vi angive standardargumenter til skabeloner. Følgende eksempel viser det samme.

Eksempel:

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

Produktion
Constructor Called>

Hvad er forskellen mellem funktionsoverbelastning og skabeloner?

Både funktionsoverbelastning og skabeloner er eksempler på polymorfi-træk ved OOP. Funktionsoverbelastning bruges, når flere funktioner udfører ret ens (ikke identiske) operationer, skabeloner bruges, når flere funktioner udfører identiske operationer.

Hvad sker der, når der er et statisk medlem i en skabelonklasse/-funktion?

Hver forekomst af en skabelon indeholder sin egen statiske variabel. Se Skabeloner og statiske variable for flere detaljer.

Hvad er skabelonspecialisering?

Skabelonspecialisering giver os mulighed for at have forskellige koder for en bestemt datatype. Se Skabelon specialisering for flere detaljer.

Kan vi overføre ikke-type parametre til skabeloner?

Vi kan videregive ikke-type argumenter til skabeloner. Ikke-type parametre bruges hovedsageligt til at specificere maks. eller min. værdier eller enhver anden konstant værdi for en bestemt forekomst af en skabelon. Det vigtige at bemærke om ikke-type parametre er, at de skal være const. Compileren skal kende værdien af ​​ikke-type parametre på kompileringstidspunktet. Fordi compileren skal oprette funktioner/klasser for en specificeret ikke-typeværdi på kompileringstidspunktet. I nedenstående program, hvis vi erstatter 10000 eller 25 med en variabel, får vi en compiler fejl.

Eksempel:

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;  for (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);    retur 0; }>

Produktion
10 1>

Her er et eksempel på et C++-program til at vise forskellige datatyper ved hjælp af en konstruktør og skabelon. Vi udfører et par handlinger

  • overføre tegnværdi ved at oprette et objekt i main()-funktionen.
  • sende heltalsværdi ved at oprette et objekt i main()-funktionen.
  • sende float-værdi ved at oprette et objekt i main()-funktionen.

Eksempel:

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 af typen skabelon 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');  // videregivelse af heltalsværdi ved at oprette en objektinfo q(22);  // videregivelse af flydende værdi ved at oprette en objektinfor(2,25);  retur 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>

Skabelon Argument Fradrag

Skabelonargument-fradrag udleder automatisk datatypen for argumentet, der sendes til klasse- eller funktionsskabelonerne. Dette giver os mulighed for at instansiere skabelonen uden eksplicit at angive datatypen.

Overvej f.eks. nedenstående funktionsskabelon for at gange to tal:

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

Generelt, når vi ønsker at bruge multiply()-funktionen til heltal, skal vi kalde det sådan:

multiply (25, 5);>

Men vi kan også kalde det:

multiply(23, 5);>

Vi specificerer ikke eksplicit typen, dvs. 1,3 er heltal.

Det samme gælder for skabelonklasserne (kun siden C++17). Antag, at vi definerer skabelonklassen som:

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

Hvis vi vil oprette en forekomst af denne klasse, kan vi bruge en af ​​følgende syntaks:

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

Bemærk: Det er vigtigt at bemærke, at skabelonargumentfradraget for klasser kun er tilgængeligt siden C++17, så hvis vi forsøger at bruge automatisk skabelonargumentfradrag for en klasse i tidligere version, vil det give en fejl.

Eksempel på skabelonargumentfradrag

Nedenstående eksempel viser, hvordan STL-vektorklasseskabelonen udleder datatypen uden at være udtrykkeligt specificeret.

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>

Bemærk: Ovenstående program vil mislykkes ved kompilering i C++14 og nedenunder compiler, da klasseskabelonargument-fradrag blev tilføjet i C++17.

np.unik

Funktion Skabelon Argumenter Fradrag

Funktionsskabelon argument fradrag har været en del af C++ siden C++98 standarden. Vi kan springe over at erklære den type argumenter, vi ønsker at overføre til funktionsskabelonen, og compileren vil automatisk udlede typen ved hjælp af de argumenter, vi sendte i funktionskaldet.

Eksempel: I det følgende eksempel demonstrerer vi, hvordan funktioner i C++ automatisk udleder deres type af sig selv.

C++
// C++ program to illustrate the function template argument // deduction #include  using namespace std; // defining function template template t multiplicer(t først, t sekund) { returner første * sekund; } // driverkode int main() { auto resultat = multiplicer(10, 20);  std::cout<< 'Multiplication OF 10 and 20: ' << result  << std::endl;  return 0; }>

Produktion
Multiplication OF 10 and 20: 200>

Bemærk: For funktionsskabelonerne, som har samme type for argumenterne som template void function(t a1, t a2){}, kan vi ikke videregive argumenter af forskellige typer.

Klasseskabelonargumenter fradrag (C++17 og frem)

Klasseskabelonen argument fradrag blev tilføjet i C++17 og har siden været en del af sproget. Det giver os mulighed for at oprette klasseskabelonforekomster uden eksplicit definition af typerne ligesom funktionsskabeloner.

Eksempel: I det følgende eksempel demonstrerer vi, hvordan compileren automatisk klassificerer skabeloner i C++.

C++
// C++ Program to implement Class Template Arguments // Deduction #include  #include  #include  using namespace std; // Defining class template template klasse elev { privat: streng elev_navn;  T total_marks; public: // Parametriseret konstruktør elev(streng n, T m): elev_navn(n) , total_marks(m) { } void getinfo() {// udskrivning af detaljerne for elevcout<< '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>

Her betyder i int, og d betyder dobbelt.

For skabelon-metaprogrammering, r efter følgende artikel - Skabelon Metaprogrammering .

Tag en Quiz om skabeloner . Java understøtter også disse funktioner. Java kalder det generiske lægemidler .