Programování v jazyku C++ Předmět navazuje na X36ALG, tj. předpokládá znalosti základů algoritmizace a základů jazyka Java Dokumentace k předmětu na WWW https://service.felk.cvut.cz/courses/x36pjc/ Slajdy k přednáškám možno stáhnout z WWW nebo zakoupit v Copy-Centrum Dejvice přednášky nejsou jen prezentace slajdů, další informace na tabuli (kopie slajdů použít pro záznam poznámek) Doporučená skripta: Cvičení: Virius, M.: Programování v C++. ČVUT 1998. vše u počítače Vývojové prostředí: ve škole CBuilderX pro Solaris, doma cokoliv Závěrečné hodnocení viz zvláštní slajd C++ 1
Programovací jazyk C 1972 D. Ritchie Bell Laboratories PDP11 1978 Kernighan, Ritchie: The C Programming Language Systémový jazyk operačního systému Unix 1982 ANSI norma X3J11, převzala ISO #include <stdio.h> void main(void) { printf( Nazdar, toto je prvni program v C\n ); C++ 2
Programovací jazyk C++ 1983 Bjarne Stroustrup, AT&T Bell Laboratories 1986 Bjarne Stroustrup: The C++ Programming Language 1990 M.Ellis, B.Stroustrup: The Annotated C++ Reference Manual 1991 Bjarne Stroustrup: The C++ Programming Language vyšlo v českém překladu (BEN 1997) 1994 Bjarne Stroustrup: The Design and Evaluation of C++ 1996 Working Paper for Draft Proposed International Standard for Information Systems -- Programming Language C++ 1997 Bjarne Stroustrup: The C++ Programming Language (3nd Edition) 1998 ISO norma ISO/IEC 14882, převzala ANSI 2000 Bjarne Stroustrup: The C++ Programming Language (Special Edition) http://www.research.att.com/~bs/homepage.html C++ 3
První program v C++ Pro starší překladače vytvořené před normou (např. Borland C++ 3.1) // PrvniProgram1.cpp #include <iostream.h> void main() { cout << "Nazdar, toto je prvni program v C++" << endl; Pro novější překladače vytvořené po normě (např. ) // PrvniProgram2.cpp #include <iostream> using namespace std; int main() { cout << "Nazdar, toto je prvni program v C++" << endl; return 0; C++ 4
Stručná charakteristika C++ Procedurální vyšší programovací jazyk, podporující objektově orientované programování, s vysokou efektivitou cílového programu Některé rysy nižších jazyků (asemblerů) Jednoduché (skalární) datové typy: celočíselné, reálné, ukazatele Strukturované datové typy: pole, řetězce, struktury, třídy (nejsou v C) Zvláštní typ reference Bohaté operační struktury: aritmetické, logické, bitové, přiřazení Základní řídicí struktury: podmíněné příkazy, přepínače, cykly, bloky, funkce, výjimky (výjimky nejsou v C) Programové rušení dynamicky vytvořených datových objektů (není sbírání smetí garbage collection) Přetěžování funkcí a operátorů (není v C) Generické funkce a třídy (není v C) Program se skládá ze zdrojových souborů nezávisle překládaných Zdrojové soubory obsahují deklarace a definice Vstupním bodem programu je funkce main C++ 5
// DruhyProgram.cpp #include <iostream> using namespace std; Ukázky programů int main () { int x = 10, y; y = x + 20; cout << "hodnota promenne x je " << x << endl; cout << "hodnota promenne y je " << y << endl; return 0; Program po překladu a spuštění vypíše: hodnota promenne x je 10 hodnota promenne y je 30 C++ 6 uvod\druhyprogram.cpp
Ukázky programů Program, který pro zadaný rok zjistí, zda je přestupný Přestupný rok je dělitelný 4 a buď není dělitelný 100 nebo je dělitelný 400 // rok.cpp #include <iostream> using namespace std; int main() { int rok; cout << "zadejte rok "; cin >> rok; cout << "rok " << rok; if (rok%4==0 && (rok%100!=0 rok%400==0)) cout << " je prestupny"; else cout << " neni prestupny"; cout << endl; return 0; C++ 7 uvod\rok.cpp
Ukázky programů Program pro výpočet pořadového čísla dne v roce // den.cpp #include <iostream> using namespace std; int main() { int den, mesic, rok, n = 0; cout << "zadejte den, mesic a rok: "; cin >> den >> mesic >> rok; switch (mesic) { case 1: n = den; break; case 2: n = 31+den; break; case 3: n = 59+den; break; case 4: n = 90+den; break; case 5: n = 120+den; break;... case 12: n = 334+den; break; default: cout << "nedovoleny mesic"; return 1; if (mesic>2 && rok%4==0 && (rok%100!=0 rok%400==0)) n++; cout << den << "." << mesic << "." << rok; cout << " je " << n << ". den v roce\n"; return 0; C++ 8 uvod\den.cpp
Ukázky programů Výpočet faktoriálu přirozeného čísla n ( n! = 1 2... n ) // faktorial.cpp #include <iostream> using namespace std; int main() { cout << "zadejte prirozene cislo" << endl; int n; cin >> n; if (n<1) { cout << n << " neni prirozene cislo"; return 1; int i = 1; int f = 1; while (i<n) { i = i+1; f = f * i; cout << n << "! = " << f << endl; return 0; C++ 9 uvod\faktorial.cpp
Ukázky programů Program pro součet posloupnosti čísel vstupní data: n a 1 a 2... a n // soucetcisel.cpp #include <iostream> using namespace std; int main() { int dalsi, suma = 0, n; cout << "zadejte pocet cisel "; cin >> n; cout << "zadejte " << n << " cisel" << endl; for (int i=1; i<=n; i++) { cin >> dalsi; suma = suma+dalsi; cout << "soucet je " << suma << endl; return 0; C++ 10 uvod\soucetcisel.cpp
Ukázky programů Počet znaků, řádků a slov ve vstupním textu // rdslzn.cpp #include <iostream> using namespace std; int main() { int c, nl = 0, nw = 0, nc = 0; bool inword = false; while ((c = cin.get())!= EOF) { ++nc; if (c == '\n') ++nl; if (c == ' ' c == '\n' c == '\t') inword = false; else if (!inword) { inword = true; ++nw; cout << "znaku " << nc << " radku " << nl; cout << " slov " << nw << endl; return 0; C++ 11 uvod\rdslzn.cpp
Ukázky programů Tabulka četnosti číslic ve vstupním textu // cislice.cpp #include <iostream> using namespace std; int ndig[10]; // globální proměnná int main() { int c, i; while ((c = cin.get())!= EOF) if (c >= '0' && c <= '9') ++ndig[c-'0']; for (i = 0; i < 10; ++i) cout << i << ' ' << ndig[i] << endl; return 0; C++ 12 uvod\cislice.cpp
Ukázky programů Funkce pro výpočet celočíselné mocniny // mocnina1.cpp #include <iostream> using namespace std; int mocnina(int x, int n) { int v = 1; for (int i = 1; i <= n; ++i) v *= x; return v; int main() { for (int i = 0; i < 10; ++i) { cout << i << ' ' << mocnina(2,i); cout << ' ' << mocnina(-3,i) << endl; return 0; C++ 13 uvod\mocnina1.cpp
Ukázky programů Funkce pro výpočet celočíselné mocniny // mocnina2.cpp #include <iostream> using namespace std; int mocnina(int, int); int main() { for (int i = 0; i < 10; ++i) { cout << i << ' ' << mocnina(2,i); cout << ' ' << mocnina(-3,i) << endl; return 0; int mocnina(int x, int n) { int v = 1; for (int i = 1; i <= n; ++i) v *= x; return v; C++ 14 uvod\mocnina2.cpp
Ukázky programů třídy, objekty, ukazatelé Vstup: řada celých čísel zakončená nulou Výstup: čísla v opačném pořadí // opacneporadi.cpp #include <iostream> using namespace std; class Prvek { int _hodn; Prvek *_dalsi; public: Prvek(int h, Prvek *d) { _hodn = h; _dalsi = d; int hodn() {return _hodn; Prvek* dalsi() {return _dalsi; ; C++ 15 uvod\opacneporadi.cpp
Ukázky programů třídy, objekty, ukazatelé int main() { cout << "zadejte radu cisel zakoncenych nulou" << endl; Prvek* prvni = NULL; int cislo; cin >> cislo; while (cislo!=0) { prvni = new Prvek(cislo, prvni); cin >> cislo; cout << "cisla v opacnem poradi" << endl; Prvek *pom = prvni; while (pom!=null) { cout << pom->hodn() << " "; pom = pom->dalsi(); cout << endl; return 0; C++ 16 uvod\opacneporadi.cpp
Ukázky programů výstupní parametry // minmax1.cpp // funkce s výstupními parametry pomocí ukazatelů #include <iostream> using namespace std; void minmax(int x, int y, int *pmin, int *pmax) { if (x < y) { *pmin = x; *pmax = y; else { *pmin = y; *pmax = x; int main() { int a, b, min, max; cout << "zadej dve cela cisla: "; cin >> a >> b; minmax(a, b, &min, &max); cout << "min = " << min << ", max = " << max << endl; return 0; C++ 17 uvod\minmax1.cpp
Ukázky programů typ reference // minmax2.cpp // funkce s výstupními parametry pomocí typu reference #include <iostream> using namespace std; void minmax(int x, int y, int& pmin, int& pmax) { if (x < y) { pmin = x; pmax = y; else { pmin = y; pmax = x; int main() { int a, b, min, max; cout << "zadej dve cela cisla: "; cin >> a >> b; minmax(a, b, min, max); cout << "min = " << min << ", max = " << max << endl; return 0; C++ 18 uvod\minmax2.cpp
identifikátory Lexikální elementy písmena (rozlišuje se velikost), číslice, _, klíčová slova if while malými písmeny! omezovače a operátory { ; + - & && <<= číselné literály 125 125.45e-7 0.12E3 oktalové: 037 hexadecimální: 0x1F znakové literály x \n \t \0 \\ \ \014 řetězce abcd xyz\nabc vnitřní reprezentace: posloupnost znaků zakončená nulou komentáře /* toto je komentar */ // zbytek řádku je komentář C++ 19
Typy dat Připomeňme: datový typ (zkrácené jen typ) specifikuje: množinu hodnot množinu operací, které lze s těmito hodnotami provádět Rozdělení typů podle struktury: jednoduché (skalární), jejichž hodnoty jsou z hlediska operací atomické strukturované, jejichž hodnoty se skládají ze složek void, jehož množina hodnot je prázdná Rozdělení typů z hlediska jejich definice: základní (standardní), které jsou definovány programovacím jazykem odvozené, které jsou definovány programem Jednoduché typy: celočíselné reálné ukazatele Množiny hodnot jednoduchých typů nejsou (na rozdíl od jazyka Java) definovány normou jazyka, ale implementací C++ 20
Základní celočíselné typy Číselné se znaménkem short = signed short = signed short int int = signed = signed int long = long int = signed long = signed long int Číselné bez znaménka unsigned short = unsigned short int unsigned = unsigned int unsigned long = unsigned long int Znakové typy unsigned char signed char char Logický typ bool Pro všechny celočíselné typy jsou definovány stejné operace (+, -, *, /, %, atd.) C++ 21
Základní celočíselné typy množiny hodnot Množiny hodnot jsou dány implementací, norma požaduje pouze short <= int <= long, unsigneg short <= unsigned <= unsigned log Vnitřní reprezentací je obvykle dvojkový doplněk Následující přehled uvádí obvyklé velikosti vnitřní reprezentace a rozsahy hodnot v prostředí 32 bitů short 2B -32768.. 32767 int 4B -2147483648.. 2147483647 long 4B -2147483648.. 2147483647 unsigned short 2B 0.. 65635 unsigned 4B 0.. 4294967295 unsigned long 4B 0.. 4294967295 signed char 1B -128.. 127 unsigned char 1B 0.. 255 char 1B -128.. 127 bool 1B false = 0, true = 1 C++ 22
Reálné typy Označení reálných typů: float double long double Množiny hodnot jsou dány implementací, norma požaduje pouze float <= double <= long double Vnitřní reprezentací je pohyblivá řádová čárka Následující přehled uvádí obvyklé velikosti vnitřní reprezentace, rozsahy absolutních hodnot a počet planých číslic mantisy v prostředí 32 bitů float 4B 3.4E-38.. 3.4E+38 7 až 8 double 8B 1.7E-308.. 1.8E308 15 až 16 long double 10B 3.4E-4932.. 1.1E+4932 19 až 20 Aritmetické typy: celočíselné + reálné C++ 23
Odvozené typy Výčtový typ výčet identifikátorů označujících celočíselné konstanty Pole jednorozměrná pole prvků libovolného typu (kromě funkce), indexováno od 0 Struktura (záznam) obsahuje pojmenované položky různých typů uložené za sebou Union (sjednocení) pojmenované položky různých typů uložené přes sebe Třída struktura s definovanými operacemi (metodami) Funkce specifikuje funkci typem návratové hodnoty a typy parametrů Ukazatel adresa datového objektu (proměnné nebo konstanty) nebo funkce specifikovaného typu Reference synonymum existujícího datového objektu C++ 24
Deklarace Stejná syntaxe pro deklaraci proměnných, typů, funkcí, struktur apod. Syntaxe zjednodušeně: paměťová třída kvalifikátor specifikace typu seznam deklarátorů ; například extern const int prom, pole[20] ; Paměťová třída v deklaraci proměnné určuje způsob přidělení paměti auto dynamické přidělení paměti na zásobníku register proměnná v registru static statické přidělení paměti resp. lokální v souboru extern bez přidělení paměti Není-li paměťová třída v deklaraci proměnné uvedena, pak: lokální proměnné ve funkci je paměť přidělena na zásobníku globální proměnné je paměť přidělena staticky Třída static u globální proměnné znamená, že proměnná je použitelná pouze v daném souboru, tzn. není přístupná z jiných souborů C++ 25
Deklarace (pokračování) Kvalifikátor udává další vlastnosti deklarovaného objektu: const konstantní objekt volatile přístup k objektu nemá být optimalizován například: extern const int Max; Max = 10; /* chyba */ Specifikace typu: void = prázdná množina hodnot označení aritmetického typu popis výčtového typu, struktury, sjednocení nebo třídy identifikátor typu Není-li specifikace typu uvedena, starší překladače doplní int Identifikátory typu se deklarují deklarací s paměťovou třídou typedef C++ 26
Deklarátory Možné tvary deklarátoru (bez typu reference): identifikátor jednoduchý deklarátor * deklarátor deklarátor ukazatele deklarátor [ konstantní výraz ] deklarátor pole deklarátor ( parametry ) deklarátor funkce ( deklarátor ) za hvězdičkou může být kvalifikátor Příklady deklarací: int i; proměnná typu int int *pi; proměnná typu ukazatel na int char ca[9]; pole 9 znaků long lf(int); funkce typu long s jedním parametrem typu int int *fp(void); funkce typu ukazatel na int bez parametrů int (*pf)(void); ukazatel na funkci typu int bez parametrů const char *pc; ukazatel na konstatní znak char * const cp; konstantní ukazatel na znak C++ 27
Deklarátory (pokračování) Obecná pravidla pro význam deklarátorů je-li S specifikace typu pro deklarátor tvořený identifikátorem id, pak se deklaruje id typu S v ostatních případech provede deklaraci vnořený deklarátor D, kterému se dodá specifikace typu upravená následujícím způsobem: deklarátor * D ukazatel na S D [ n ] D ( parametry ) ( D ) S specif. typu pro vnořený deklarátor pole n prvků typu S Příklad: char (*pp)[10] pole 10 znaků (*pp) pole 10 znaků *pp ukazatel na pole 10 znaků pp funkce vracející hodnotu typu S a s danou specifikací parametrů C++ 28
Deklarace typu Deklarace obsahující paměťovou třídu typedef Příklady: typedef unsigned char Byte; typedef unsigned short Word, *WordPtr; static Byte b; Word w; WordPtr pw; typedef int Mat[10][10]; extern Mat M; C++ 29
Popis výčtového typu Syntaxe: enum značka { seznam literálů Příklad: enum Color {Red, Blue, Green; Literály jsou synonyma celočíselných hodnot /* Red = 0, Blue = 1, Green = 2 */ Literálu lze explicitně přiřadit hodnotu enum Masky { Nula, Jedna, Dva, Ctyri = 4, Osm = 8; /* Dva = 2, Ctyri = 4, Osm = 8 */ enum Sign { Minus = -1, Zero, Plus; /* Minus = -1, Zero = 0, Plus = 1 */ enum { E1, E2, E3 = 5, E4, E5 = E4 + 10, E6; /* E4 = 6, E5 = 16, E6 = 17 */ Pro výčtové typy jsou definovány stejné operace, jako pro celočíselné typy Vnitřní reprezentace proměnných výčtových typů je stejná jako vnitřní reprezentace proměnných typu int (velikost 4B ve 32 bitovém prostředí) C++ 30
Inicializace Datové objekty (proměnné, konstanty) se inicializují v době vzniku statické na začátku programu ostatní na začátku funkce (bloku) Implicitní inicializace statické objekty jsou vynulovány ostatní nemají definovanou hodnotu Explicitní inicializace deklarátor = výraz nebo deklarátor = { seznam výrazů Statické objekty lze inicializovat pouze konstantními výrazy Příklady: float A = 10; register int B = A*A; C++ 31
Výrazy Bohatý repertoár operací: aritmetické, bitové, logické, relační, operace s ukazateli Výraz může označovat modifikovatelný objekt (lvalue) nebo hodnotu (rvalue) Pořadí vyhodnocení operandů není (až na výjimky) definováno Některé operace mají vedlejší efekt (inkrementace, dekrementace, přiřazení) v jednom výrazu nad jedním objektem max. jeden! Pro operátory je důležitá jejich priorita a asociativita C++ 32
Priorita a asociativita operátorů ( ) [ ]. -> závorky, indexace, selekce + -! * & unární operátory ++ -- inkrementace, dekrementace (typ) p řetypování sizeof operátor délky * / % násobení, d ělení, zbytek po dělení + - s čítání, odčítání << >> bitový posun vlevo, vpravo < > <= >= relace ==!= rovnost, nerovnost & bitový logický sou čin ^ bitová nonekvivalence bitový logický sou čet && logický sou čin logický sou čet?: podmín ěný výraz = *= /= %= += -= <<= >>= &= = ^= p řiřazení, operátor čárka C++ 33
Aritmetické výrazy Operace se provádějí v těchto aritmetikách: int, unsigned, long, unsigned long, float, double, long double Před provedením operace může dojít k implicitní konverzi operandů: bool, char, short (signed, unsigned) a enum jsou před provedením operace konvertovány na int (nebo unsigned int) - tzv. celočíselné roztažení (integral promotion) jméno pole prvků typu T je konvertováno na typ ukazatel na T jméno funkce je konvertováno na typ ukazatel na funkci C++ 34
Aritmetické výrazy U většiny operací s aritmetickými operandy se provádějí tzv. běžné aritmetické konverze (usual arithmetic conversion): operandy se konvertují pomocí celočíselného roztažení, a potom je-li typ jednoho operandu C++ 35 druhý se převede na long double long double double double float float unsigned long unsigned long long long unsigned unsigned int int Typy číselných literálů: 12 int 12L long 3.4 double 3.4F float 3.4L long double Příklady: a + b konverze na int, výsledek int 1 / 2 celočíselné dělení, výsledek 0 1.0 / 2.0 reálné dělení, výsledek double 1 / 2.0L konverze na long double
Aritmetické operace Operandy aritmetického typu, provádějí se běžné aritm. konverze Unární: + - Binární: + - * / % Dělení je podle typu operandů buď celočíselné nebo reálné Operace % je zbytek po dělení, musí mít operandy celočíselné, a je definována takto: x == (x / y) * y + x % y Operace + a - jsou definovány též pro ukazatele (viz dále) C++ 36
Relační operace Operandy aritmetického typu, provádějí se běžné aritm. konverze Výsledek je typu bool: false (0) relace neplatí true (1) relace platí Binární: < > <= >= ==!= Relační operátory jsou definovány též pro ukazatele C++ 37
Operandy skalárního typu Logické operace Výsledek typu bool (false 0 nebo true 1) Operandy se vyhodnocují zleva, druhý operand se nevyhodnocuje, je-li výsledek dán prvním operandem Unární:! logická negace výsledek true, má-li operand hodnotu false, jinak je výsledek true Binární: && logický součin výsledek true, mají-li oba operandy hodnotu true, jinak false logický součet výsledek true, má-li alespoň jeden operand hodnotu true, jinak false C++ 38
Bitové operace Operandy jen celočíselné, provádějí se běžné aritm. konverze Unární: ~ negace všech bitů Binární: & logický součin všech bitů logické součet všech bitů ^ logické xor všech bitů << posun bitové reprezentace levého operandu vlevo >> posun bitové reprezentace levého operandu vpravo U operací posunu pravý operand udává délku posunu v bitech Pozor, plete se & a &&, a : x = 1; y = 2; x & y == 0 x && y == 1 C++ 39
Inkrementace a dekrementace Unární operace, operand skalárního typu, modifikovatelný, označení místa v paměti Lze zapsat prefixově nebo postfixově Má vedlejší efekt: změní hodnotu operandu Inkrementace: ++ Dekrementace: -- Prefix: ++X --X inkrementuje (dekrementuje) X, hodnotou je změněné X Postfix: X++ X-- inkrementuje (dekrementuje) X, hodnotou je X před změnou Příklady: před operace po x == 1 y = ++x x == 2, y == 2 x == 1 y = x++ x == 2, y == 1 x == 1 y = --x x == 0, y == 0 x == 1 y = x-- x == 0, y == 1 C++ 40
Přiřazení Syntaxe: X = Y Levý operand musí být modifikovatelný, označení místa v paměti Přiřazení má hodnotu a vedlejší efekt Hodnotou výrazu je přiřazovaná hodnota, typem je typ levé strany Pozor: plete se = a ==! Přípustné typy operandů: levá a pravá strana jsou téhož skalárního typu nebo téhož typu struct nebo union (pro pole není přiřazení dovoleno) jsou-li typy levé a pravé strany skalární, avšak různé, musí být hodnota pravé strany konvertibilní na typ levé strany Složené přiřazení: += -= *= /= %= &= = ^= <<= >>= Význam: X op= Y je zkratkou za X = X op (Y) C++ 41
Konverze při přiřazení Následující tabulka udává implicitní konverze při přiřazení typ pravé strany typ levé strany poznámka ke konverzi jednoduchý bool je-li hodnota pravé strany nenulová, přiřadí se true (1), jinak false (0) reálný kratší reálný zaokrouhlení mantisy reálný delší reálný doplnění mantisy nulami reálný celočíselný odseknutí necelé části celočíselný reálný možná ztráta přesnosti celočíselný kratší celočíselný odseknutí vyšších bitů celočíselný unsgn. delší celočíselný doplnění nulových bitů celočíselný sgn. delší celočíselný rozšíření znaménka 0 T * T * nebo 0 void * C++ 42
Podmíněný výraz Výsledek výrazu je závislý na hodnotě podmínky Syntaxe: Podmínka? Výraz1 : Výraz2 kde Výraz1 a Výraz2 jsou kompatibilních typů Je-li Podmínka splněna, je výsledkem hodnota Výrazu1, jinak je výsledkem hodnota Výrazu2 Vyhodnocuje se podmínka a pak jen příslušný výraz Příklad: max = a > b? a : b; p = r * (x < 0? -1 : x == 0? 0 : 1); C++ 43
Operátor čárka Umožňuje několik výrazů v místě, kde se očekává jeden výraz (nejčastěji v příkazu for, viz dále) Syntaxe: Výraz1, Výraz2,, Výrazn Výrazy se vyhodnotí v pořadí zleva doprava, výsledkem je hodnota posledního výrazu (hodnoty ostatních výrazů se zahodí ) Pozor: může škodit (viz indexace) Nejčastější použití v příkazu for: for (v = 1, i = n; i > 1; v *= i, i--); Další operátory budou vysvětleny později C++ 44
Standardní datové proudy Při operacích vstupu nebo výstupu data proudí od zdroje ke spotřebiči Objekt umožňující operaci vstupu nebo výstupu se nazývá datový proud (zkráceně proud, angl. stream) Vstupní proud: zdrojem je vstupní zařízení (např. klávesnice) nebo vstupní soubor, spotřebičem je program Výstupní proud: zdrojem je program, spotřebičem výstupní zařízení (např. obrazovka monitoru) nebo výstupní soubor Standardní proudy cin, cout a cerr poskytuje knihovna specifikovaná v hlavičkovém souboru <iostream> Vstupní proud cin umožňuje vstupní konverze dat zadaných z klávesnice cin >> proměnná Druh konverze je dán typem proměnné Výstupní proud cout (cerr) umožňuje výstupní konverze dat na obrazovku cout << výraz Druh konverze je dán typem výrazu Při spuštění programu lze cin a cout přesměrovat C++ 45
Výstup: cout << char short int long char * float double long double void * Přípustné typy v konverzích Vstup: cin >> char short int long char * float double long double přeskočí počáteční mezery! C++ 46
Manipulátory Slouží pro řízení vstupní a výstupní konverze Jsou definovány v souboru <iomanip> int n = 36; cout << n <<, << hex << n <<, ; cout << oct << n << endl; cout << dec << setw(6) << n << endl; Některé manipulátory: dec hex oct endl setw(int n) setfill(int c) setprecision(int n) dekadická konverze šestnáctková konverze osmičková konverze konec řádku + flush šířka položky n znaků plnící znak c n desetinných míst C++ 47
Příkazy Obecně: příkazy se dělí na jednoduché a strukturované všechny jednoduché jsou zakončeny středníkem podmínka v cyklech a podmíněném příkazu je dána výrazem skalárního typu; je splněna, je-li hodnota výrazu různá od nuly Výrazový příkaz: výraz ; smysl mají jen výrazy s vedlejším efektem x = y + 2; y++; f(a, 2); g(); g; /* příkaz bez vedlejšího efektu */ Prázdný příkaz: ; použití např. jako prázdné tělo cyklu for (i = 0; i < 10; a[i++] = 0); C++ 48
Příkaz bloku Příkaz bloku: { posloupnost deklarací posloupnost příkazů deklarace jsou v bloku lokální, v bloku platí též deklarace z nadřazeného kontextu lokální deklarace zastíní deklaraci stejného identifikátoru z nadřazeného kontextu deklarace mohou chybět (složený příkaz) { int a, b; a = 10; { int c = a; /* c = 10 */ int a = 20; c = a; /* c = 20 */ a = 0; cout << a; /* vypíše se 10 */ C++ 49
Podmíněný příkaz Podmíněný příkaz: if ( podmínka ) příkaz if ( podmínka ) příkaz1 else příkaz2 else se vztahuje k nejbižšímu předcházejícímu if ve stejném bloku if (a > b) m = a; else m = b; if (a > b) if (a > c) m = a; else m = c; if (a > b) { if (a > b) m = a; else m = b; C++ 50
Příkazy cyklu Příkaz while: while ( podmínka ) příkaz tělo cyklu se provádí, dokud je splněna podmínka podmínka se vyhodnocuje na začátku Příkaz do: do příkaz while ( podmínka ) ; tělo cyklu se provádí, dokud je splněna podmínka podmínka se vyhodnocuje na konci těla jediný strukturovaný příkaz zakončený středníkem Příkaz for: for ( výraz1 ; výraz2 ; výraz3 ) příkaz příkaz má stejný efekt, jako příkazy: { výraz1 ; while ( výraz2 ) { příkaz ; výraz3 ; C++ 51
Příkazy řízení Příkaz break: break ; ukončí bezprostředně nadřazený cyklus nebo přepínač Příkaz continue: continue ; přejde na nové vyhodnocení podmínky cyklu while ( podm1 ) { if ( podm2 ) break; if ( podm3 ) continue; C++ 52
Příkaz větvení (přepínač) Příkaz switch: switch ( výraz ) příkaz slouží k rozdělení výpočtu do několika větví podle hodnoty celočíselného výrazu příkazem je téměř vždy složený příkaz některé z příkazů ve složeném příkazu jsou označeny návěštími ve tvaru: case konst. výraz : nebo default : po vyhodnocení výrazu se pokračuje tou variantou, která je označena návěštím se stejnou hodnotou (návěští musí být různá) návěští default pokrývá ostatní hodnoty každá větev obyčejně končí příkazem break switch ( n ) { case 1: cout << * ; break; case 2: cout << ** ; break; case 3: cout << *** ; break; default: cout << - C++ 53
Příkaz skoku a návratu Příkaz skoku: goto návěští ; návěští je identifikátor použití: výskok z více úrovní vnoření cyklu apod. lze skákat dovnitř strukturovaných příkazů - nedoporučuje se Příkaz s návěštím: návěští : příkaz návěští jsou lokální ve funkci for (i = 1; j < 10; i++) for (j = 1; j < 20; j++) { if (podm) goto konec; konec: ; Příkaz return: return výraz ; nebo return ; ukončí funkci a definuje návratovou hodnotu C++ 54
Pole Typ indexu: 0.. počet prvků - 1 kde počet prvků je dán konstantním výrazem v deklarátoru pole Typ prvků: libovolný, kromě reference Příklad: int a[10]; const int MAX = 100; float pole[max+1]; // v C musí být MAX zavedeno jinak Jméno typu pole lze zavést deklarací typu: typedef int POLE[20]; POLE a; Operace: pouze indexace (selektor pole) přiřazení mezi dvěma poli není dovoleno a[1] = 10; pole[i] = 0; Hodnota indexu se nekontroluje! C++ 55
Pole Vícerozměrná pole se deklarují jako pole, jejichž prvky jsou pole int mat[10][5]; Otázka: jaké pole se zavede následující deklarací: int a[10,5]; Přístup k prvkům vícerozměrného pole: mat[i][j] = 20; Inicializace polí: int P[3] = {1, 2, 3; /* inicializací lze zadat počet prvků pole */ int Q[] = {1, 2, 3; int PP[4][3] = {{1, 3, 5, {2, 4, 6, {3, 5, 7; /* následující inicializace má stejný efekt */ int PP[4][3] = {1, 3, 5, 2, 4, 6, 3, 5, 7; /* inicializace nemusí být úplná */ int QQ[][3] = { {1, {2, {3, {4 ; /* pole má 4 řádky, inicializován jen 1. sloupec ostatní jsou vynulovány */ C++ 56
/* razeni1.cpp */ #include <iostream> using namespace std; Příklad - řazení pole čísel const int MAXPOCET = 100; int pole[maxpocet], pocet; void sort(void) { int i, imin, min, j, n = pocet-1; for (i = 0; i < n; i++) { imin = i; min = pole[i]; for (j = i+1; j <= n; j++) if (pole[j]<min) { imin = j; min = pole[j]; if (imin!= i) { pole[imin] = pole[i]; pole[i] = min; C++ 57 pole\razeni1.cpp
Příklad - řazení pole čísel int main(void) { int i; cout << "zadej pocet: "; cin >> pocet; cout << "zadej " << pocet << " celych cisel\n"; for (i = 0; i < pocet; i++) cin >> pole[i]; sort(); cout << "serazene pole:\n"; for (i=0; i<pocet; i++) cout << pole[i] << endl; return 0; C++ 58 pole\razeni1.cpp
Literály typu řetězec: abcd xyz\nabc Řetězce knihovna C V paměti jsou zobrazeny posloupností znaků zakončenou nulovým bytem Proměnná typu řetězec se deklaruje jako pole znaků dostatečné délky char txt[10]; /* lze uložit až 9-ti znakový řetězec */ Inicializace pole znaků řetězcem: char Msg1[10] = abcd ; char Msg2[] = text ; Operace s řetězci provádějí funkce deklarované v <string.h> Pro přiřazení řetězce do pole znaků slouží knihovní funkce strcpy(kam,co): strcpy(txt, abcd ); strcpy(msg1, Msg2); Nekontroluje se, zda pole je dostatečně velké! Pro porovnání řetězců slouží knihovní funkce strcmp: strcmp(x, y) < 0 když x < y = 0 když x = y > 0 když x > y C++ 59
Příklad - řazení pole řetězců ve stylu C Program přečte posloupnost slov zakončených tečkou a slova seřadí /* razeni2.cpp */ #include <iostream> #include <string.h> using namespace std; const int MAXPOCET = 100; const int MAXDELKA = 100; char pole[maxpocet][maxdelka]; int pocet; void sort(void) { int i, imin, j, n = pocet-1; char min[maxdelka]; for (i = 0; i < n; i++) { imin = i; strcpy(min, pole[i]); for (j = i+1; j <= n; j++) if (strcmp(pole[j],min)<0) { imin = j; strcpy(min, pole[j]); if (imin!= i) { strcpy(pole[imin], pole[i]); strcpy(pole[i], min); C++ 60 pole\razeni2.cpp
Příklad - řazení pole řetězců ve stylu C int main() { int i; pocet = 0; cout << "zadej posloupnost slov zakoncenou teckou" << endl; cin >> pole[pocet]; while (strcmp(pole[pocet],".")!=0) cin >> pole[++pocet]; sort(); cout << "serazena slova:\n"; for (i = 0; i < pocet; i++) cout << pole[i] << endl; return 0; C++ 61 pole\razeni2.cpp
Řetězce knihovna C++ Jednodušší práci s řetězci umožňuje třída string ze standardní knihovny C++ Deklarace třídy je v souboru <string> Příklady deklarací objektů typu string, operací a metod: string s1, s2 = "abc", s3 = s2; s1 = s2; s3 = s1 + s2; s3 += s1; s3 += "abc"; s3 += 'x'; int delka = s3.length(); s1[0] = 'x'; cout << s1.substr(0, 2) << endl;; int i = s2.find('b'); C++ 62 pole\string.cpp
Příklad - řazení pole řetězců ve stylu C++ /* razeni3.cpp */ /* precte posloupnost slov zakoncenou teckou a slova seradi */ #include <iostream> #include <string> using namespace std; const int MAXPOCET = 100; string pole[maxpocet]; int pocet; void sort(void) { int i, imin, j, n = pocet-1; string min; for (i = 0; i < n; i++) { imin = i; min = pole[i]; for (j = i+1; j <= n; j++) if (pole[j]<min) { imin = j; min = pole[j]; if (imin!= i) { pole[imin] = pole[i]; pole[i] = min; C++ 63 pole\razeni3.cpp
Příklad - řazení pole řetězců ve stylu C++ int main() { int i; pocet = 0; cout << "zadej posloupnost slov zakoncenou teckou" << endl; cin >> pole[pocet]; while (pole[pocet]!= ".") cin >> pole[++pocet]; sort(); cout << "serazena slova:" << endl; for (i = 0; i < pocet; i++) cout << pole[i] << endl; return 0; C++ 64 pole\razeni3.cpp
Ukazatele Příklady deklarací proměnných typu ukazatel: int *p; /* p je ukazatel na int */ char *q; /* q je ukazatel na char */ S typem ukazatel souvisejí operace reference a dereference Reference (adresa): & X kde X je označení datového objektu nebo funkce Je-li X typu T, pak &X je typu T*, tzn. ukazatel na T Dereference (zpřístupnění objektu, na který ukazuje ukazatel): * X kde X je výraz typu ukazatel Je-li X typu T*, pak *X je typu T Příklady: int i, *pi = &i; /* pi obsahuje adresu i */ char c, *pc = &c; /* pc obsahuje adresu c */ *pi = 25; /* do i se uloží 25 */ *pc = a ; /* do c se uloží a */ char str[] = Hello, word ; char *ptr = &str[2]; *ptr = 1 ; /* změní se str[2] */ C++ 65
Přiřazení ukazatelů Kompatibilní vzhledem k přiřazení jsou ukazatele se stejným doménovým typem int i, *pi, pi1; char c, *pc = &c; pi = &i; O.K. pi1 = pi; O.K. pi = &c; Chyba pc = pi; Chyba Typovou kontrolu lze obejít pomocí operace přetypování pc = (char*)pi; pc ukazuje na první byte proměnné i pi = (int*)pc; nebezpečné! Prázdný ukazatel je NULL (označuje 0) pc = NULL; Ukazatel s prázdným doménovým typem: void *p; C++ 66
Ukazatelová aritmetika Ukazatelé mohou být operandy sčítání, odčítání a všech relačních operátorů Dovolené kombinace a typ výsledku: T* + int -> T* T* - int -> T* T* - T* -> int T* relop T* -> int Přičtení n k ukazateli typu T* znamená jeho změnu o n-násobek délky typu T podobně odečtení a rozdíl ukazatelů Příklady: int a[10], *p = &a[0]; *(p + 3) = 10;/* do a[3] se uloží 10 */ /* vynulování pole a */ for (p = &a[0]; p <= &a[9]; p++) *p = 0; /* nebo */ for (p = &a[0]; p <= &a[9]; *p++ = 0); C++ 67
Pole a ukazatele Jméno pole prvků typu T = konstantní ukazatel typu T* ukazující na prvek s indexem 0 int a[10], *pa, i; pa = a; totéž co pa = &a[0] *(a + 2) = 3; totéž co a[2] = 3 *(a + i) = 4; totéž co a[i] = 4; for (pa = a; pa <= a + 9; *pa++ = 0); a++; Chyba (proč?) Upřesnění indexace: X [ Y ] kde jeden výraz je typu ukazatel na T a druhý typu int, výsledek je typu T Výraz X [ Y ] je ekvivalentní s *(( X ) + ( Y ) ) pa[3] = 10; totéž co *(pa + 3) = 10; C++ 68
Příklad - řazení pole čísel pomocí ukazatelů /* razeni1a.cpp */ /* razeni pole celych cisel pomoci ukazatelu */ #include <iostream> using namespace std; const int MAXPOCET = 100; int pole[maxpocet], pocet; void sort(void) { int *p, *pmin, min, *q, *pn = pole + pocet-1; for (p = pole; p < pn; p++) { pmin = p; min = *p; for (q = p+1; q <= pn; q++) if (*q < min) { pmin = q; min = *q; if (pmin!= p) { *pmin = *p; *p = min; C++ 69 pole\razeni1a.cpp
Příklad - řazení pole čísel pomocí ukazatelů int main(void) { int *p; cout << "zadej pocet: "; cin >> pocet; cout << "zadej " << pocet << " celych cisel\n"; for (p = pole; p < pole+pocet; p++) cin >> *p; sort(); cout << "serazene pole:\n"; for (p = pole; p < pole+pocet; p++) cout << *p << endl; return 0; C++ 70 pole\razeni1a.cpp
Deklarace funkce Funkce jsou podprogramy realizující dílčí algoritmy Funkce může mít parametry: parametr funkce v C++ (C) je lokální proměnná funkce, která je při volání funkce inicializována skutečným parametrem (náhrada parametru hodnotou) Funkce může vracet hodnotu libovolného typu s výjimkou pole (typ výsledku funkce) Jestliže funkce nevrací žádnou hodnotu (je to procedura), je typ výsledku void Deklarací funkce (funkčním prototypem) se deklaruje identifikátor funkce, typy parametrů a typ výsledku; tělo funkce je dáno definicí funkce Funkce může mít proměnný počet parametrů Příklady deklarací funkcí (jména parametrů nejsou významná): int F(void); // funkce bez parametrů int F1(); // funkce bez parametrů void G(long x, int y); // procedura char *H(char *, char *); // bez jmen parametrů int K(int, ); // proměnný počet parametrů C++ 71
Definici funkce tvoří: Definice funkce hlavička funkce, což je deklarace funkce nezakončená středníkem, tělo funkce, což je blok. Tělo funkce, jejíž výsledek je typu T (T!= void), může kdekoliv dynamicky končit příkazem return x; kde x je výraz kompatibilní vzhledem k přiřazení s typem T. Tělo procedury může dynamicky končit kdekoliv příkazem return; Příklady definice funkce: long Power(long x, int z) { long result = 1; while (y-- >= 0) result *= x; return result; void Dummy(void) { C++ 72
Volání funkce Syntaxe: F ( X1, X2, Xn ) kde F je ukazatel na funkci a X1, Xn jsou výrazy skutečných parametrů Identifikátor funkce je konstantním ukazatelem na funkci Při volání funkce se: kontroluje počet parametrů (není-li funkce deklarována s proměnným počtem parametrů) kontroluje přípustnost skutečných parametrů a provádějí případné konverze (podobně jako při přiřazení) Pozor: závorky jsou třeba, i když se jedná o funkci bez parametrů! C++ 73
Volání funkce (pokračování) Příklady: long Power(long, int); long l; int a, b; float r; l = Power(l, 10); a = Power(a+3, b); f = Power(f, 3); void CtiPole(int, int *); int pole[10]; CtiPole(10, pole); C++ 74
Přetěžování (overloading) funkcí Funkce se rozlišují nejen jménem, ale i typy parametrů a počtem parametrů (neplatí v C) void f(char x) { cout << x << endl; void f(int x) { cout << x << endl; main() { f( a ); f(10); C++ 75
Přetěžování funkcí (pokračování) Při volání přetížené funkce se vyvolá ta, jejíž parametry se nejlépe spárují se skutečnými parametry Párování (matching) parametrů: 1. přesná shoda typů 2. shoda typů po roztažení (promotion) char int short int enum int float double 3. shoda typů po standardní konverzi int float float int int unsigned int long 4. shoda typů po uživatelské konverzi Pokud nejlepší párování má více než jedna funkce, ohlásí se chyba C++ 76
Přetěžování funkcí (pokračování) Příklady void f(float, int); void f(int, float); f(1,1); f(1.2,1.3); void f(long); void f(float); f(1.1); f(1.1f); void f(unsigned); void f(int); void f(char); unsigned char uc; f(uc); // chyba // chyba // chyba // f(float) // f(int) C++ 77
Implicitní hodnoty parametrů V hlavičce funkce lze definovat implicitní (default) hodnotu parametru, skutečný parametr pak lze vynechat (neplatí v C) Skutečné parametry lze vynechávat od konce void f(int x, int y=1, int z=3) { cout << x= << x << y= << y << z= << z); main() { f(10, 20, 30); f(10, 20); f(10); Co není dovoleno f(int x=1, int y); chyba f(int x, int y=10); f(int x); f(20); nejednoznačnost C++ 78
Inline funkce Volání inline funkce není skok do podprogramu, ale nahradí se tělem funkce inline int max(int x, int y) { return x>y? x : y; main() { int a,b,c; a = max(b, c); Překlad inline není zaručen C++ 79
Výstupní parametry funkcí Parametrem může být funkci zadána proměnná, jejíž hodnotu má funkce změnit Styl C (pomocí ukazatelů): Má-li funkce změnit hodnotu proměnné typu T, parametr bude typu T*, tj. ukazatel na T Příklad: funkce pro výměnu hodnot dvou proměnných typu int void swap(int *px, int *py) { int pom = *px; *px = *py; *py = pom; použití: int a, b; float x, y; const int c = 10; swap(&a, &b); swap(&x, &y); // chyba při překladu swap(&x, &c); // chyba při překladu (viz též příklad uvod/minmax1.cpp) C++ 80
Výstupní parametry funkcí Styl C++ (pomocí typu reference): Má-li funkce změnit hodnotu proměnné typu T, parametr bude typu T&, tj reference na T Příklad: void swap(int& x, int& y) { int pom = *x; x = y; y = pom; použití: int a, b; float x, y; const int c = 10; swap(a, b); swap(x, y); // chyba při překladu swap(x, c); // chyba při překladu (viz též příklad uvod/minmax2.cpp) C++ 81
Parametr typu reference Parametr typu reference na T označuje ve funkci proměnnou, která je dána skutečným parametrem Přípustným skutečným parametrem pro parametr typu reference je pouze proměnná typu T (nemůže to být ani proměnná jiného typu, ani konstanta, ani výraz obsahující operátory) Typ reference může být použit i při deklaraci proměnné (viz později) Typ reference může být kvalifikován jako typ označující konstantu (viz později) C++ 82
Příklad - čtení a řazení pole funkcemi s parametry /* razeni.cpp */ #include <iostream> using namespace std; void ctipole(int& pocet, int maxpocet, int *pole); void vypispole(int pocet, int *pole); void sort(int pocet, int *pole); int main() { const int MAXPOCET = 100; int pocet; int pole[maxpocet]; ctipole(pocet, MAXPOCET, pole); cout << "zadane pole" << endl; vypispole(pocet, pole); sort(pocet, pole); cout << "serazene pole" << endl; vypispole(pocet, pole); return 0; C++ 83 funkce\razeni.cpp
Příklad - čtení a řazení pole funkcemi s parametry void ctipole(int& pocet, int maxpocet, int *pole) { cout << "zadej pocet prvku pole(max. " << maxpocet << "): "; cin >> pocet; if (pocet>maxpocet) { cout << "pocet prevysuje limit" << endl; exit(1); cout << "zadej " << pocet << " celych cisel\n"; for (int i = 0; i < pocet; i++) cin >> pole[i]; C++ 84 funkce\razeni.cpp
Příklad - čtení a řazení pole funkcemi s parametry void vypispole(int pocet, int* pole) { for (int i=0; i<pocet; i++) cout << pole[i] << endl; C++ 85
Příklad - čtení a řazení pole funkcemi s parametry void sort(int pocet, int* pole) { int i, imin, min, j, n = pocet-1; for (i = 0; i < n; i++) { imin = i; min = pole[i]; for (j = i+1; j <= n; j++) if (pole[j]<min) { imin = j; min = pole[j]; if (imin!= i) { pole[imin] = pole[i]; pole[i] = min; C++ 86 funkce\razeni.cpp
Modulární struktura programu Modul je obecně programová jednotka, ve které jsou definovány prostředky (typy, proměnné, funkce,...) použitelné v jiných programových jednotkách; říkáme, že modul tyto prostředky vyváží Modul má dvě části: specifikační část, ve které jsou vyvážené prostředky deklarovány implementační část, ve které jsou vyvážené prostředky implementovány V jazyku C++ (C) je modul m tvořen dvěma soubory: specifikační část tvoří soubor m.h (hlavičkový soubor) implementační část tvoří soubor m.cpp soubor m.h se direktivou #include vloží do všech souborů, které prostředky vyvážené modulem m využívají, a pro zajištění konzistence specifikace a implementace i do souboru m.cpp C++ 87
Modulární struktura programu Příklad: řazení pole Procedury pro čtení, výpis a řazení pole vložíme do samostatného modulu tvořeného soubory pole.h a pole.cpp // pole.h void ctipole(int&, int, int*); void vypispole(int, int*); void sort(int, int*); // pole.cpp #include "pole.h" #include <iostream> using namespace std; void ctipole(int& pocet, int maxpocet, int *pole) {... void vypispole(int pocet, int* pole) {... void sort(int pocet, int* pole) {... C++ 88 prog\priklad1\pole.h,pole.cpp
Modulární struktura programu Soubor main.cpp bude používat funkce vyvážené modulem pole // main.cpp #include "pole.h" #include <iostream> using namespace std; int main() { const int maxpocet = 100; int pocet; int pole[maxpocet]; ctipole(pocet, maxpocet, pole); cout << "zadane pole" << endl; vypispole(pocet, pole); sort(pocet, pole); cout << "serazene pole" << endl; vypispole(pocet, pole); return 0; C++ 89 prog\priklad1\main.cpp
Parametry funkce main Hlavní funkce main může být napsána jako funkce se dvěma parametry, s jejichž pomocí lze převzít parametry příkazového řádku, kterým je program spuštěn /* mainpar.cpp */ #include <iostream> using namespace std void main(int argc, char *argv[]) { int i; cout << "parametry prikazoveho radku:\n"; for (i = 0; i < argc; i++) cout << i << ": " << argv[i] << endl; argv[0] cesta souboru spuštěného programu argv[1] první parametr argv[argc-1] poslední parametr C++ 90
Třídy a objekty V jazyku Java musí každá deklarace být součástí nějaké třídy; třída zde slouží jako zdroj funkcí i jako datový typ Jazyk C++ vychází z jazyka C, kde zdrojem funkcí i dat jsou soubory tvořené deklaracemi a definicemi. V jazyku C++ třída slouží především jako popis strukturovaného datového typu a specifikuje, z jakých složek (položek, atributů) se skládají objekty (instance) dané třídy a jaké operace lze s objekty dané třídy provádět. Připomeňme příklad z X36ALG: Čítač Zvětšit Zmenšit Nastavit 35 C++ 91
Čítač Příklad komunikace s programem Hodnota=0 0. Konec 1. Zvetsit 2. Zmensit 3. Nastavit Vase volba: 1 Hodnota=1 0. Konec 1. Zvetsit 2. Zmensit 3. Nastavit Vase volba: 0 Konec C++ 92
Funkce menu int menu() /* vypise nabidku a precte volbu vrati: 0... konec, 1,2,3... operace s citacem */ { char volba; cout << endl; do { cout << "0. Konec\n"; cout << "1. Zvetsit\n"; cout << "2. Zmensit\n"; cout << "3. Nastavit\n"; cout << "Vase volba: "; cin >> volba; cin.ignore(100, '\n'); if (volba < '0' volba > '3') { cout << "Nedovolena volba\n"; volba = 'e'; while (volba == 'e'); return volba '0'; C++ 93 tridy1\priklad1\main.cpp
Čítač jako datový typ Čítač zavedeme jako datový typ s operacemi zvetsit, zmensit, nastavit a hodnota a s datovými položkami hodn a pochodn Grafické vyjádření: Citac hodn název typu datové položky pochodn zvetsit operace zmensit nastavit hodnota Poznámka: hodnota položky pochodn bude stanovena při vytvoření objektu C++ 94
Třída Citac /* citac.h */ class Citac { int hodn; int pochodn; public: Citac(int ph) {pochodn = ph; nastavit(); void zvetsit() {hodn++; void zmensit() {hodn--; void nastavit() {hodn = pochodn; int hodnota() {return hodn; ; C++ 95 tridy1\priklad1\citac.h
#include "citac.h" #include <iostream> using namespace std; Program s objektem třídy Citac int menu() /* vypise nabidku a precte volbu vrati: 0... konec, 1,2,3... operace s citacem */ {... int main() { int volba; cout << "\ncitac - obektový styl\n"; Citac citac(0); do { cout << "Hodnota = " << citac.hodnota() << endl; volba = menu(); switch (volba) { case 1: citac.zvetsit(); break; case 2: citac.zmensit(); break; case 3: citac.nastavit(); break; while (volba > 0); cout << "Konec\n"; return 0; C++ 96 tridy1\priklad1\main.cpp
Definice metod v implementačním souboru Definice metod nemusí být součástí deklarace třídy, ale mohou být uvedeny v implementačním souboru Příklad: soubor citac.h obsahuje deklaraci třídy, ve které jsou pouze deklarace položek a deklarace (prototypy) konstruktoru a metod: /* citac.h */ class Citac { int hodn; int pochodn; public: Citac(int ph); void zvetsit(); void zmensit(); void nastavit(); int hodnota(); ; C++ 97 tridy1\priklad2\citac.h
Definice metod v implementačním souboru Soubor citac.cpp obsahuje definice metod: /* citac.cpp */ #include "citac.h" Citac::Citac(int ph) {pochodn = ph; nastavit(); void Citac::zvetsit() {hodn++; void Citac::zmensit() {hodn--; void Citac::nastavit() {hodn = pochodn; int Citac::hodnota() {return hodn; C++ 98 tridy1\priklad2\citac.cpp
Deklarace třídy Typ třída = datové položky + metody + konstruktory + destruktor + případné další deklarace class T { deklarace položek deklarace metod typ jméno( ); deklarace konstruktorů T( ); deklarace destruktoru ~T(); ; Definice metody: typ T::jméno( ) { Definice konstruktoru: T::T( ) { Definice destruktoru: T::~T() { V těle metody (konstruktoru, destruktoru) jsou přímo vidět položky (metody) daného objektu C++ 99
Inline metody Je-li metoda (konstruktor, destruktor) definována v rámci deklarace třídy (ne v implementačním souboru), překladač ji přeloží jako jako inline class T { typ jméno( ) { tělo T( ) { tělo ~T() { tělo ; Inline překlad není zaručen Poznámka: deklarace metody uvnitř deklarace třídy je zakončena středníkem definice metody uvnitř deklarace třídy není zakončena středníkem C++ 100
Řízení přístupu Veřejné položky (metody, konstruktory, destruktor) přístupné z vnějšku třídy se deklarují za klíčovým slovem public class T { deklarace privátních položek a metod z vnějšku nepřístupných public: deklarace veřejných položek, metod, konstruktorů a destruktoru z vnějšku přístupných ; Privátní položky metody) jsou přístupné jen v metodách dané třídy Klíčovým slovem private se přístupnost mění na privátní class T { public: deklarace veřejných metod a položek private: deklarace privátních metod a položek ; C++ 101
Deklarace objektu Objekt v C++ je proměnná typu třída (instance třídy) Deklarace objektu je vždy spojena s inicializací konstruktorem T x( ); T y; deklarace objektu a inicializace konstruktorem s parametry deklarace objektu a inicializace konstruktorem bez parametrů Konstruktor nelze vyvolat jinak, než při vytvoření proměnné! Konstruktory mohou být přetížené, při inicializaci se vyvolá ten, jehož parametry se nejlépe párují se skutečnými parametry Bezprostředně před zrušením objektu se volá destruktor (je-li deklarován) C++ 102
Použití přístupných metod a položek Volání metody M na objekt x: x.m( ); Metody mohou být přetížené, vyvolá se ta, jejíž parametry se nejlépe párují se skutečnými parametry Označení přístupné položky P objektu x: x.p Příklad: class T { public: int a; ; T x; x.a = 1; C++ 103
Rozdíl mezi class a struct Jen v implicitní přístupnosti class T { přístupnost private ; struct T { přístupnost public ; class T { int a; public: void f(); ; struct T { private: int a; public: void f(); ; class T { public: void f(); private: int a; ; C++ 104 struct T { void f(); private: int a; ;
Třída pro operace s komplexními čísly /* complex.h */ #include <ostream> using namespace std; Třída Complex class Complex { double re, im; public: Complex(double r = 0, double i = 0); double getre() const {return re; double getim() const {return im; double abs() const; Complex plus(const Complex& y) const; Complex minus(const Complex& y) const; friend ostream& operator<<(ostream&, const Complex&); ; C++ 105 tridy1\priklad3\complex.h
Implementace třídy Complex: /* complex.cpp */ #include "complex.h" #include <cmath> using namespace std; Třída Complex Complex::Complex(double r, double i) { re=r; im=i; double Complex::abs() const { return sqrt(re*re + im*im); Complex Complex::plus(const Complex& y) const { return Complex(re+y.re, im+y.im); Complex Complex::minus(const Complex& y) const { return Complex(re-y.re, im-y.im); ostream& operator<<(ostream& os, const Complex& x) { os << x.tostring(); return os; C++ 106 tridy1\priklad3\complex.cpp
Poznámky ke třídě Complex Complex plus(const Complex& y) const; const ve specifikaci parametru typu reference znamená, že metoda (funkce) parametr nezmění a skutečným parametrem tedy může být i konstanta const na konci hlavičky metody znamená, že metoda nezmění položky objektu, na který se volá, a že tedy může být volána i na konstantní objekt (const se musí být uvedeno i v hlavičce definice metody) #include <ostream> vložení h-souboru, který obsahuje deklaraci tříd pro práci s výstupními proudy (streamy) friend ostream& operator<<(ostream&, const Complex&); deklarace funkce, která se vyvolá pro provedení operace os << c, kde os je objekt s vlastnostmi výstupního proudu a c je objekt typu Complex. Tím, že je tato deklarace funkce součástí deklarace třídy a má prefix friend, funkce má stejná přístupová práva k privátním položkám objektů typu Complex jako metody dané třídy C++ 107
Použití třídy Complex /* main.cpp */ #include "complex.h" #include <iostream> using namespace std; int main() { Complex a(1,1), b(2,2), c; cout << "a = " << a << endl; cout << "b = " << b << endl; c = a.plus(b); cout << "a+b = " << c << endl; return 0; C++ 108 tridy1\priklad3\main.h
Struktury v jazyku C V jazyku C nejsou třídy, pouze struktury Popis typu struktura obsahuje pouze deklarace veřejných položek a pro zavedení jména typu struktury je třeba použít deklaraci typu typedef typedef struct Complex {float re, im; Complex;... Complex x = {1,1, y = {2,2, z; Operace se strukturou se realizují pomocí funkcí Complex plus(complex x, Complex y) { Complex vysl; vysl.re = x.re + y.re; vysl.im = x.im + y.im;... z = plus(x,y); C++ 109
Dynamické proměnné Statická proměnná: je dána deklarací a má jméno je-li deklarovaná na úrovni souboru, existuje po celou dobu provádění programu je-li deklarovaná ve funkci, je ve funkci lokální a existuje jen po dobu provádění funkce Dynamická proměnná: není dána deklarací je vytvořena dynamicky operátorem new (v C funkcí malloc apod.) při provádění programu nemá jméno, je přístupná pomocí ukazatele existuje do té doby, než je programově zrušena operátorem delete (v C++ není garbage collector) C++ 110
Dynamicky vytvořený objekt - příklad Příklad (čítač): #include "citac.h"... int main() { int volba; cout << "Citac\n"; Citac* pcitac = new Citac(0); do { cout << "Hodnota = " << pcitac->hodnota() << endl; volba = menu(); switch (volba) { case 1: pcitac->zvetsit(); break; case 2: pcitac->zmensit(); break; case 3: pcitac->nastavit(); break; while (volba > 0); cout << "Konec\n"; delete pcitac; return 0; C++ 111 dynprom\citac\main.cpp