A sapluuna on yksinkertainen mutta erittäin tehokas työkalu C++:ssa. Yksinkertainen idea on välittää tietotyyppi parametrina, jotta meidän ei tarvitse kirjoittaa samaa koodia eri tietotyypeille. Esimerkiksi ohjelmistoyritys saattaa joutua lajittelemaan () eri tietotyyppejä varten. Useiden koodien kirjoittamisen ja ylläpitämisen sijaan voimme kirjoittaa yhden sort():n ja välittää tietotyypin parametrina.
C++ lisää kaksi uutta avainsanaa tukemaan malleja: 'sapluuna' ja 'tyyppinimi' . Toinen avainsana voidaan aina korvata avainsanalla 'luokka' .
Miten mallit toimivat?
Mallit laajennetaan kääntäjän aikana. Tämä on kuin makroja. Erona on, että kääntäjä tekee tyyppitarkistuksen ennen mallin laajentamista. Idea on yksinkertainen, lähdekoodi sisältää vain funktion/luokan, mutta käännetty koodi voi sisältää useita kopioita samasta funktiosta/luokasta.
Toimintomallit
Kirjoitamme geneerisen funktion, jota voidaan käyttää eri tietotyypeille. Esimerkkejä funktiomalleista ovat sort(), max(), min(), printArray().
Lisätietoja aiheesta saat osoitteesta Yleiset C++:ssa .
Esimerkki:
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 '>' on ylikuormitettu malliT myMax(T x, T y) { return (x> y) ? x : y; } int main() { // Kutsu myMax int coutille<< 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; }>
Lähtö
7 7 g>
Esimerkki: Toteutus Kuplalajittelu käyttämällä malleja C++:ssa
kolmas normaalimuotoC++
// 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; }>
Lähtö
Sorted array : 10 20 30 40 50>
Luokkamallit
Luokkamallit, kuten funktiomallit, luokkamallit ovat hyödyllisiä, kun luokka määrittelee jotain, joka on riippumaton tietotyypistä. Voi olla hyödyllinen luokissa, kuten LinkedList, BinaryTree, Stack, Queue, Array jne.
Esimerkki:
C++ // C++ Program to implement // template Array class #include using namespace std; template class Array { yksityinen: T* ptr; int koko; public: Array(T arr[], int s); void print(); }; sapluunaArray::Matriisi(T arr[], int s) { ptr = new T[s]; koko = s; for (int i = 0; i< size; i++) ptr[i] = arr[i]; } template tyhjä 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(); paluu 0; }>
Lähtö
1 2 3 4 5>
Voiko malleilla olla useampi kuin yksi argumentti?
Kyllä, kuten normaalit parametrit, voimme välittää useamman kuin yhden tietotyypin argumentteina malleihin. Seuraava esimerkki osoittaa saman.
Esimerkki:
C++ // C++ Program to implement // Use of template #include using namespace std; template luokka A { T x; U y; julkinen: A() { cout<< 'Constructor Called' << endl; } }; int main() { Aa; A b; paluu 0; }>
Lähtö
Constructor Called Constructor Called>
Voimmeko määrittää oletusarvon malliargumenteille?
Kyllä, kuten normaalit parametrit, voimme määrittää oletusargumentit malleille. Seuraava esimerkki osoittaa saman.
Esimerkki:
C++ // C++ Program to implement // Use of template #include using namespace std; template luokka A { julkinen: T x; U y; A() { cout<< 'Constructor Called' << endl; } }; int main() { // This will call A Aa; paluu 0; }>
Lähtö
Constructor Called>
Mitä eroa on toimintojen ylikuormituksen ja mallien välillä?
Sekä toimintojen ylikuormitus että mallit ovat esimerkkejä OOP:n polymorfismiominaisuuksista. Funktioiden ylikuormitusta käytetään, kun useat funktiot tekevät melko samanlaisia (ei identtisiä) operaatioita, malleja käytetään, kun useat funktiot tekevät identtisiä operaatioita.
Mitä tapahtuu, kun malliluokassa/funktiossa on staattinen jäsen?
Jokainen mallin esiintymä sisältää oman staattisen muuttujansa. Katso Mallit ja staattiset muuttujat Lisätietoja.
Mikä on mallien erikoistuminen?
Mallin erikoistumisen ansiosta voimme käyttää erilaisia koodeja tietylle tietotyypille. Katso Mallin erikoisala Lisätietoja.
Voimmeko välittää ei-tyyppisiä parametreja malleihin?
Voimme välittää ei-tyyppisiä argumentteja malleille. Ei-tyyppisiä parametreja käytetään pääasiassa enimmäis- tai minimiarvojen tai minkä tahansa muun vakioarvon määrittämiseen tietylle mallin esiintymälle. Tärkeä asia, joka on huomioitava ei-tyyppisissä parametreissa, on, että niiden on oltava vakio. Kääntäjän on tiedettävä ei-tyyppisten parametrien arvo käännöshetkellä. Koska kääntäjän on luotava funktioita/luokkia määritetylle ei-tyyppiarvolle käännöshetkellä. Alla olevassa ohjelmassa, jos korvaamme 10000 tai 25 muuttujalla, saamme kääntäjävirheen.
Esimerkki:
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; 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); paluu 0; }>
Lähtö
10 1>
Tässä on esimerkki C++-ohjelmasta, joka näyttää eri tietotyypit rakentajan ja mallin avulla. Suoritamme muutaman toiminnon
- merkin arvon välittäminen luomalla objekti main()-funktiossa.
- välitetään kokonaislukuarvo luomalla objekti main()-funktiossa.
- kelluvan arvon välittäminen luomalla objekti main()-funktiossa.
Esimerkki:
C++ // C++ program to show different data types using a // constructor and template. #include using namespace std; // defining a class template template luokan tiedot { julkinen: // rakentaja tyypin 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'); // välitetään kokonaislukuarvo luomalla objektitiedot q(22); // kelluvan arvon välittäminen luomalla objektitiedotr(2,25); paluu 0; }>
Lähtö
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>
Malli-argumentin vähennys
Malliargumentin päättely päättelee automaattisesti luokka- tai funktiomalleihin välitetyn argumentin tietotyypin. Tämän avulla voimme luoda mallin ilman tietotyyppiä.
Harkitse esimerkiksi alla olevaa funktiomallia kahden luvun kertomiseksi:
template t multiply (t num1,t num2) { return num1*num2; }>Yleensä, kun haluamme käyttää multiply()-funktiota kokonaisluvuille, meidän on kutsuttava sitä seuraavasti:
multiply (25, 5);>
Mutta voimme kutsua sitä myös:
multiply(23, 5);>
Emme nimenomaisesti määritä tyyppiä, eli 1,3 ovat kokonaislukuja.
Sama pätee malliluokkiin (vain C++17:stä lähtien). Oletetaan, että määrittelemme malliluokan seuraavasti:
template class student{ private: t total_marks; public: student(t x) : total_marks(x) {} };>Jos haluamme luoda esiintymän tästä luokasta, voimme käyttää mitä tahansa seuraavista syntakseista:
student stu1(23); or student stu2(24);>
Huomautus: On tärkeää huomata, että luokkien malliargumentin vähennys on saatavilla vain C++17:stä lähtien, joten jos yritämme käyttää automaattista malliargumentin vähennystä luokassa aiemmassa versiossa, se antaa virheen.
poista angular cli
Esimerkki malliargumentin vähennyksestä
Alla oleva esimerkki osoittaa, kuinka STL-vektoriluokkamalli päättelee tietotyypin ilman, että sitä on erikseen määritelty.
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 << ' '; } }>
Lähtö
Elements of v1 : 1.1 2 3.9 4.909 Elements of v2 : 1 2 3 4>
Huomautus: Yllä oleva ohjelma epäonnistuu kääntämisessä C++14:ssä ja alemmissa kääntäjissä, koska luokkamallipohjan argumenttien vähennys lisättiin C++17:ään.
Funktiomallin argumentit Vähennys
Funktiomallin argumenttien päättely on ollut osa C++:aa C++98-standardista lähtien. Voimme ohittaa funktiomalliin välitettävien argumenttien tyypin ilmoittamisen, ja kääntäjä päättelee tyypin automaattisesti käyttämällä argumentteja, jotka välitimme funktiokutsussa.
Esimerkki: Seuraavassa esimerkissä näytämme, kuinka C++:n funktiot päättelevät automaattisesti tyyppinsä itsestään.
C++ // C++ program to illustrate the function template argument // deduction #include using namespace std; // defining function template template t kertoa(t ensin, t toinen) { return ensimmäinen * toinen; } // ohjainkoodi int main() { auto tulos = kerro(10, 20); std::cout<< 'Multiplication OF 10 and 20: ' << result << std::endl; return 0; }>
Lähtö
Multiplication OF 10 and 20: 200>
Huomautus: Funktiomalleille, joilla on sama tyyppi argumenteille, kuten template void function(t a1, t a2){}, emme voi välittää erityyppisiä argumentteja.
Luokkamallin argumenttien vähennys (C++17 eteenpäin)
Luokkamallin argumenttipäätelmä lisättiin C++17:ään ja on siitä lähtien ollut osa kieltä. Sen avulla voimme luoda luokkamallin ilmentymiä ilman, että tyypit määritellään tarkasti, aivan kuten funktiomalleja.
Esimerkki: Seuraavassa esimerkissä näytämme, kuinka kääntäjä luokittelee automaattisesti C++:n luokkamalleja.
C++ // C++ Program to implement Class Template Arguments // Deduction #include #include #include using namespace std; // Defining class template template luokan opiskelija { yksityinen: merkkijono opiskelijan_nimi; T yhteensä_merkit; public: // Parametrisoitu konstruktori student(merkkijono n, T m) : opiskelijan_nimi(n) , yhteensä_merkit(m) { } void getinfo() { // opiskelijan tietojen tulostaminen<< '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; }>
Lähtö
STUDENT NAME: Vipul TOTAL MARKS: 100 Type ID: i STUDENT NAME: Yash TOTAL MARKS: 98.5 Type ID: d>
Tässä i tarkoittaa int:tä ja d tarkoittaa tuplaa.
Mallin metaohjelmointia varten r katso seuraava artikkeli - Mallin metaohjelmointi .
Ota a Tietovisa malleista . Java tukee myös näitä ominaisuuksia. Java kutsuu sitä geneeriset lääkkeet .
