A plantilla és una eina senzilla però molt potent en C++. La idea senzilla és passar el tipus de dades com a paràmetre de manera que no calgui escriure el mateix codi per a diferents tipus de dades. Per exemple, una empresa de programari pot necessitar ordenar () per a diferents tipus de dades. En lloc d'escriure i mantenir diversos codis, podem escriure un sort() i passar el tipus de dades com a paràmetre.
C++ afegeix dues paraules clau noves per donar suport a les plantilles: 'plantilla' i 'typename' . La segona paraula clau sempre es pot substituir per la paraula clau 'classe' .
Com funcionen les plantilles?
Les plantilles s'amplien en el moment del compilador. Això és com les macros. La diferència és que el compilador fa la comprovació de tipus abans de l'expansió de la plantilla. La idea és senzilla, el codi font només conté funció/classe, però el codi compilat pot contenir diverses còpies de la mateixa funció/classe.
Plantilles de funcions
Escrivim una funció genèrica que es pot utilitzar per a diferents tipus de dades. Exemples de plantilles de funcions són sort(), max(), min(), printArray().
Per saber més sobre el tema consulta Genèrics en C++ .
Exemple:
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 '>' és una plantilla sobrecarregadaT myMax(T x, T y) { retorn (x> y) ? x : y; } int main() { // Truqueu a myMax per a 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; }>
Sortida
7 7 g>
Exemple: Implementació Classificació de bombolles utilitzant plantilles en C++
centrant imatges en cssC++
// 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) { per a (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; }>
Sortida
Sorted array : 10 20 30 40 50>
Plantilles de classe
Les plantilles de classe com les plantilles de funcions, les plantilles de classe són útils quan una classe defineix quelcom que és independent del tipus de dades. Pot ser útil per a classes com LinkedList, BinaryTree, Stack, Queue, Array, etc.
Exemple:
C++ // C++ Program to implement // template Array class #include using namespace std; template class Array { privat: T* ptr; int mida; public: Array(T arr[], int s); void print(); }; plantillaMatriu::Array(T arr[], int s) { ptr = new T[s]; mida = s; per (int i = 0; i< size; i++) ptr[i] = arr[i]; } template void Array::print() { per (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(); retorn 0; }>>>
Sortida 1 2 3 4 5>
Hi pot haver més d'un argument per a les plantilles?
Sí, com els paràmetres normals, podem passar més d'un tipus de dades com a arguments a les plantilles. L'exemple següent demostra el mateix.
Exemple:
C++ // C++ Program to implement // Use of template #include using namespace std; template classe A { T x; U y; públic: A() { cout<< 'Constructor Called' << endl; } }; int main() { Aa; A b; retorn 0; }>>>
Sortida Sí, com els paràmetres normals, podem especificar arguments per defecte a les plantilles. L'exemple següent demostra el mateix. Exemple:
C++ // C++ Program to implement // Use of template #include using namespace std; template classe A { públic: T x; U y; A() { cout<< 'Constructor Called' << endl; } }; int main() { // This will call A Aa; retorn 0; }>>>
Sortida Tant la sobrecàrrega de funcions com les plantilles són exemples de característiques de polimorfisme de la POO. La sobrecàrrega de funcions s'utilitza quan diverses funcions fan operacions força similars (no idèntiques), les plantilles s'utilitzen quan diverses funcions fan operacions idèntiques. Què passa quan hi ha un membre estàtic en una classe/funció de plantilla?
Cada instància d'una plantilla conté la seva pròpia variable estàtica. Vegeu Plantilles i variables estàtiques per a més detalls.
Què és l'especialització de plantilles?
L'especialització de plantilles ens permet tenir codis diferents per a un tipus de dades concret. Vegeu Especialització de plantilla per a més detalls.
Podem passar paràmetres no tipus a les plantilles?
Podem passar arguments no tipus a les plantilles. Els paràmetres no tipus s'utilitzen principalment per especificar valors màxims o mínims o qualsevol altre valor constant per a una instància concreta d'una plantilla. L'important a tenir en compte sobre els paràmetres no tipus és que han de ser const. El compilador ha de conèixer el valor dels paràmetres no tipus en temps de compilació. Com que el compilador ha de crear funcions/classes per a un valor no tipus especificat en temps de compilació. Al programa següent, si substituïm 10000 o 25 per una variable, obtenim un error del compilador.
Exemple:
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 = màx; per (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); retorn 0; }>>>
Sortida Aquí teniu un exemple de programa C++ per mostrar diferents tipus de dades mitjançant un constructor i una plantilla. Farem unes quantes accions - passant el valor del caràcter mitjançant la creació d'un objecte a la funció main().
- passant un valor enter mitjançant la creació d'un objecte a la funció main().
- passant el valor flotant mitjançant la creació d'un objecte a la funció main().
Exemple:
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 tipus template info(TA) { 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'); // passant un valor enter mitjançant la creació d'una informació d'objecte q(22); // passant el valor flotant mitjançant la creació d'una informació d'objecter(2,25); retorn 0; }>>>
Sortida La deducció d'arguments de plantilla dedueix automàticament el tipus de dades de l'argument passat a les plantilles de classe o funció. Això ens permet crear una instancia de la plantilla sense especificar explícitament el tipus de dades.
Per exemple, considereu la plantilla de funció següent per multiplicar dos nombres:
En general, quan volem utilitzar la funció multiplicar () per a nombres enters, l'hem d'anomenar així: multiply (25, 5);>
Però també podem dir-ho:
multiply(23, 5);>
No especifiquem explícitament el tipus, és a dir, 1,3 són nombres enters.
El mateix passa amb les classes de plantilla (només des de C++17). Suposem que definim la classe de plantilla com:
template class student{ private: t total_marks; public: student(t x) : total_marks(x) {} };>
Si volem crear una instància d'aquesta classe, podem utilitzar qualsevol de les sintaxis següents:
student stu1(23); or student stu2(24);>
Nota: És important tenir en compte que la deducció d'arguments de plantilla per a classes només està disponible des de C++17, de manera que si intentem utilitzar la deducció automàtica d'arguments de plantilla per a una classe de la versió anterior, es produirà un error.
array slicing java
Exemple de deducció d'arguments de plantilla
L'exemple següent mostra com la plantilla de classe vectorial STL dedueix el tipus de dades sense especificar-se explícitament.
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 << ' '; } }>
Sortida
Elements of v1 : 1.1 2 3.9 4.909 Elements of v2 : 1 2 3 4>
Nota: El programa anterior fallarà en la compilació en C++14 i en el compilador inferior, ja que la deducció d'arguments de plantilla de classe es va afegir a C++17.
Arguments de plantilla de funció Deducció
La deducció d'arguments de plantilla de funció forma part de C++ des de l'estàndard C++98. Podem ometre declarar el tipus d'arguments que volem passar a la plantilla de funció i el compilador deduirà automàticament el tipus utilitzant els arguments que hem passat a la trucada de funció.
Exemple: A l'exemple següent, demostrem com les funcions en C++ dedueixen automàticament el seu tipus per si mateixes.
C++ // C++ program to illustrate the function template argument // deduction #include using namespace std; // defining function template template t multiplica (t primer, t segon) { retorn primer * segon; } // codi del controlador int main() { resultat automàtic = multiplicar (10, 20); std::cout<< 'Multiplication OF 10 and 20: ' << result << std::endl; return 0; }>
Sortida Multiplication OF 10 and 20: 200>
Nota: Per a les plantilles de funcions que tenen el mateix tipus per als arguments com la plantilla void function(t a1, t a2){}, no podem passar arguments de diferents tipus.
Deducció d'arguments de plantilla de classe (a partir de C++17)
La deducció de l'argument de la plantilla de classe es va afegir a C++17 i des de llavors forma part del llenguatge. Ens permet crear les instàncies de la plantilla de classe sense definir explícitament els tipus com les plantilles de funció.
Exemple: A l'exemple següent, demostrem com el compilador classe automàticament les plantilles en 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 parametritzat student(string n, T m): student_name(n) , total_marks(m) { } void getinfo() { // imprimint els detalls del cost de l'estudiant<< '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; }>
Sortida
STUDENT NAME: Vipul TOTAL MARKS: 100 Type ID: i STUDENT NAME: Yash TOTAL MARKS: 98.5 Type ID: d>
Aquí, i significa int i d significa doble.
Per a la metaprogramació de plantilles, r consulteu l'article següent - Metaprogramació de plantilles .
Preneu a Test sobre plantilles . Java també admet aquestes funcions. Java l'anomena genèrics .