logo

Šablóny v C++ s príkladmi

A šablóna je jednoduchý, ale veľmi výkonný nástroj v C++. Jednoduchou myšlienkou je odovzdať typ údajov ako parameter, aby sme nemuseli písať rovnaký kód pre rôzne typy údajov. Napríklad softvérová spoločnosť môže potrebovať triediť () pre rôzne typy údajov. Namiesto písania a údržby viacerých kódov môžeme napísať jeden sort() a odovzdať dátový typ ako parameter.

C++ pridáva dve nové kľúčové slová na podporu šablón: 'šablóna' a ‘typename’ . Druhé kľúčové slovo môže byť vždy nahradené kľúčovým slovom 'trieda' .



Ako fungujú šablóny?

Šablóny sa rozširujú v čase kompilátora. Toto je ako makrá. Rozdiel je v tom, že kompilátor vykonáva kontrolu typu pred rozšírením šablóny. Myšlienka je jednoduchá, zdrojový kód obsahuje iba funkciu/triedu, ale skompilovaný kód môže obsahovať viacero kópií tej istej funkcie/triedy.

šablóny-cpp

Šablóny funkcií

Píšeme generickú funkciu, ktorú možno použiť pre rôzne typy údajov. Príklady šablón funkcií sú sort(), max(), min(), printArray().

Ak sa chcete dozvedieť viac o téme, pozrite si Generiká v C++ .



Príklad:

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 '>' je preťažená šablónaT myMax(T x, T y) { return (x> y) ? x : y; } int main() { // Volanie myMax pre 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; }>

Výkon
7 7 g>

Príklad: Implementácia Bublinové triedenie pomocou šablón v 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; }>

Výkon
 Sorted array : 10 20 30 40 50>

Šablóny tried

Šablóny tried, ako sú šablóny funkcií, šablóny tried sú užitočné, keď trieda definuje niečo, čo je nezávislé od typu údajov. Môže byť užitočný pre triedy ako LinkedList, BinaryTree, Stack, Queue, Array atď.



Príklad:

štvrťroku v podnikaní
C++
// C++ Program to implement // template Array class #include  using namespace std; template class Array { private: T* ptr;  int veľkosť; public: Array(T arr[], int s);  void print(); }; šablónaPole::Pole(T arr[], int s) { ptr = new T[s];  veľkosť = s;  pre (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();  návrat 0; }>

Výkon
 1 2 3 4 5>

Môže existovať viac ako jeden argument pre šablóny?

Áno, podobne ako bežné parametre, môžeme šablónam odovzdať viac ako jeden typ údajov ako argumenty. Nasledujúci príklad ukazuje to isté.

Príklad:

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

Výkon
Constructor Called Constructor Called>

Môžeme zadať predvolenú hodnotu pre argumenty šablóny?

Áno, ako normálne parametre, môžeme špecifikovať predvolené argumenty pre šablóny. Nasledujúci príklad ukazuje to isté.

Príklad:

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

Výkon
Constructor Called>

Aký je rozdiel medzi preťažením funkcií a šablónami?

Preťaženie funkcií aj šablóny sú príkladmi vlastností polymorfizmu OOP. Preťaženie funkcií sa používa, keď viaceré funkcie vykonávajú celkom podobné (nie identické) operácie, šablóny sa používajú, keď viaceré funkcie vykonávajú rovnaké operácie.

Čo sa stane, keď je v triede/funkcii šablóny statický člen?

Každá inštancia šablóny obsahuje svoju vlastnú statickú premennú. Pozri Šablóny a statické premenné pre viac detailov.

Čo je špecializácia šablón?

Špecializácia šablón nám umožňuje mať rôzne kódy pre konkrétny typ údajov. Pozri Špecializácia šablón pre viac detailov.

Môžeme šablónam odovzdať netypové parametre?

Netypové argumenty môžeme odovzdať šablónam. Netypové parametre sa používajú hlavne na špecifikovanie maximálnych alebo minimálnych hodnôt alebo akejkoľvek inej konštantnej hodnoty pre konkrétnu inštanciu šablóny. Pri netypových parametroch je dôležité poznamenať, že musia byť konšt. Kompilátor musí poznať hodnotu netypových parametrov v čase kompilácie. Pretože kompilátor potrebuje vytvoriť funkcie/triedy pre zadanú netypovú hodnotu v čase kompilácie. Ak v programe nižšie nahradíme 10000 alebo 25 premennou, dostaneme chybu kompilátora.

Príklad:

návratové pole java
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;  pre (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);    návrat 0; }>

