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++
Přetěžování operátorů << a >> pro datové proudy v C++
13. dubna 2001, 00.00 | Dnes si ukážeme jak přetížit operátory << a >> pro výstup a vstup do datových proudů. Také si řekneme něco o práci s textovými soubory pomocí datových proudů.
Přetěžování operátorů << a >> pro datové proudy v C++V minulém článku jsme si něco málo ukázali jak pracovat s datovými proudy a něco o objektech cin ,cout, cerr. Dnes si ukážeme jak poslat do (resp. přijmout z) datového proudu nejen primitivní datový typ, ale také instanci nějaké třídy. Také si ukážeme jak používat další stream - fstream, tedy datový proud, jehož "cílem" je soubor.
Jak posílat do datových proudů vlastní objekty?Jedná se o vlastnost, kterou nám již knihovna stdio z jazyka C neposkytuje. Jde právě o jeden ze dvou minule zmiňovaných důvodů proč používat proudy místo funkcí s stdio. Opět použijeme přetížené operátory << a >>. Hlavní problém je, jak je přetížit. V první řadě musím říci, že operátory je dobré (vlastně i nutné!) přetěžovat jako obyčejné funkce, nikoliv jako členské metody. Důvod je jasný. Operátor přetížený jako členská metoda by musel být metodou nějakého proudu. To však autoři knihovny nemohli udělat, protože v době tvorby knihovny pro datové proudy nemohli znát náš datový typ, pro který budeme požadovat operátor <<, nebo >>. Stejně tak nemůžeme, jak se v OOP v podobných situacích dělá, vytvořit nějakou svou třídu mujstream, které zdědí vše například z ostream, a navíc třídu ostream rozšíří o operátor <<. Problém je v tom, že ze třídy ostream dědí mnoho tříd, které by dědily i nadále z ostream, ne z mujstream, takže by metodu << nedědily. Ve svém článku "Přetěžování operátoru 1. díl" jsem přesně uvedl, kdy přetěžovat operátory jako funkce a kdy jako metody. Nelze tedy operátory pro přístup k proudům přetížit jako metody. Smíříme se s tímto faktem a ukážeme si, jak přetížit operátor >> pro nějakou jednoduchou třídu:
|
Operátory << , >> by měly vracet referenci na proud, na který byly volány. Je to nepsané pravidlo, aby šlo operátory dávat "za sebe".
Náš operátor přistupuje k soukromým atributům třídy MojeTřída pomocí veřejných metod. Operátor >> není ale zase tak "cizí" metoda, abychom ji nedovolili přistupovat k soukromým datům. Čtenář, který je zvyklý dodržovat principy OOP, nyní asi trochu pociťuje odpor k nějakému porušení zapouzdření, ale u operátorů << a >> se běžně používá. Musíme si uvědomit, že ne ke všem soukromým proměnným musí být přístup přes veřejné metody. řešením je označit funkci jako friend (přátelskou). Pro ukázku přetížím operátor << jako přátelskou funkci. Nejprve musím v definici mojí třídy uvést, že funkce << je přátelská. Vepište prosím do třídy MojeTřída na poslední řádek (před };) text: friend istream& operátor<<(ostream &os,MojeTrida &objekt);. Tedy deklaraci funkce s klíčovým slovem friend. Kromě funkcí mohou být "přátelské" také třídy. Přátelské funkce, nebo metody přátelských tříd mohou přistupovat k soukromým položkám třídy. Nyní stačí dopsat tělo funkce:
|
A jednoduchá funkce main:
|
Asi Vás hned napadne, co se asi stane, jestliže místo čísla vložíte nějaký znak. Proudy mají tak zvané stavové bity (příznaky), které nastavují podle toho, zda došlo k nějaké chybě, nebo ne. Existují metody, kterými můžete zjistit, který bit je nastaven, tedy jestli se stalo něco špatného, případně co. Nejjednodušší způsob ale je využít přetíženého operátoru přetypování streamu na void*. Je-li například (void*) cin == NULL došlo k chybě. Samozřejmě operátor přetypování na void* je k dispozici pro všechny proudy. Je-li proud v chybovém stavu, není schopen data posílat, nebo přijímat. Je nutné jej "resetovat" metodou clear(int = 0), která vyčistí chybové stavy. Pro příklad pozměníme funkci main:
|
Nyní se podívejme na třídy ifstream (resp. ofstream), které dědí z istream (resp. ostream). Jedná se o datové proudy, jejichž zdrojem (resp. cílem) je soubor. Velkou výhodou je, že na ifstream lze volat operátor <<, protože ifstream je (dědí z) istream. Konstruktor těchto tříd může mít mnoho parametrů. Lze jej volat s 1 parametrem - jménem souboru. Otevřeme-li takto soubor a budeme-li používat operátory << a >>, bude se jednat o textový soubor a o tak zvaný formátovaný vstup a výstup. O jiných možnostech si povíme v dalším článku. Uvedu jednoduchý příklad. Opět změníme funkci main v předchozím příkladu:
|
Třída ofstream je deklarována v hlavičkovém souboru fstream. Nezapomeňte proto na začátek našeho příkladu připsat: #include<fstream>
Soubor se uzavře buď při volání destruktoru streamu, nebo pomocí metody close().
Tolik tedy dnes k datovým proudům a k přetěžování operátorů << a >>. Příště ukážu několik málo dalších příkladů a také se podíváme na neformátovaný přístup k datovým proudům - tedy na práci s binárními soubory. V následujícím článku potom k paměťovým proudům, čímž téma datových proudů dokončíme.
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