EN mal er et enkelt, men veldig kraftig verktøy i C++. Den enkle ideen er å sende datatypen som en parameter slik at vi ikke trenger å skrive den samme koden for forskjellige datatyper. For eksempel kan et programvareselskap trenge å sortere() for forskjellige datatyper. I stedet for å skrive og vedlikeholde flere koder, kan vi skrive en sort() og sende datatypen som en parameter.
C++ legger til to nye nøkkelord for å støtte maler: 'mal' og 'typenavn' . Det andre nøkkelordet kan alltid erstattes av nøkkelordet 'klasse' .
Hvordan fungerer maler?
Maler utvides på kompilatortid. Dette er som makroer. Forskjellen er at kompilatoren gjør typekontroll før malutvidelse. Ideen er enkel, kildekoden inneholder bare funksjon/klasse, men kompilert kode kan inneholde flere kopier av samme funksjon/klasse.
Funksjonsmaler
Vi skriver en generisk funksjon som kan brukes for ulike datatyper. Eksempler på funksjonsmaler er sort(), max(), min(), printArray().
For å vite mer om emnet se Generikk 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 malT myMax(T x, T y) { return (x> y) ? x: y; } int main() {// Ring 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; }>
Produksjon
7 7 g>
Eksempel: Implementering Boblesortering bruke maler 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; }>
Produksjon
Sorted array : 10 20 30 40 50>
Klasse maler
Klassemaler som funksjonsmaler, klassemaler er nyttige når en klasse definerer noe som er uavhengig av datatypen. Kan være nyttig for klasser som LinkedList, BinaryTree, Stack, Queue, Array, etc.
Eksempel:
C++ // C++ Program to implement // template Array class #include using namespace std; template klasse Array { privat: T* ptr; int størrelse; offentlig: Array(T arr[], int s); void print(); }; malArray::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(); returner 0; }>
Produksjon
1 2 3 4 5>
Kan det være mer enn ett argument for maler?
Ja, som vanlige parametere, kan vi sende mer enn én datatype som argumenter til maler. 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; returner 0; }>
Produksjon
Constructor Called Constructor Called>
Kan vi spesifisere en standardverdi for malargumenter?
Ja, som vanlige parametere, kan vi spesifisere standardargumenter til maler. 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; returner 0; }>
Produksjon
Constructor Called>
Hva er forskjellen mellom funksjonsoverbelastning og maler?
Både funksjonsoverbelastning og maler er eksempler på polymorfistrekk ved OOP. Funksjonsoverbelastning brukes når flere funksjoner utfører ganske like (ikke identiske) operasjoner, maler brukes når flere funksjoner utfører identiske operasjoner.
Hva skjer når det er et statisk medlem i en malklasse/funksjon?
Hver forekomst av en mal inneholder sin egen statiske variabel. Se Maler og statiske variabler for flere detaljer.
Hva er malspesialisering?
Malspesialisering lar oss ha forskjellige koder for en bestemt datatype. Se Malspesialisering for flere detaljer.
Kan vi overføre ikke-type parametere til maler?
Vi kan sende ikke-type argumenter til maler. Ikke-type parametere brukes hovedsakelig for å spesifisere maks eller min verdier eller en hvilken som helst annen konstant verdi for en bestemt forekomst av en mal. Det viktige å merke seg om ikke-type parametere er at de må være const. Kompilatoren må kjenne verdien av ikke-type parametere på kompileringstidspunktet. Fordi kompilatoren må lage funksjoner/klasser for en spesifisert ikke-typeverdi på kompileringstidspunktet. I programmet nedenfor, hvis vi erstatter 10000 eller 25 med en variabel, får vi en kompilatorfeil.
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 = maks; 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); returner 0; }>
Produksjon
10 1>
Her er et eksempel på et C++-program for å vise forskjellige datatyper ved hjelp av en konstruktør og mal. Vi vil utføre noen få handlinger
- sende tegnverdi ved å lage et objekt i hoved()-funksjonen.
- sende heltallsverdi ved å lage et objekt i main()-funksjonen.
- sende flyteverdi ved å lage et objekt i main()-funksjonen.
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 av typen mal 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'); // sende heltallsverdi ved å lage en objektinfo q(22); // sende flyteverdi ved å lage en objektinfor(2,25); returner 0; }>
Produksjon
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>
Mal Argumentfradrag
Malargumentdeduksjon trekker automatisk ut datatypen til argumentet som sendes til klasse- eller funksjonsmalene. Dette lar oss instansiere malen uten å spesifisere datatypen eksplisitt.
Tenk for eksempel på funksjonsmalen nedenfor for å multiplisere to tall:
template t multiply (t num1,t num2) { return num1*num2; }>
Generelt, når vi vil bruke multiply()-funksjonen for heltall, må vi kalle det slik:
multiply (25, 5);>
Men vi kan også kalle det:
multiply(23, 5);>
Vi spesifiserer ikke eksplisitt typen, dvs. 1,3 er heltall.
Det samme gjelder for malklassene (bare siden C++17). Anta at vi definerer malklassen som:
template class student{ private: t total_marks; public: student(t x) : total_marks(x) {} };>
Hvis vi vil lage en forekomst av denne klassen, kan vi bruke hvilken som helst av følgende syntaks:
student stu1(23); or student stu2(24);>
Merk: Det er viktig å merke seg at malargumentfradraget for klasser kun er tilgjengelig siden C++17, så hvis vi prøver å bruke automatisk malargumentdeduksjon for en klasse i tidligere versjon, vil det gi en feil.
Eksempel på malargumentfradrag
Eksemplet nedenfor viser hvordan STL-vektorklassemalen utleder datatypen uten å være eksplisitt spesifisert.
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 << ' '; } }>
Produksjon
Elements of v1 : 1.1 2 3.9 4.909 Elements of v2 : 1 2 3 4>
Merk: Programmet ovenfor vil mislykkes ved kompilering i C++14 og under kompilatoren siden klassemal argumenter fradrag ble lagt til i C++17.
ny linje python
Funksjon Mal Argument Fradrag
Funksjonsmal argumentdeduksjon har vært en del av C++ siden C++98-standarden. Vi kan hoppe over å deklarere typen argumenter vi ønsker å overføre til funksjonsmalen og kompilatoren vil automatisk utlede typen ved å bruke argumentene vi sendte i funksjonskallet.
Eksempel: I det følgende eksempelet viser vi hvordan funksjoner i C++ automatisk utleder typen av seg selv.
C++ // C++ program to illustrate the function template argument // deduction #include using namespace std; // defining function template template t multiplisere(t først, t sekund) { returner første * sekund; } // driverkode int main() { autoresultat = multipliser(10, 20); std::cout<< 'Multiplication OF 10 and 20: ' << result << std::endl; return 0; }>
Produksjon
Multiplication OF 10 and 20: 200>
Merk: For funksjonsmalene som har samme type for argumentene som mal void function(t a1, t a2){}, kan vi ikke sende argumenter av forskjellige typer.
Klassemalargumentfradrag (C++17 og utover)
Klassemalargumentdeduksjonen ble lagt til i C++17 og har siden vært en del av språket. Det lar oss lage klassemalforekomster uten eksplisitt definisjon av typene akkurat som funksjonsmaler.
Eksempel: I det følgende eksempelet viser vi hvordan kompilatoren automatisk klassifiserer maler i C++.
C++ // C++ Program to implement Class Template Arguments // Deduction #include #include #include using namespace std; // Defining class template template klasse elev { privat: string student_name; T totalt_merker; offentlig: // Parameterisert konstruktør student(streng n, T m) : student_name(n) , total_marks(m) { } void getinfo() { // skriver ut detaljene for studentcout<< '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; }>
Produksjon
STUDENT NAME: Vipul TOTAL MARKS: 100 Type ID: i STUDENT NAME: Yash TOTAL MARKS: 98.5 Type ID: d>
Her betyr i int, og d betyr dobbel.
For mal-metaprogrammering, r etter følgende artikkel – Mal Metaprogrammering .
Ta en Quiz om maler . Java støtter også disse funksjonene. Java kaller det generiske legemidler .