UN modello è uno strumento semplice ma molto potente in C++. L'idea semplice è passare il tipo di dati come parametro in modo da non dover scrivere lo stesso codice per tipi di dati diversi. Ad esempio, una società di software potrebbe aver bisogno di sort() per diversi tipi di dati. Invece di scrivere e mantenere più codici, possiamo scrivere un sort() e passare il tipo di dati come parametro.
C++ aggiunge due nuove parole chiave per supportare i modelli: 'modello' E 'nometipo' . La seconda parola chiave può sempre essere sostituita dalla parola chiave 'classe' .
Come funzionano i modelli?
I modelli vengono espansi in fase di compilazione. Questo è come i macro. La differenza è che il compilatore esegue il controllo del tipo prima dell'espansione del modello. L'idea è semplice, il codice sorgente contiene solo funzione/classe, ma il codice compilato può contenere più copie della stessa funzione/classe.
Modelli di funzioni
Scriviamo una funzione generica che può essere utilizzata per diversi tipi di dati. Esempi di modelli di funzione sono sort(), max(), min(), printArray().
Per saperne di più sull'argomento fare riferimento a Generici in C++ .
Esempio:
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 '>' è un modello sovraccaricoT mioMax(T x, T y) { return (x> y) ? x:y; } int main() { // Chiama myMax per 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; }>
Produzione
7 7 g>
Esempio: Implementazione Ordinamento a bolle utilizzando modelli in 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 (UN); cout<< ' Sorted array : '; for (int i = 0; i < n; i++) cout << a[i] << ' '; cout << endl; return 0; }>
Produzione
Sorted array : 10 20 30 40 50>
Modelli di classe
I modelli di classe come i modelli di funzione, i modelli di classe sono utili quando una classe definisce qualcosa che è indipendente dal tipo di dati. Può essere utile per classi come LinkedList, BinaryTree, Stack, Queue, Array, ecc.
Esempio:
C++ // C++ Program to implement // template Array class #include using namespace std; template class Array { privato: T* ptr; dimensione intera; pubblico: Array(T arr[], int s); stampa nulla(); }; modelloVettore::Array(T arr[], int s) { ptr = new T[s]; taglia = s; for (int i = 0; i< size; i++) ptr[i] = arr[i]; } template matrice vuota::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(); restituire 0; }>
Produzione
1 2 3 4 5>
Può esserci più di un argomento per i modelli?
Sì, come i normali parametri, possiamo passare più di un tipo di dati come argomenti ai template. L'esempio seguente dimostra lo stesso.
Esempio:
migliorato per il loop JavaC++
// C++ Program to implement // Use of template #include using namespace std; template classe A {Tx; Sì; pubblico: A() { cout<< 'Constructor Called' << endl; } }; int main() { AUN; UN B; restituire 0; }>
Produzione
Constructor Called Constructor Called>
Possiamo specificare un valore predefinito per gli argomenti del modello?
Sì, come i parametri normali, possiamo specificare argomenti predefiniti nei modelli. L'esempio seguente dimostra lo stesso.
Esempio:
C++ // C++ Program to implement // Use of template #include using namespace std; template classe A { pubblico: T x; Sì; A() { cout<< 'Constructor Called' << endl; } }; int main() { // This will call A AUN; restituire 0; }>
Produzione
Constructor Called>
Qual è la differenza tra sovraccarico delle funzioni e modelli?
Sia il sovraccarico delle funzioni che i modelli sono esempi di caratteristiche di polimorfismo dell'OOP. L'overloading delle funzioni viene utilizzato quando più funzioni eseguono operazioni abbastanza simili (non identiche), i modelli vengono utilizzati quando più funzioni eseguono operazioni identiche.
Cosa succede quando è presente un membro statico in una classe/funzione modello?
Ogni istanza di un modello contiene la propria variabile statica. Vedere Modelli e variabili statiche per ulteriori dettagli.
Cos'è la specializzazione dei modelli?
La specializzazione del modello ci consente di avere codici diversi per un particolare tipo di dati. Vedere Specializzazione dei modelli per ulteriori dettagli.
Possiamo passare parametri non di tipo ai template?
Possiamo passare argomenti non di tipo ai template. I parametri non di tipo vengono utilizzati principalmente per specificare valori massimi o minimi o qualsiasi altro valore costante per una particolare istanza di un modello. La cosa importante da notare sui parametri non di tipo è che devono essere const. Il compilatore deve conoscere il valore dei parametri non di tipo in fase di compilazione. Perché il compilatore deve creare funzioni/classi per un valore non di tipo specificato in fase di compilazione. Nel programma seguente, se sostituiamo 10000 o 25 con una variabile, otteniamo un errore del compilatore.
Esempio:
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 = massimo; 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); restituire 0; }>
Produzione
10 1>
Ecco un esempio di un programma C++ per mostrare diversi tipi di dati utilizzando un costruttore e un modello. Eseguiremo alcune azioni
- passando il valore del carattere creando un oggetto nella funzione main().
- passando un valore intero creando un oggetto nella funzione main().
- passando il valore float creando un oggetto nella funzione main().
Esempio:
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: // costruttore del tipo 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'); // passando un valore intero creando un oggetto info q(22); // passando il valore float creando un oggetto infor(2,25); restituire 0; }>
Produzione
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>
Detrazione dell'argomento modello
La deduzione dell'argomento del modello deduce automaticamente il tipo di dati dell'argomento passato ai modelli di classe o di funzione. Ciò ci consente di istanziare il modello senza specificare esplicitamente il tipo di dati.
Ad esempio, considera il modello di funzione seguente per moltiplicare due numeri:
template t multiply (t num1,t num2) { return num1*num2; }>
In generale, quando vogliamo usare la funzione multiply() per gli interi, dobbiamo chiamarla così:
multiply (25, 5);>
Ma possiamo anche chiamarlo:
multiply(23, 5);>
Non specifichiamo esplicitamente il tipo, ad esempio 1,3 sono numeri interi.
Lo stesso vale per le classi modello (solo a partire da C++ 17). Supponiamo di definire la classe template come:
template class student{ private: t total_marks; public: student(t x) : total_marks(x) {} };>
Se vogliamo creare un'istanza di questa classe, possiamo utilizzare una qualsiasi delle seguenti sintassi:
student stu1(23); or student stu2(24);>
Nota: È importante notare che la detrazione dell'argomento del modello per le classi è disponibile solo a partire da C++17, quindi se proviamo a utilizzare la deduzione automatica dell'argomento del modello per una classe nella versione precedente, verrà generato un errore.
Esempio di detrazione dell'argomento modello
L'esempio seguente dimostra come il modello di classe vettoriale STL deduce il tipo di dati senza essere specificato esplicitamente.
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 << ' '; } }>
Produzione
Elements of v1 : 1.1 2 3.9 4.909 Elements of v2 : 1 2 3 4>
Nota: Il programma precedente non riuscirà nella compilazione nel compilatore C++14 e nelle versioni precedenti poiché la detrazione degli argomenti del modello di classe è stata aggiunta in C++17.
Detrazione degli argomenti del modello di funzione
La deduzione degli argomenti del modello di funzione fa parte del C++ a partire dallo standard C++98. Possiamo saltare la dichiarazione del tipo di argomenti che vogliamo passare al modello di funzione e il compilatore dedurrà automaticamente il tipo utilizzando gli argomenti passati nella chiamata alla funzione.
Esempio: Nell'esempio seguente viene dimostrato come le funzioni in C++ deducano automaticamente da sole il proprio tipo.
C++ // C++ program to illustrate the function template argument // deduction #include using namespace std; // defining function template template t moltiplica(t primo, t secondo) { return primo * secondo; } // codice driver int main() { risultato automatico = moltiplicare (10, 20); std::cout<< 'Multiplication OF 10 and 20: ' << result << std::endl; return 0; }>
Produzione
Multiplication OF 10 and 20: 200>
Nota: Per i modelli di funzione che hanno lo stesso tipo per argomenti come template void function(t a1, t a2){}, non possiamo passare argomenti di tipi diversi.
Detrazione degli argomenti del modello di classe (da C++ 17 in poi)
La deduzione dell'argomento del modello di classe è stata aggiunta in C++17 e da allora fa parte del linguaggio. Ci consente di creare istanze di modelli di classe senza definire esplicitamente i tipi proprio come i modelli di funzioni.
Esempio: Nell'esempio seguente viene dimostrato come il compilatore classifica automaticamente i modelli in C++.
C++ // C++ Program to implement Class Template Arguments // Deduction #include #include #include using namespace std; // Defining class template template studente di classe { privato: string nome_studente; T voti_totali; public: // Costruttore parametrizzato student(string n, T m) : student_name(n) , total_marks(m) { } void getinfo() { // stampa i dettagli dello studente 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; }>
Produzione
STUDENT NAME: Vipul TOTAL MARKS: 100 Type ID: i STUDENT NAME: Yash TOTAL MARKS: 98.5 Type ID: d>
Qui i significa int e d significa double.
Per la metaprogrammazione dei template, r fare riferimento al seguente articolo – Metaprogrammazione dei modelli .
Prendi un Quiz sui modelli . Anche Java supporta queste funzionalità. Java lo chiama generici .