logo

Șabloane în C++ cu exemple

A șablon este un instrument simplu, dar foarte puternic în C++. Ideea simplă este să trecem tipul de date ca parametru, astfel încât să nu fie nevoie să scriem același cod pentru diferite tipuri de date. De exemplu, o companie de software poate avea nevoie să sorteze() pentru diferite tipuri de date. În loc să scriem și să menținem mai multe coduri, putem scrie un sort() și trece tipul de date ca parametru.

C++ adaugă două cuvinte cheie noi pentru a sprijini șabloanele: „șablon” și „nume tip” . Al doilea cuvânt cheie poate fi întotdeauna înlocuit cu cuvântul cheie 'clasă' .



Cum funcționează șabloanele?

Șabloanele sunt extinse la momentul compilatorului. Este ca macro-urile. Diferența este că compilatorul face verificarea tipului înainte de extinderea șablonului. Ideea este simplă, codul sursă conține doar funcție/clasă, dar codul compilat poate conține mai multe copii ale aceleiași funcție/clasă.

șabloane-cpp

Șabloane de funcție

Scriem o funcție generică care poate fi utilizată pentru diferite tipuri de date. Exemple de șabloane de funcție sunt sort(), max(), min(), printArray().

Pentru a afla mai multe despre subiect, consultați Generic în C++ .



Exemplu:

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 '>' este un șablon supraîncărcatT myMax(T x, T y) { return (x> y) ? X y; } int main() { // Apelați myMax pentru int cout<< myMax (3, 7)<< endl;  // call myMax for double  cout << myMax(3,0, 7,0)<< endl;  // call myMax for char  cout << myMax('GE')<< endl;  return 0; }>

Ieșire
7 7 g>

Exemplu: Implementarea Sortare cu bule folosind șabloane în 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) { pentru (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; }>

Ieșire
 Sorted array : 10 20 30 40 50>

Șabloane de clasă

Șabloanele de clasă, cum ar fi șabloanele de funcție, șabloanele de clasă sunt utile atunci când o clasă definește ceva care este independent de tipul de date. Poate fi util pentru clase precum LinkedList, BinaryTree, Stack, Queue, Array etc.



Exemplu:

redenumiți un folder linux
C++
// C++ Program to implement // template Array class #include  using namespace std; template class Array { private: T* ptr;  dimensiune int; public: Array(T arr[], int s);  void print(); }; șablonMatrice::Matrice(T arr[], int s) { ptr = new T[s];  dimensiune = s;  pentru (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();  întoarce 0; }>>>  
Ieșire
 1 2 3 4 5>

Poate exista mai mult de un argument pentru șabloane?

Da, la fel ca parametrii normali, putem trece mai mult de un tip de date ca argumente șabloanelor. Următorul exemplu demonstrează același lucru.

Exemplu:

C++
// C++ Program to implement // Use of template #include  using namespace std; template clasa A { T x;  U y; public: A() { cout<< 'Constructor Called' << endl; } }; int main() {  AA;  A b;  întoarce 0; }>>>  
Ieșire Da, la fel ca parametrii normali, putem specifica argumente implicite pentru șabloane. Următorul exemplu demonstrează același lucru.

Exemplu:

C++
// C++ Program to implement // Use of template #include  using namespace std; template clasa A { public: T x;  U y;  A() { cout<< 'Constructor Called' << endl; } }; int main() {  // This will call A  AA;  întoarce 0; }>>>  
Ieșire Atât supraîncărcarea funcțiilor, cât și șabloanele sunt exemple de caracteristici de polimorfism ale OOP. Supraîncărcarea funcțiilor este utilizată atunci când funcțiile multiple fac operații destul de similare (nu identice), șabloanele sunt folosite când funcțiile multiple fac operații identice.

Ce se întâmplă când există un membru static într-o clasă/funcție șablon?

Fiecare instanță a unui șablon conține propria sa variabilă statică. Vedea Șabloane și variabile statice pentru mai multe detalii.

Ce este specializarea șablonului?

Specializarea șabloanelor ne permite să avem coduri diferite pentru un anumit tip de date. Vedea Specializare șablon pentru mai multe detalii.

Putem trece parametri non-tip șabloanelor?

Putem transmite argumente non-tip șabloanelor. Parametrii non-tip sunt utilizați în principal pentru specificarea valorilor maxime sau minime sau orice altă valoare constantă pentru o anumită instanță a unui șablon. Lucrul important de remarcat despre parametrii non-tip este că trebuie să fie const. Compilatorul trebuie să cunoască valoarea parametrilor non-tip în momentul compilării. Deoarece compilatorul trebuie să creeze funcții/clase pentru o valoare specificată non-tip în momentul compilării. În programul de mai jos, dacă înlocuim 10000 sau 25 cu o variabilă, obținem o eroare de compilator.

Exemplu:

python sort tuple
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;  pentru (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);    întoarce 0; }>>>  
Ieșire Iată un exemplu de program C++ pentru a afișa diferite tipuri de date folosind un constructor și un șablon. Vom efectua câteva acțiuni

  • transmiterea valorii caracterului prin crearea unui obiect în funcția main().
  • transmiterea valorii întregi prin crearea unui obiect în funcția main().
  • transmiterea valorii float prin crearea unui obiect în funcția main().