Výkon
10 1>

Tu je príklad programu C++ na zobrazenie rôznych typov údajov pomocou konštruktora a šablóny. Vykonáme niekoľko akcií

  • odovzdaním hodnoty znaku vytvorením objektu vo funkcii main().
  • odovzdaním celočíselnej hodnoty vytvorením objektu vo funkcii main().
  • odovzdaním hodnoty float vytvorením objektu vo funkcii main().

Príklad:

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: // konštruktor typu template 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');  // odovzdanie celočíselnej hodnoty vytvorením informácií o objekte q(22);  // odovzdanie hodnoty float vytvorením informácií o objekter(2,25);  návrat 0; }>

Výkon
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>

Odpočet argumentov podľa šablóny

Dedukcia argumentu šablóny automaticky odvodí typ údajov argumentu odovzdaného šablóne triedy alebo funkcie. To nám umožňuje vytvoriť inštanciu šablóny bez explicitného určenia typu údajov.

Zvážte napríklad nižšie uvedenú šablónu funkcie na vynásobenie dvoch čísel:

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

Vo všeobecnosti, keď chceme použiť funkciu multiply() pre celé čísla, musíme ju nazvať takto:

multiply (25, 5);>

Môžeme to však nazvať aj takto:

multiply(23, 5);>

Nešpecifikujeme explicitne typ, tj 1,3 sú celé čísla.

To isté platí pre triedy šablón (len od C++ 17). Predpokladajme, že definujeme triedu šablón ako:

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

Ak chceme vytvoriť inštanciu tejto triedy, môžeme použiť ktorúkoľvek z nasledujúcich syntaxí:

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

Poznámka: Je dôležité poznamenať, že dedukcia argumentov šablóny pre triedy je dostupná len od C++17, takže ak sa pokúsime použiť automatickú dedukciu argumentov šablóny pre triedu v predchádzajúcej verzii, vyvolá to chybu.

Príklad odpočtu argumentov podľa šablóny

Nasledujúci príklad ukazuje, ako šablóna vektorovej triedy STL odvodzuje typ údajov bez toho, aby bol explicitne špecifikovaný.

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 << ' ';  } }>


Výkon

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

Poznámka: Vyššie uvedený program zlyhá pri kompilácii v kompilátore C ++ 14 a nižšie, pretože v C ++ 17 bol pridaný odpočet argumentov šablóny triedy.

Odpočet argumentov šablóny funkcie

Dedukcia argumentov šablóny funkcií je súčasťou C++ od štandardu C++98. Môžeme preskočiť deklarovanie typu argumentov, ktoré chceme odovzdať šablóne funkcie a kompilátor automaticky odvodí typ pomocou argumentov, ktoré sme odovzdali vo volaní funkcie.

Príklad: V nasledujúcom príklade demonštrujeme, ako funkcie v C++ automaticky dedukujú svoj typ samy.

C++
// C++ program to illustrate the function template argument // deduction #include  using namespace std; // defining function template template t multiply(t first, t second) { return first * second; } // kód ovládača int main() { automatický výsledok = multiply(10, 20);  std::cout<< 'Multiplication OF 10 and 20: ' << result  << std::endl;  return 0; }>

Výkon
Multiplication OF 10 and 20: 200>

Poznámka: Pre šablóny funkcií, ktoré majú rovnaký typ pre argumenty, ako je template void function(t a1, t a2){}, nemôžeme odovzdať argumenty rôznych typov.

np.concatenate

Odpočet argumentov šablóny triedy (od C++17)

Dedukcia argumentov šablóny triedy bola pridaná v C++ 17 a odvtedy je súčasťou jazyka. Umožňuje nám vytvárať inštancie šablón triedy bez explicitnej definície typov, rovnako ako šablóny funkcií.

Príklad: V nasledujúcom príklade demonštrujeme, ako kompilátor automaticky triedi šablóny v C++.

C++
// C++ Program to implement Class Template Arguments // Deduction #include  #include  #include  using namespace std; // Defining class template template class student { private: string meno_studenta;  T total_marks; public: // Parametrizovaný konštruktor student(string n, T m) : meno_studenta(n) , total_marks(m) { } void getinfo() { // tlač podrobností o študentovi cout<< '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; }>


Výkon

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

Tu i znamená int a d znamená double.

Pre šablónové metaprogramovanie, r pozri nasledujúci článok - Metaprogramovanie šablón .

Vezmite a Kvíz o šablónach . Java podporuje aj tieto funkcie. Java to nazýva generiká .