A šablona je jednoduchý, ale velmi výkonný nástroj v C++. Jednoduchá myšlenka je předat datový typ jako parametr, abychom nemuseli psát stejný kód pro různé datové typy. Softwarová společnost může například potřebovat třídit() pro různé typy dat. Spíše než psát a udržovat více kódů můžeme napsat jeden sort() a předat datový typ jako parametr.
c náhodné číslo
C++ přidává dvě nová klíčová slova pro podporu šablon: 'šablona' a ‘název typu’ . Druhé klíčové slovo lze vždy nahradit klíčovým slovem 'třída' .
Jak fungují šablony?
Šablony jsou rozbaleny v době kompilátoru. To je jako makra. Rozdíl je v tom, že kompilátor provádí kontrolu typu před rozšířením šablony. Myšlenka je jednoduchá, zdrojový kód obsahuje pouze funkci/třídu, ale zkompilovaný kód může obsahovat více kopií stejné funkce/třídy.
Šablony funkcí
Píšeme generickou funkci, kterou lze použít pro různé datové typy. Příklady šablon funkcí jsou sort(), max(), min(), printArray().
Chcete-li se dozvědět více o tématu, viz Generika v C++ .
Příklad:
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 '>' je přetížená šablonaT myMax(T x, T y) { return (x> y) ? x : y; } int main() { // Volání myMax pro 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; }>
Výstup
7 7 g>
Příklad: Provádění Bublinové řazení pomocí šablon v 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; }>
Výstup
Sorted array : 10 20 30 40 50>
Šablony tříd
Šablony tříd, jako jsou šablony funkcí, šablony tříd, jsou užitečné, když třída definuje něco, co je nezávislé na datovém typu. Může být užitečné pro třídy jako LinkedList, BinaryTree, Stack, Queue, Array atd.
Příklad:
C++ // C++ Program to implement // template Array class #include using namespace std; template class Array { private: T* ptr; int velikost; public: Array(T arr[], int s); void print(); }; šablonaPole::Array(T arr[], int s) { ptr = new T[s]; velikost = 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(); návrat 0; }>
Výstup
1 2 3 4 5>
Může existovat více než jeden argument pro šablony?
Ano, stejně jako normální parametry můžeme šablonám předat více než jeden datový typ jako argumenty. Následující příklad ukazuje totéž.
Příklad:
C++ // C++ Program to implement // Use of template #include using namespace std; template třída A { T x; U y; public: A() { cout<< 'Constructor Called' << endl; } }; int main() { AA; A b; návrat 0; }>
Výstup
Constructor Called Constructor Called>
Můžeme zadat výchozí hodnotu pro argumenty šablony?
Ano, jako normální parametry můžeme šablonám zadat výchozí argumenty. Následující příklad ukazuje totéž.
Příklad:
C++ // C++ Program to implement // Use of template #include using namespace std; template třída A { public: T x; U y; A() { cout<< 'Constructor Called' << endl; } }; int main() { // This will call A AA; návrat 0; }>
Výstup
Constructor Called>
Jaký je rozdíl mezi přetížením funkcí a šablonami?
Jak přetížení funkcí, tak šablony jsou příklady vlastností polymorfismu OOP. Přetížení funkcí se používá, když více funkcí provádí velmi podobné (ne identické) operace, šablony se používají, když více funkcí provádí stejné operace.
Co se stane, když je ve třídě/funkci šablony statický člen?
Každá instance šablony obsahuje svou vlastní statickou proměnnou. Vidět Šablony a statické proměnné Více podrobností.
Co je specializace šablon?
Specializace na šablony nám umožňuje mít různé kódy pro konkrétní datový typ. Vidět Specializace na šablony Více podrobností.
návratové pole java
Můžeme šablonám předávat netypové parametry?
Netypové argumenty můžeme předat šablonám. Netypové parametry se používají hlavně k určení maximálních nebo minimálních hodnot nebo jakékoli jiné konstantní hodnoty pro konkrétní instanci šablony. U netypových parametrů je důležité poznamenat, že musí být konst. Kompilátor musí znát hodnotu netypových parametrů v době kompilace. Protože kompilátor potřebuje vytvořit funkce/třídy pro zadanou netypovou hodnotu v době kompilace. Pokud v níže uvedeném programu nahradíme 10000 nebo 25 proměnnou, dostaneme chybu kompilátoru.
Příklad:
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); návrat 0; }>
Výstup
10 1>
Zde je příklad programu C++ pro zobrazení různých datových typů pomocí konstruktoru a šablony. Provedeme několik akcí
- předávání znakové hodnoty vytvořením objektu ve funkci main().
- předávání celočíselné hodnoty vytvořením objektu ve funkci main().
- předání hodnoty float vytvořením objektu ve funkci main().
Příklad:
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: // konstruktor typu 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'); // předání celočíselné hodnoty vytvořením informace o objektu q(22); // předání hodnoty float vytvořením informace o objektur(2,25); návrat 0; }>
Výstup
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>
Odpočet argumentu šablony
Odvod argumentu šablony automaticky odvodí datový typ argumentu předaného šablonám třídy nebo funkce. To nám umožňuje vytvořit instanci šablony bez explicitního zadání datového typu.
Zvažte například níže uvedenou šablonu funkce pro násobení dvou čísel:
template t multiply (t num1,t num2) { return num1*num2; }>
Obecně, když chceme použít funkci multiply() pro celá čísla, musíme ji nazvat takto:
pole.z javy
multiply (25, 5);>
Můžeme to ale také nazvat:
multiply(23, 5);>
Typ explicitně nespecifikujeme, tj. 1,3 jsou celá čísla.
Totéž platí pro třídy šablon (pouze od C++ 17). Předpokládejme, že definujeme třídu šablony jako:
template class student{ private: t total_marks; public: student(t x) : total_marks(x) {} };>
Pokud chceme vytvořit instanci této třídy, můžeme použít kteroukoli z následujících syntaxí:
student stu1(23); or student stu2(24);>
Poznámka: Je důležité poznamenat, že dedukce argumentů šablony pro třídy je k dispozici pouze od C++17, takže pokud se pokusíme použít automatickou dedukci argumentu šablony pro třídu v předchozí verzi, vyvolá to chybu.
Příklad dedukce argumentu šablony
Níže uvedený příklad ukazuje, jak šablona vektorové třídy STL dedukuje datový typ, aniž by byl explicitně specifikován.
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 << ' '; } }>
Výstup
Elements of v1 : 1.1 2 3.9 4.909 Elements of v2 : 1 2 3 4>
Poznámka: Výše uvedený program selže při kompilaci v kompilátoru C++14 a nižším, protože v C++17 byl přidán odpočet argumentů šablony třídy.
Odpočet argumentů šablony funkce
Dedukce argumentů šablony funkcí je součástí C++ od standardu C++98. Můžeme přeskočit deklarování typu argumentů, které chceme předat šabloně funkce, a kompilátor automaticky odvodí typ pomocí argumentů, které jsme předali při volání funkce.
abstraktní třída
Příklad: V následujícím příkladu si ukážeme, jak funkce v C++ samy automaticky odvodí svůj typ.
C++ // C++ program to illustrate the function template argument // deduction #include using namespace std; // defining function template template t multiply(t first, t second) { return first * second; } // kód ovladače int main() { automatický výsledek = multiply(10, 20); std::cout<< 'Multiplication OF 10 and 20: ' << result << std::endl; return 0; }>
Výstup
Multiplication OF 10 and 20: 200>
Poznámka: U šablon funkcí, které mají stejný typ pro argumenty, jako je template void function(t a1, t a2){}, nemůžeme předat argumenty různých typů.
Odpočet argumentů šablony třídy (C++17 a novější)
Odvod argumentů šablony třídy byl přidán v C++17 a od té doby je součástí jazyka. Umožňuje nám vytvářet instance šablon třídy bez explicitní definice typů, stejně jako šablony funkcí.
Příklad: V následujícím příkladu si ukážeme, jak kompilátor automaticky třídí šablony v C++.
import skeneru javaC++
// C++ Program to implement Class Template Arguments // Deduction #include #include #include using namespace std; // Defining class template template třída student { private: string jméno_studenta; T total_marks; public: // Parametrizovaný konstruktor student(string n, T m) : student_name(n) , total_marks(m) { } void getinfo() { // tisk podrobností o studentovi 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; }>
Výstup
STUDENT NAME: Vipul TOTAL MARKS: 100 Type ID: i STUDENT NAME: Yash TOTAL MARKS: 98.5 Type ID: d>
Zde i znamená int a d znamená double.
Pro šablonové metaprogramování, r viz následující článek - Metaprogramování šablon .
Vezměte a Kvíz o šablonách . Java také podporuje tyto funkce. Java to nazývá generika .