Fotografický magazín "iZIN IDIF" každý týden ve Vašem e-mailu.
Co nového ve světě fotografie!
Zadejte Vaši e-mailovou adresu:
Kamarád fotí rád?
Přihlas ho k odběru fotomagazínu!
Zadejte e-mailovou adresu kamaráda:
C/C++
Šablony funkcí v C++
7. září 2001, 00.00 | V dnešním článku se podíváme na šablony funkcí. Vysvětlíme si k čemu šablony slouží, jak šablony deklarovat a jak je použít. Ukážeme si pro nás nové klíčové slovo template.
Co jsou to šablony funkcí a proč je používat? Šablona funkce je konstrukce, která umožňuje vytvořit funkci na základě parametrů. Proto se také vytváření a používání šablon někdy nazývá parametrické programování, a v souvislosti s šablonami se hovoří o parametrismu. Šablony nemusí být jen šablony funkcí, ale také šablony datových typů (struktur - struct, tříd - class, unií - union). O těch si povíme něco příště, dnešní článek bude věnován jen šablonám funkcí. Význam šablon se často a nejlépe demonstruje na příkladu funkce swap. Swap je funkce, která vymění ("přehodí") obsah dvou proměnných. Představme si situaci, kdy chceme mít možnost vyměnit hodnoty proměnných mnoha typů, nebo i instancí mnoha tříd. Bez použití šablon bychom museli napsat mnoho funkcí swap, které by se od sebe lišili jen typem parametrů. Lepší řešení je vytvořit jednu šablonu funkce swap, podle které se dle potřeby vytvoří požadovaná funkce na základě parametru, kterým bude typ. Syntaxe šablony funkce je:
|
Šablona funkce swap:
|
Parametrem šablony je typ T. Klíčové slovo class značí, že parametrem bude datový typ. Nemusí se jednat pouze o třídu, ale o jakýkoliv datový typ, i primitivní datový typ. Dále následuje funkce, swap. Tato funkce bude mít dva parametry, jenž budou referencí na typ T. V těle funkce vytvoříme dočasnou proměnnou c, která je typu T. Dále provedeme záměnu hodnot proměnných pomocí třetí proměnné. Konkrétní funkci pro konkrétní typ (instanci šablony) vytvoříme dosazením typu za parametr T. Překladač ještě v době překladu vytvoří funkcí swap, která bude mít tělo jako šablona, ale za T bude dosazen typ int. Příklad instanciace a použití šablony swap:
|
Podívejme se na řádek swap<int>(a,b);. V závorkách < > je parametr šablony. v závorkách ( ) jsou parametry funkce. Je-li parametr šablony zřejmý z volání funkce, nemusí se parametry šablony vůbec uvádět. V našem případě je z typu proměnných a a b jasné, že parametrem šablony je int, proto stačí dokonce napsat jen swap(a,b). Naše šablona může být použitá pro jakýkoliv typ. Jen je dobrá si všimnout, že ve funkci swap bude vytvořena kopie proměnné (objektu) a, a že bude použít operátor = pro přiřazení hodnot. Proto by typ, který bude parametrem naší šablony měl mít kopírovací konstruktor, pokud to bude nutné (viz můj článek Kopírovací konstruktor v C++), a také, pokud to bude nutné, přetížený operátor = (viz můj článek Přetěžování operátorů). Ukažme si nyní využití šablony funkce swap. Spolu s deklarací šablony swap vytvořme program:
|
Jak je vidět naše šablona funkce swap je použitelná pro mnoho typů. Je nutné upozornit, že v přeloženém programu šablona vlastně neexistuje. Existují v něm pouze instance šablony, které se vytvoří v době překladu. Nemusíme se tedy obávat nějakého zpomalení programu používáním šablon. Naopak šablony se mnohdy používají pro optimalizaci výsledného programu, protože mnoho činností přebírá překladač v době překladu, čímž může být výsledný program rychlejší. Šablony mohou někomu připomínat makra s parametry. Dalo by se skutečně říci, že šablony jsou vlastně lepší a "inteligentnější" makra.
Přetěžování šablon funkcíŠablony funkce lze přetěžovat stejně tak jako samotné funkce. Pokusíme se přetížit naší šablonu funkce swap. Další šablona bude šablona funkce zaměňující hodnoty prvků dvou stejně dlouhých polí:
|
Dalším parametrem šablony swap je celé číslo. Za tento parametr lze dosadit jen konstantu, nebo výraz, který lze vyhodnotit v době překladu. Společně s předchozí šablonou swap lze obě šablony použít například takto:
|
Priority volání
Vytvořme si do třetice obyčejnou funkci (Ne šablonu funkce!), která jako své parametry dostane ukazatele na první znak řetězce zakončeného znakem '\0'. Funkce přehodí samotné řetězce, ne pouze ukazatele na ně. Takto napsaná funkce je použitelné pouze pro řetězce stejné délky.
|
Nyní společně se šablonami swap vytvořme jednoduchou funkci main:
|
Po spuštění programu se můžeme podle výpisu přesvědčit, že funkce swap budou skutečně volány tak, jak jsem uvedl v poznámkách. Pro dva řetězce nebude vytvořena instance šablony, a přeloženo její volání, ale bude přeloženo volání funkce swap(char *a, char *b). Priorita volání funkcí by šla shrnout do následujících pravidel:
Explicitní a implicitní vytváření instancí šablon.
Existují dva způsoby jak vytvářet instance šablon. První je implicitní vytvoření instance. Znamená to, že překladač vytvoří instanci a přeloží ji jen tehdy, jestliže ji potřebuje. Všechny instance šablony swap v předchozích příkladech jsou vytvořeny implicitně. Další možnost jak vytvořit instanci šablony explicitně. Budeme-li chtít, aby překladač vytvořil instanci šablony swap pro parametr float, i když nebude v daném modulu požadována, napíšeme:
|
Tolik tedy k šablonám funkcí. Příště se podíváme na šablony datových typů. Na jednoduché příkladu si vytvoříme šablonu třídy. Instance šablony třídy je třída. Také se podíváme na další, pro nás nové, klíčové slovo typename.
Obsah seriálu (více o seriálu):
- Základy OOP v C++: Od C k C++
- Základní pojmy objektově orientovaného programování
- Vytváření tříd, instance třídy, zasílání zpráv v C++
- Vytváření instancí - konstruktory, destruktory
- Kopírovací konstruktor v C++
- Jednoduchá dědičnost v C++
- Časná versus pozdní vazba - úvod do polymorfismu v C++
- Polymorfismus - dokončení
- Vícenásobná dědičnost v C++
- Vícenásobná dědičnost v C++ - opakovaná dědičnost
- Vícenásobná dědičnost v C++ - volání konstruktorů a destruktorů
- Přetěžování operátorů v C++ 1.díl
- Přetěžování operátorů v C++ 2. díl
- Vstupní a výstupní operace pomocí datových proudů v C++
- Přetěžování operátorů << a >> pro datové proudy v C++
- Neformátovaný vstup a výstup v C++
- Paměťové proudy v C++
- Prostory jmen v C++
- Řetězce v C++
- Výjimky v C++
- Výjimky v C++ - výjimky tvoří dědičnou hierarchii
- Výjimky v C++ - dokončení
- Dynamická identifikace typů v C++
- Přetypování v C++
- Problémy s typy při vícenásobné dědičnosti
- Šablony funkcí v C++
- Šablony datových typů v C++
- Vnitřní typy u parametrů šablon, vnořené šablony v C++
- Pole s libovolným intervalem indexování v C++
- Datové kontejnery v C++ - Úvod do STL
- Vector - datový kontejner v C++
- Iterátory v C++
- Šablona vector v C++ a iterátory
- Asociativní pole v C++
- Množina v C++
- Funkční objekty v C++
- Standardní funkční objekty v C++
- Úvod do standardních algoritmů v C++
- Kopírovací a přesouvací algoritmy v C++
- Vyhledávací algoritmy v C++
- Skenovací (prohlížecí) algoritmy v C++
- Transformační algoritmy v C++
- Řadící algoritmy v C++
- Halda v C++
- Standardní algoritmy v C++ - dokončení
- Automatické ukazatele v C++
- Inteligentní ukazatel - čítač referencí v C++
- Použití čítače referencí v C++
- Kopírování velkých objektů v C++
- Řízené kopírování prvků v poli v C++
- Dokončení seriálu objektově orientované programování v C++
Diskuse k článku
-
25. listopadu 2012
-
30. srpna 2002
-
10. října 2002
-
4. listopadu 2002
-
12. září 2002
-
25. listopadu 2012
-
28. července 1998
-
31. července 1998
-
28. srpna 1998
-
6. prosince 2000
-
27. prosince 2007
-
4. května 2007