Exemplu:

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: // constructor de tip 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');  // transmiterea unei valori întregi prin crearea unei informații despre obiect q(22);  // transmiterea valorii float prin crearea unei informații despre obiectr(2,25);  întoarce 0; }>>>  
Ieșire Deducerea argumentului șablon deduce automat tipul de date al argumentului transmis șabloanelor de clasă sau funcție. Acest lucru ne permite să instanțiem șablonul fără a specifica în mod explicit tipul de date.

De exemplu, luați în considerare șablonul de funcție de mai jos pentru a înmulți două numere:

În general, atunci când dorim să folosim funcția multiplica() pentru numere întregi, trebuie să o numim astfel:

multiply (25, 5);>

Dar o putem numi și:

multiply(23, 5);>

Nu specificăm în mod explicit tipul, adică 1,3 sunt numere întregi.

Același lucru este valabil și pentru clasele șabloane (numai din C++17). Să presupunem că definim clasa șablonului ca:

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

Dacă vrem să creăm o instanță a acestei clase, putem folosi oricare dintre următoarele sintaxe:

replaceall în șir de caractere java
student stu1(23);    or  student stu2(24);>

Notă: Este important de reținut că deducerea argumentului șablon pentru clase este disponibilă numai din C++17, așa că dacă încercăm să folosim deducerea argumentului șablonului automat pentru o clasă din versiunea anterioară, va genera o eroare.

Exemplu de deducere a argumentului șablon

Exemplul de mai jos demonstrează modul în care șablonul de clasă vectorială STL deduce tipul de date fără a fi specificat în mod explicit.

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


Ieșire

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

Notă: Programul de mai sus nu va eșua compilarea în C++14 și compilatorul inferior, deoarece deducerea argumentelor șablonului de clasă a fost adăugată în C++17.

Argumente șablon de funcție Deducere

Deducerea argumentelor șablonului de funcție a făcut parte din C++ încă de la standardul C++98. Putem sări peste declararea tipului de argumente pe care dorim să le transmitem șablonului funcției, iar compilatorul va deduce automat tipul folosind argumentele pe care le-am transmis în apelul funcției.

Exemplu: În exemplul următor, demonstrăm cum funcțiile din C++ își deduc automat tipul de la sine.

C++
// C++ program to illustrate the function template argument // deduction #include  using namespace std; // defining function template template t multiplica(t primul, t al doilea) { return first * second; } // codul driver int main() { rezultat automat = multiplicare(10, 20);  std::cout<< 'Multiplication OF 10 and 20: ' << result  << std::endl;  return 0; }>

Ieșire
Multiplication OF 10 and 20: 200>

Notă: Pentru șabloanele de funcție care au același tip pentru argumente precum template void function(t a1, t a2){}, nu putem transmite argumente de diferite tipuri.

site-uri precum coomeet

Deducerea argumentelor șablonului de clasă (de la C++17 în continuare)

Deducerea argumentului șablonului de clasă a fost adăugată în C++17 și de atunci a făcut parte din limbaj. Ne permite să creăm instanțe de șablon de clasă fără a defini în mod explicit tipurile la fel ca șabloanele de funcție.

Exemplu: În exemplul următor, demonstrăm modul în care compilatorul clasează automat șabloanele în C++.

C++
// C++ Program to implement Class Template Arguments // Deduction #include  #include  #include  using namespace std; // Defining class template template class student { private: string student_name;  T total_marks; public: // Constructor parametrizat student(string n, T m): student_name(n) , total_marks(m) { } void getinfo() { // imprimarea detaliilor studentului<< '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; }>


Ieșire

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

Aici, i înseamnă int, iar d înseamnă dublu.

Pentru metaprogramarea șablonului, r consultați următorul articol - Metaprogramarea șablonului .

Ia o Test pe șabloane . Java acceptă și aceste caracteristici. Java îl numește generice .