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++
Pole s libovolným intervalem indexování v C++
1. října 2001, 00.00 | Předvedeme si jak vytvořit pole, jehož indexy nemusí být v intervalu 0 až N-1 jak jsme zvyklí, ale v libovolném zadaném intervalu. Např. od -10 do 20. V podstatě pole jaké známe např. z Pascalu. Vše, co je k práci s takovým polem nutné, je zde ke stažení.
Dnes si ukážeme jak vytvořit pole, jehož indexy nemusí být v intervalu 0 až N-1 jak jsme zvyklí, ale v libovolném programátorem zadaném intervalu. Například od -10 do +20. Tedy v podstatě pole jaké známe například z programovacího jazyka Pascal. Vše co je k práci s takovým polem potřeba je na konci tohoto článku k dispozici ke stažení.
Jak jsem již v minulém článku naznačoval, bude se jednat o šablonu. Ukážeme si vlastně na příkladu "větší" šablony jaké mají šablony v C++ nesmírné praktické využití. Všem, kteří nečetli mé předchozí 3 články o šablonách, a chtějí porozumět mému dnešnímu příkladu šablony, doporučuji si nejprve přečíst mé předchozí 3 články o šablonách.
Touto šablonou jsem se vlastně pokusil vytvořit něco jako datový kontejner z knihovny STL. Knihovnou STL se začneme zabývat od příštího článku. V STL je mnoho kontejnerů jako třeba zásobník, fronta, asociativní pole,"obyčejné" jednorozměrné pole, atd... Co ale v STL schází je právě takové pole, které se nyní budeme snažit vytvořit. Všechny kontejnery mají předepsané nějaké rozhraní (Veřejné metody a vnitřní veřejné typy.), které jsem se snažil dodržet. Existuje tedy mnoho metod, které jsou v příkladě podstatě jen z formality.
Vytváříme kontejnerŠablonu jsem nazval Array. Array je poměrně frekventované slovo v programovacích jazycích, přesto jsem nezjistil že by ve standardní knihovně C++ již bylo použito. Je ale možné, že jej používá nějaká jiná knihovna. Aby nedošlo ke konfliktu jmen, umístil jsem své pole do prostoru jmen, který jsem pojmenoval www_builder_cz. Bude se jednat o šablonu třídy. Parametrem šablony bude typ, který bude typem prvků v poli uložených. Interval indexů nebude parametrem šablony, protože by hranice intervalu musely být známy již v době kompilace, což se mi nezdá výhodné. Atributy třídy, která bude instancí šablony bude jednak ukazatel na první prvek "obyčejného" pole, které bude ve třídě zapouzdřeno. Bude obsahovat samotná data. Dále dva atributy, které budou udávat dolní hranici indexu a počet prvků v poli. Tyto dva atributy by měly stačit k výpočtu všech ostatních potřebných informací. Deklarace šablony třídy vypadá takto:
|
Ve veřejném rozhraní třídy je mnoho vnitřních typů. Všechny standardní kontejnery mají takto pojmenované typy, proto jsem je zde i já rozhodl takto pojmenovat. Nejprve bych chtěl upozornit na typ size_t, který jsem pojmenoval jako size_type a typ ptrdiff_t , který jsem pojmenoval jako difference_type. Oba typy jsou jen přejmenované primitivní datové typy. Přejmenování závisí na jednotlivých překladačích, ale ve 32-bitovém prostředí se jedná s největší pravděpodobností o typy usigned int a int. Dalším důležitým typem je iterator. Iterátorům se budeme věnovat v jednom samostatném článku. Iterátory se chovají podobně jako ukazatele, a v našem případě to dokonce ukazatel je. Těm, kteří se s pojmem iterátor setkali poprvé se omlouvám, že používám pojem, který jsem nevysvětlil. Prozatím budeme iterátor považovat za ukazatel, v některém ze svých následujících článcích tento pojem vysvětlím blíže. Dále následují konstruktory, operátor = a destruktor. Následují metody vytvářející (vracející) iterátory (ukazatele) na začátek bloku dat a za poslední prvek. Metody begin a end by měly mít všechny kontejnery. Následuje operátor [] a metoda at. Metoda at dělá to samé, co operátor []. Rozhodl jsem se jí vytvořit jen pro to, protože stejnou metodu (i stejně zbytečnou) má jiný kontejner - vector. Poté jsou deklarovány relační operátory, metoda swap pro výměnu obsahů dvou polí, a některé informační metody o parametrech kontejneru. Metoda size vrací počet prvků v kontejneru, metoda capacity vrací velikost paměti (v bytech), které zabírají prvky v kontejneru. Metoda empty oznamuje, zda kontejner je, či není prázdný. Dále následuje metoda max_size, která obvykle u kontejnerů vrací maximální možný počet prvků, které se do kontejneru dají přidat. Můj kontejner ale nedokáže měnit svou velikost. Schází zde metody insert a erase, které u jiných kontejneru jsou. Proto vlastně Array nemůže být považován za plnohodnotný kontejner. V mém kontejneru tedy metoda max_size dělá tu samou činnost jako size. Dále jsem přidal dvě metody getLower pro vrácení dolního indexu a getUpper pro vrácení horního indexu. Tolik k deklaraci. Podívejme se na implementaci některých vybraných metod. Vše, s podle mne podrobným komentářem, je ke stažení na konci článku.
|
První dvě metody ukazují, jak se naše pole kopíruje. Je dobré si všimnou práce s iterátory (ukazateli). Znovu připomínám, že begin vrací iterátor (ukazatel) na začátek pole, end vrací iterátor ZA poslední prvek v poli. Ještě bych chtěl upozornit na operátory < a >. Používají v sobě funkci lexicographical_compare. Jedná se o instanci jedné z mnoha standardních šablon funkcí. Jde o další věc, kterou předkládám bez vysvětlení, za což se omlouvám. Nejen standardním kontejnerům, iterátorům, ale i standardním funkcím se budeme v budoucnu věnovat podrobněji.
Důležité je upozornit, že typ, který bude parametrem šablony. Tedy typ prvků, které budou uloženy v poli, musí mít k dispozici bezparametrický konstruktor. Dále musíme vzít v úvahu, že bude pro proměnné (instance) tohoto typu používán operátor =. Proto nebude-li použitelný implicitní operátor, bude se muset přetížit. Dále, pokud budete chtít porovnávat dvě pole pomocí operátorů < ,nebo >, musejí být tyto operátory k dispozici i pro prvky v poli.
Nyní si ukažme několik příkladů jak naše pole použít ve svých programech. Velice jednoduchý příklad je:
|
Nyní se bez větších komentářů podíváme na příklad, kdy do našeho pole chceme vkládat instance nějaké vlastní třídy, ne proměnné primitivního datového typu.
|
A na závěr celá šablona array.h ke stažení. Měla by být univerzálně použitelná na všech překladačích podporujících alespoň trochu ANSI normu. Jak je asi zřejmé psaní šablon je poněkud náročnější, než psaní běžných tříd, nebo funkcí. Hlavně je velice obtížné je ladit, protože mnoho dnešních ladících nástrojů má s šablonami mnoho problémů. Na druhou stranu používání šablon je velice výhodné. Ideální stav je tedy takový, kdy nám někdo šablonu již napíše, a dodá nám ji již funkční a hotovou. My ji jenom používáme. Autoři jazyka C++ si toho byli vědomi, proto zahrnuli do standardu jazyka knihovnu STL (Standard Template Library). Tato knihovna nabízí k použití mnoho již vytvořených šablon jednak datových kontejnerů, a jednak algoritmů pro práci s nimi. STL knihovna je (měla by být) k dispozici u každého překladače C++. Od příštího článku se začneme knihovně STL věnovat.
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++
-
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