You are on page 1of 58

Jazyky C a C++ Petr Peringer peringer AT fit.vutbr.

cz Vysok uen technick v Brn Fakulta informanch technologi, Boetchova 2, 61266 Brno kvten 2002 vod Tyto slajdy jsou ureny pro studenty kursu CPP na FIT. Obsahuj zkladn popis jazyk C a C++ vhodn pro studenty, kte ji zvldli nkter z vych programovacch jazyk (Pascal,...). Obsah slajd je velmi strun, podrobnj informace jsou soust vkladu.

Zdroje informac dobr literatura http://www.fit.vutbr.cz/study/courses/CPP/public/ NetNews: FAQ, pehledy knihoven databze programu man (sekce 3) GNU info a dal dokumentace help v integrovanm prosted Programovac jazyk C++

Historie C (1973) K&R = Kerninghan, Ritchie C with classes (1981) Bjarne Stroustrup, Bell Labs ISO C90 (1990) mezinrodn norma jazyka C ISO C++ (1998) mezinrodn norma C++ ISO C99 (1999) nov norma jazyka C Pvodn definic je kniha Stroustrup: The C++ Programming Language (Addison-Wesley 1985, 1991, 1997). Plat norma ISO/IEC 14882 (1998). Existuje cel ada peklada a vvojovch prosted pro jazyk C++. Aktuln pehled najdete na WWW strnce. Doporuen prosted GNU C++ existuje pro vechny bn platformy. Je teba pouvat co nejnovj verzi, protoe ty star se pli odchyluj od normy.

Poznmka: Tento text pedpokld znalost jazyka ISO C

Charakteristika jazyka C++ Obecn vyuiteln programovac jazyk vy rovn. Je standardizovan (ISO/ANSI) Podporuje abstraktn datov typy a vytven knihoven. Nstupce jazyka C (zptn kompatibilita) Efektivita Objektov orientace (tdy, ddinost) Monost petovat opertory Generick tdy a funkce (ablony) Obsluha vjimek Programy jsou penositeln pi dodrovn jistch pravidel Mnoho rznch implementac peklada Mnostv prostedk pro rzn aplikace (GUI, ...) Nevhody je vt a sloitj ne C zddil nkter nevhody jazyka C nen ist objektov orientovan Pklady

Pklad: peklad a sestaven programu Soubor ahoj.cc: #include <iostream> int main() { std::cout << " Ahoj! \n"; // tisk etzce } Zpsob zpracovn (UNIX, peklada GNU C++): g++ -o ahoj ahoj.cc # peklad, sestaven ./ahoj # sputn Poznmka: Ppony .cc, .cpp, .C, .c++, .cxx Optimalizace (UNIX, GNU C++):

g++ -O2 -o prog prog.cc Ladn (Linux, GNU C++, GNU debugger): g++ -g -o prog prog.cc # +ladic informace gdb prog # ladn ddd prog # ladn v X Pklad: etzce // pklad ten a tisku etzc v C++ #include <iostream> #include <string> using namespace std; // nemusme pst std:: int main() { #if 1 cout << "C++ string" << endl; string s; cout << "s = " << s << endl; cout << "string s (libovoln dlka): " << flush; cin >> s ; // sledujte jak funguje (te slova) cout << "s = " << s << endl; #else cout << "C string" << endl; char s[100] = ""; cout << "s = " << s << endl; cout << "string s (max 99 zn): " << flush; cin >> s ; // te slovo, pozor na "buffer overflow" cout << "s = " << s << endl; #endif } Pklad: etnost slov // stl-map.cc // pklad pouit STL kontejneru map<> // program pot etnost slov ve vstupnm textu // slovo je cokoli oddlen "blm znakem" #include <string> #include <iostream> #include <map>

typedef std::map<string,int> map_t; typedef map_t::iterator mapiter_t; int main() { std::string word; map_t m; // asociativn pole while( std::cin >> word ) m[word]++; // tisk for(mapiter_t i=m.begin(); i!=m.end(); ++i) cout << i->first << "\t" << i->second << "\n"; } Pklad: azen sel // stl-sort-vector.cc // pklad pouit algoritmu sort #include <vector> // vector #include <algorithm> // sort, copy #include <iostream> // cout #include <iterator> // ostream_iterator typedef std::vector<int> vec_t; typedef std::ostream_iterator<int> outiter_t; int main() { #if 1 const int SIZE = 5; static int a[SIZE] = { 4, 2, 5, 1, 3 }; vec_t v(SIZE); // vektor std::copy(a, a+SIZE, v.begin() ); // kopie #else int i; vec_t v; while ( std::cin >> i ) // ten v.push_back(i); // vektor se zvtuje #endif std::sort(v.begin(), v.end()); // azen outiter_t o(std::cout, "\n"); // itertor std::copy(v.begin(), v.end(), o); // tisk } Rozdly mezi C a C++

C++ je nadstavbou nad jazykem C90 dobe napsan C programy jsou t C++ programy (s nkolika vjimkami: nov klov slova, poznmky, povinn prototypy funkc, silnj typov kontrola) rozdly mezi C a C++ jsou zjitny pekladaem krom nkolika vjimek: znakov literly jsou typu char sizeof('a') == sizeof(int) // C sizeof('a') == sizeof(char) // C++ vtov typ nen ekvivalentn typu int enum e { A }; sizeof(A) == sizeof(int) // C sizeof(A) == sizeof(e) // C++ != sizeof(int) jmno struktury v C++ me pekrt jmno objektu, funkce, vtu nebo typu v nadazenm bloku: int x[99]; void f() { struct x { int a; }; sizeof(x); /* pole v C, struktura v C++ */ } Rozen C++ typ bool (true, false) typ reference inline funkce deklarace v bloku je pkaz anonymn unie petovn funkc a opertor opertory new, delete, new[] a delete[] tdy (class), abstraktn tdy ukrvn dat (private, public, protected) automatick inicializace uivatelem definovan konverze polymorfismus (virtuln funkce) jmno tdy a vtu je jmno typu ddinost, nsobn ddinost ukazatele na leny td v inicializaci statickch objekt je dovolen obecn vraz generick datov typy - ablony (template, typename) obsluha vjimek (try, catch, throw) prostory jmen (namespace, using) nov zpsoby petypovn (static_cast, const_cast, reinterpret_cast, dynamic_cast) informace o typu za bhu programu (typeid, type_info) klov slovo mutable Poznmky

/* text C poznmky */ // text C++ poznmky plat a do konce dku Identifiktory Identifiktory obsahujc dvojit podtrtko (__), nebo zanajc podtrenm a velkm psmenem jsou vyhrazeny pro implementaci C++.

Klov slova C++ asm enum operator throw auto explicit private true bool extern protected try break false public typeid case float register typename catch for reinterpret_cast union class friend short unsigned const goto signed using const_cast char sizeof virtual continue inline static void default int static_cast volatile do long struct while double mutable switch wchar_t dynamic_cast namespace template else new this Alternativn reprezentace bitand and bitor or xor compl and_eq or_eq xor_eq not not_eq Literly Syntaxe selnch literl je stejn jako v C. Znakov literly jsou typu: char v C++ int v C, v C++ pouze vceznakov (mbc) Poznmka: V C++ existuj 3 rzn znakov typy: char, unsigned char a signed char

Deklarace Deklarace me bt kdekoliv mezi pkazy.

Typov kontrola Silnj typov kontrola v C++ : void (*func)(); je ukazatel na fci vracejc void v C, ukazatel na fci vracejc void bez parametr v C++ Ukazatel na konstantn objekt nelze piadit do ukazatele na nekonstantn objekt. Typov kontrola pi sestavovn programu rozli funkce s rznmi parametry Vtov typ: lze piadit pouze konstantu danho typu lze vynechat klov slovo enum pi pouit sizeof vtovho typu zvis na hodnotch prvk Pkazy: rozsah deklarace promnn cyklu ve for for(int i=1; i<10; i++) { /* zde plat i */ } (pozor na pekladae neodpovdajc norm: BC3.1, ...) je chybou, kdy je pkazem skoku peskoena inicializace promnn Typ reference T & x = promnn_typu_T; blzk ukazatelm pouiteln pro pedvn parametr odkazem nelze vytvoit referenci na referenci, referenci na bitov pole, pole referenc a ukazatele na reference. Pklady: double x = 1.23456; double & xref = x; // bn pouit double & yref; // chyba! chyb inicializace extern int & zref; // zde me bt bez inicializace void Tran(Mat & m);// pedn odkazem // chybn nebo netypick pouit: const int & i = 7; // vytvo pomocnou promnnou int & i = 7; // chyba!

float f = 3.14; const int & ir = f;// pomocn promnn = 3 ir = 5; // chyba! nelze zmnit Poznmka: int & f(param); // pozor na to co se vrac! f(p) = 1; Typ bool Booleovsk literly: false a true implicitn konverze na int true ---> 1 false ---> 0 konverze sel, vt a ukazatel na bool 0 ----> false jinak ----> true vsledek relan operace je typu bool

Pklad: bool test = false; test = (a > b); // bool test = 5; // int --> bool Poznmka: pokud star peklada nem vestavn typ bool, lze (sten) nahradit

Opertory C++ maj 16 rovn priorit: opertory asoc. ( ) [ ] -> :: . ! ~ + - ++ -- & * (Typ) sizeof new delete .* ->* */% +<< >> < <= > >= == !=

& ^ | && || ?: = *= /= %= += -= &= ^= |= <<= >>= , Poznmka: (Typ) znamen vechny druhy petypovn Nov opertory: opertor popis :: kvalifiktor .* dereference ukazatele na len tdy pes objekt ->* dereference ukazatele na len tdy pes ukazatel na objekt new dynamick vytvoen objektu delete zruen objektu static_cast, nov opertory petypovn reinterpret_cast, const_cast, dynamic_cast Pklady: T *p = new T[10*n]; // dynamick alokace pole T *p2 = new T(5); // dynamick alokace objektu char *s = new char[100]; delete [] p; delete p2; delete [] s; Opertor :: pstup ke globln promnn: double x; void f() { int x; ::x = 3.1415926; // globln x } explicitn specifikace tdy: class T { public:

int metoda(); };

// deklarace metody

int T::metoda() { .... } // definice mimo tdu specifikace prostoru jmen: prostor::identifiktor prostor::podprostor::identifiktor std::cin Standardn konverze v C++ Implicitn konverze probhaj automaticky (jsou-li nutn) pi vyhodnocovn binrnch operac: Kad 'mal' celoseln typ se konvertuje takto: typ konverze na metoda char int podle nastaven unsigned char int dopln nuly signed char int roz znamnko short int stejn hodnota unsigned short unsigned int stejn hodnota enum int stejn hodnota bool int 0 nebo 1 Potom je kad hodnota operandu bu int (vetn long a unsigned modifiktor) double, float nebo long double. Je-li nkter operand long double, je druh konvertovn na long double Jinak, je-li operand double, konvertuje druh na double Jinak, je-li operand float, konvertuje druh na float Jinak, je-li operand unsigned long, konvertuje druh na unsigned long Jinak, je-li operand long, konvertuje druh na long Jinak, je-li operand unsigned, konvertuje druh na unsigned Jinak, jsou oba operandy typu int Vsledek odpovd typu obou operand po konverzi.

Poznmka: Pi porovnvn sla int s slem unsigned me dojt k (pro nkoho neoekvanm) problmm: int i = -1; unsigned u = 1234; if(i<u) printf(" i < u "); /* nevytiskne nic! */ Explicitn konverze

uvd programtor do textu programu (a pebr za n vekerou odpovdnost): (typ) vraz typ(vraz) static_cast<typ>(vraz) Pklady: ukzky petypovn double(int1)/int2 complex(3.14) int('c') static_cast<void*>(ptr) Poznmka: Monost pouit funkc z knihoven jazyka C extern "C" int f(int); Preprocesor jako v C - beze zmn minimalizovat jeho pouvn (jsou jin prostedky): Definici #define K1 10 lze nahradit za const int K1 = 10; Definici #define f(x) (vraz_x) lze nahradit za inline int f(int x) { return vraz_x; } ppadn lze pout generick funkce template<class T> inline T f(T x) { return vraz_x; } Zkladn principy objektov orientovanho pstupu Tradin pstup program = data + algoritmy(podprogramy) Modulrn pstup program = moduly modul = data + algoritmy(podprogramy) Objektov orientovan pstup

program = objekty + komunikace kad objekt pat do njak tdy (klasifikace) hierarchie objekt (skldn) hierarchie td (ddinost) Vvoj program analza - nvrh - implementace - testovn - drba Objektov orientovan analza (OOA) zkoumn poadavk z hlediska td a objekt Objektov orientovan nvrh (OOD) dekompozice popis systmu a jeho charakteristik notace (grafy) Objektov orientovan programovn (OOP) program je skupina spolupracujcch objekt kad objekt reprezentuje instanci njak tdy tdy jsou navzjem v relaci ddinosti volba implementanho jazyka Objektov model Hlavn principy Abstrakce Zapouzden Modularita (fyz.) Hierarchie Vedlej principy typovn paralelismus persistence Poznmky: tyto principy nejsou nov ddinost = hierarchie abstrakc

Notace pouit graf diagramy td diagramy objekt diagramy komunikace objekt Poznmka: UML

Tdy tda = data + funkce + ochrana dat rozen systmu typ -- reprezentuje mnoinu objekt definuje rozhran a chovn objekt klov slova: class, struct a union Pklad: class T { // data (i jin objekty) int i; // metody void m(); // specifikace pstupovch prv private: // definice vnoench typ, td, konstant, ... typedef int typ; }; T x; // objekt tdy T T &refx = x; // reference na objekt tdy T T *ptrx = &x; // ukazatel na objekt tdy T T xarr[20]; // pole objekt tdy T C++ povoluje nekompletn deklarace td: class X; // => omezen pi pouit Datov leny a vnoen objekty bn datov sloky (jsou v kadm objektu) statick datov sloky pouze jedna instance pro jednu tdu (tj. vechny objekty tdy sdl tuto instanci) pstupn i kdy neexistuje dn objekt mus se definovat a inicializovat vn definice tdy (krom konstant) Pklad: class X { static const int N = 100; // konstanta static int count; // jedna instance pro tdu int i; // je v kadm objektu string s; // je v kadm objektu };

int X::count = 0; // Pozor! je nutn definice Pouit statickch len td: redukce potu viditelnch globlnch jmen, kontrola pstupovch prv k jejich jmnm spolen bank pro vechny objekty - nap. poet vytvoench objekt dan tdy Kontrola pstupu ke lenm td public me bt pouit libovolnou funkc private pouze pro metody a friend funkce dan tdy protected jako private, ale navc je dostupn v metodch a friend funkcch td odvozench z tto tdy pro implicitn plat lze pedefinovat class private ano struct public ano union public ne Pstupov specifikace mohou bt umstny libovoln: class T { int i; // class => implicitn private public: int j; // public protected: int k; // protected public: int l; // public int m; }; Friend funkce a tdy klov slovo friend maj pln prva pstupu ke vem lenm tdy vlastnost friend se nedd vlastnost friend nen tranzitivn class Y; // nekompletn deklarace tdy Y class X { friend Y; // friend tda Y friend int f(); // deklarace friend funkce // ... }; class Y { }; // definice tdy Y Poznmky: naruuje ochranu dat pouvat jen vjimen

pouiteln pro vytven mnoin pbuznch td (napklad kontejner + itertor) Metody konstruktory (vznik objektu) destruktory (znik objektu) bn metody statick nestatick virtuln metody (polymorfismus) opertory (rzn operace: + - * /) konverze (petypovn objektu na jin typ) Inline metody optimalizace rychlosti programu vhodn pro krtk funkce metoda definovan uvnit tdy je automaticky inline: class X { char *i; public: char *f() { // implicitn inline return i; } }; s explicitnm uvedenm klovho slova inline: inline char *X::f() { return i; } Pklad: tda interval // tda sel od jedn do deseti - verze 1, nevhodn class Int_1_10 { int n; public: // zmna prva pstupu void SetValue(int x) { if(x<1 || x>10) error("Range error"); n = x; } int GetValue() { return n; } }; /////////////////////////////////////////////////// // - verze 2 (s konstruktory) class Int_1_10 { int n; public:

Int_1_10() { n = 1; } // implicitn ctr Int_1_10(int n) { SetValue(n); }// dal ctr void SetValue(int x); // deklarace metod int GetValue() { return n; } void Print(); }; void Int_1_10::SetValue(int x) { // definice metody if(x<1 || x>10) error("Range error"); n = x; } Klov slovo this implicitn parametr nestatickch metod tdy ukazatel na objekt se kterm metoda pracuje pro metodu tdy T je this typu T *const nebo const T *const lze pout pouze uvnit nestatick metody, napklad pro pedn odkazu na objekt Pklad: class T { void f(); void g() const; T clone() { return *this; } }; T o1; const T o2; int main() { o1.f(); // T *const this = &o1 o2.g(); // const T *const this = &o2 } Statick metody nemaj this nesm bt virtuln chovaj se jako obyejn funkce, ale maj pstup k private slokm tdy Pklad: class X { static int count; public:

// toto nen definice!

static int getCount(); static void func(int i, X* ptr); void g(); }; int X::count = 0; // definice a inicializace

void g() { int i = X::getCount(); // nepotebuje objekt X obj; // definice objektu tdy X::func(1, &obj); // kvalifikace pro static obj.g(); // obyejn metoda } Vnoen typy typy deklarovan uvnit tdy vnoen tda (nested class) lze pout nepln deklarace vnoen tdy souvislost s prostory jmen pouit pro ukryt implementan zvislch td Pklad: struct A { typedef int TypInt; // vnoen typ struct B { // definice vnoen tdy void MetodaB(int); }; class C; // forward deklarace }; class A::C { }; // definice

void A::B::MetodaB(int i) { } int main() { A::B obj; A::TypInt i = 5; obj.MetodaB(i); } Opertory new a delete Dynamick vytven a ruen jednotlivch objekt (new, delete)

pol objekt (new[], delete[]) Lze pedefinovat, ppadn petit (vhodn napklad pro pouit s jinou sprvou voln pamti). Alokace objekt: new T alokuje pam pro objekt pouije T::operator new(), pokud existuje jinak pouije ::operator new() operator new pi chyb vyvol vjimku bad_alloc Pozor! zastaral pekladae (BC<4.0) vrac 0 po spn alokaci je vyvoln konstruktor Pklad: ukazatel = new complex; Alokace pol: new T[dimenze] alokuje pam pro pole pouije T::operator new[](), pokud je definovn nen-li pouije ::operator new[]() pi chyb vyvol vjimku bad_alloc vol se implicitn konstruktor na kad prvek pole v rostoucm poad index Poznmka: mus bt uvedeny vechny rozmry pole, prvn rozmr nemus bt konstantn vraz

Pklad: T *pt = new T[10]; // pole 10 objekt Uvolnn pamti vol destruktory v obrcenm poad uvoln pam (T::operator delete() nebo ::operator delete(), ppadn varianta s delete[] pro pole) Pklad: delete ukazatel; // ru objekt delete [] pt; // ru pole Speciln alokace pamti

Opertor new (nkdy i delete) me mt vce parametr. Toho se vyuv napklad pro alokaci na konkrtn adresu. new mus mt prvn parametr typu size_t delete mus mt prvn parametr typu void*

Pklad: new T vol operator new(sizeof(T)) new(adr) T operator new(sizeof(T),adr) new T[5] operator new[](sizeof(T)*5 + x) new(2) T[5] operator new[](sizeof(T)*5 + y, 2) (x a y jsou implementac definovan hodnoty) Pklad: T *p = new(nothrow) T; if(p==0) error("mlo pamti"); // ... delete p; Definovn opertor new a delete pro tdy Pro tdu T lze definovat funkce: void * T::operator new(size_t); // objekty void * T::operator new[](size_t); // pole objekt void T::operator delete(void* ptr); void T::operator delete[](void* ptr); Nejsou-li ve uveden operace definovny, pouij se globln opertory. Pklad: class X { public: void * operator new (size_t s) ; void operator delete (void* ptr) ; }; void * X::operator new (size_t s) { char* ptr = new char[s]; // vol standardn new // ...

return static_cast<void*>(ptr); } void X::operator delete (void* ptr) { delete[] static_cast<char*>(ptr); // ::delete } Konstruktory speciln metody pro inicializaci objekt pi vzniku nesm bt static ani virtual lze definovat vce konstruktor (viz. petovn funkc) jsou volny implicitn pi vytven objekt lze je volat na const a volatile objekty specifikac private lze zakzat vytven objekt nelze zskat adresu konstruktoru Pklad: class X { int i; public: X(): i(0) {} // implicitn konstruktor (def) X(int); // konstruktor s parametrem int X(const X&); // koprovac konstruktor }; X o; // vol se X::X() X o2(55); // X::X(int) X o2 = 55; // X::X(int) a X::X(const X&) X o3(o2); // X::X(const X&) X *px = new X; // X::X() X *px2 = new X(666); // X::X(int) Implicitn vytven metod Peklada vytvo automaticky implicitn konstruktor X::X() koprovac konstruktor X::X(const X&) opertor piazen X::operator = (const X&) destruktor X::~X() pokud tyto metody nejsou definovny explicitn. Vytvoen metody jsou vdy public. Vytvoen operace se chovaj podobn jako odpovdajc operace se strukturami v jazyku C. To nkdy (typicky u td obsahujcch ukazatel) nevyhovuje poadavkm - v takovm ppad je musme definovat explicitn a to nejlpe vechny.

Poznmka: Pokud m tda sloky, kter se mus inicializovat (reference), nebo nemaj dostupn potebn operace, je program chybn vytvoen.

Poznmka: Implicitn konstruktor nen vytvoen, pokud je definovn jakkoli jin (ne koprovac) konstruktor.

Koprovac konstruktor m jeden parametr typu const X& (nebo X&) pokud je vytvoen pekladaem, kopruje objekty po slokch (jejich koprovacm konstruktorem) X::X(const X & o): s1(o.s1), s2(o.s2) {} je voln pi vzniku objektu koprovnm: deklarace s inicializac jinm objektem pedvn parametru hodnotou vracen hodnoty z funkce vyvoln a zpracovn vjimek Pklad: X f(X p) { X a; // implicitn konstruktor X b(a); // koprovac konstruktor return a; // koprovac konstruktor f(a); // koprovac konstruktor } Poznmka: Pozor - nezamovat s opertorem piazen

Poznmka: monosti optimalizace Inicializace vnoench objekt konstruktory vnoench objekt se volaj automaticky ped provedenm tla konstruktoru tdy poad voln je dno jejich poadm v definici tdy ppadn parametry lze pedat explicitn - viz pklad Pklad: class X { complex c1; complex c2;

public: X() {} // implicitn konstruktory c1 a c2 X(double a) : c2(a), c1(5) {} // poad c1 c2 }; Poznmka: Pozor na poad voln konstruktor c1 a c2

Poznmka: Pokud peklada vytv konstruktor, provede v nm inicializaci vnoench objekt implicitnmi konstruktory (pokud nejsou uvedeny v seznamu inicializac).

Inicializace pole objekt konstruktory pro elementy pole jsou volny v rostoucm poad index X pole[10]; // X::X() X *ptr = new X[10]; // X::X() X p[10] = { X(1), X(2), }; // X::X(const X&), opt

Inicializace doasnch objekt Peklada me vytvet doasn objekty implicitn (ve vrazech, inicializaci referenc, ...) explicitn zpisem: X(22); // pouije se X::X(int) ^^^^ funguje jako konverze z int na X Poznmka: Implicitn konstruktor je kad konstruktor, kter lze zavolat bez parametr. Me bt pouze jeden pro jednu tdu. Destruktory jmno je sloeno ze znaku ~ (tilda) a jmna tdy je automaticky vyvoln kdy kon rozsah platnosti objektu (konec bloku, ruen nadazenho objektu, konec programu, ...) nesm mt parametry a nesm vracet hodnotu (je vdy pouze jeden pro jednu tdu) me bt virtuln (nkdy mus bt virtuln) me bt implicitn generovn pekladaem X::~X() {} // destruktor pro tdu X

destruktory vnoench objekt jsou volny v pesn obrcenm poad ne jim odpovdajc konstruktory u pol se volaj v klesajcm poad index Poznmky: kon-li rozsah platnosti ukazatele na objekt, objekt se neru (zruen provede pouze opertor delete) destruktor lze ve specilnch ppadech volat explicitn pouitm pln kvalifikovanho jmna: X *p; p->X::~X(); // destrukce bez uvolnn pamti destruktory polymorfnch td maj bt virtuln Ruen doasnch objekt Doasn objekty jsou automaticky rueny vdy v obrcenm poad jejich vzniku: na konci vrazu ve kterm vznikly jde-li o inicializaci, potom a po dokonen inicializace odkazuje-li se na n reference, pak na konci bloku ve kterm vznikly nebo pi zniku reference (co nastane dve) na konci konstruktoru v jeho inicializan sekci vznikly na konci funkce v ppad jejich vzniku v pkazu return Konverze pouvaj se pro zmnu typu vrazu standardn konverze (definovan jazykem) uivatelsk konverze (definovan v programu) Uivatelsk konverze: lze specifikovat pomoc: konverznch konstruktor (typ tda) konstruktory, kter lze volat s jednm argumentem specifikace explicit zabrn implicitnmu pouit konverznch opertor (tda typ) metody pojmenovan operator T nemaj nvratov typ a jsou bez parametr tyto opertory se dd a mohou bt virtuln Jsou aplikovny jen kdy jsou jednoznan a pstupn. Ke kontrole jednoznanosti dochz jet ped kontrolou pstupovch prv. Poznmka: Implicitn me bt aplikovna pouze jedna uivatelsk konverze (tj. neprovede se konverze pes pomocn typ A B C, kdy neexistuje pmo A C)

Pklad: konverze class U { }; class T { public: T(int); // int --> T T(char *, int =0); // char* --> T explicit T(U); // explicitn U --> T operator int(); // T --> int }; void f(T p) { U o; T a(1); T b = "text"; // b = T("text",0) T c(o); // OK: explicitn T d = o; // chyba: implicitn konverze b = 5; // b = T(5) b = o; // chyba: implicitn konverze b = T(o); // OK: U --> T int i = a; // T --> int implicitn konverze i = int(a); // T --> int i = static_cast<int>(a); // T --> int i = (int)a; // T --> int (zastaral) if(i<1) f(66); // int --> T } Petovn opertor pisouzen vce vznam jednomu symbolu rozlien operac se provd podle kontextu zpehlednn zpisu program lze petovat vechny opertory C++ krom nsledujcch: . .* :: ?: a preprocesorovch # ## nelze zmnit poet operand opertor ani jejich prioritu a pravidla pro asociativitu alespo jeden parametr mus bt tda nebo vet nkter opertory jsou definovny implicitn: piazen (operator =) zskn adresy objektu (unrn &) vbr lenu struktury (.) je vhodn dodrovat jist pravidla: zachovvat smysl opertor pokud vestavn operace (napklad int + int) nemn dn operand, nemaj to dlat ani peten varianty Opertory je mon definovat jako (nestatick) metody, nebo jako funkce:

vraz jako metoda jako funkce @a (a).operator@ () operator@ (a) a@b (a).operator@ (b) operator@ (a, b) a=b (a).operator= (b) a[b] (a).operator[](b) a-> (a).operator->() a@ (a).operator@ (0) operator@ (a, 0) Peklada vdy pevede zpis opertoru na voln odpovdajc opertorov funkce nebo metody. Je-li deklarovno oboj, je aplikovno standardn testovn argument pro een nejednoznanosti. Petovn unrnch opertor dv mon formy deklarace: nestatick metoda bez parametr funkce (ne metoda) s jednm parametrem Kdy @ reprezentuje unrn opertor, potom @x a x@ me bt oboj interpretovno bu jako x.operator @() nebo jako operator @(x), podle deklarace. Prefixov a postfixov opertory ++ -- lze rozliit pomoc dodatenho fiktivnho parametru opertoru: class Y { // ... public: Y operator ++() { /* inkrementace ++x */ } Y operator ++(int) { /* inkrementace x++ */ } }; Y x,y; y = ++x; // vol Y::operator ++() y = x++; // vol Y::operator ++(int) Petovn binrnch opertor dv mon formy deklarace binrnho opertoru: nestatick metoda s jednm parametrem funkce (ne metoda) se dvma parametry x@y je interpretovno bu jako x.operator @(y) nebo jako operator @(x,y) Pklad: peten opertoru + pro tdu Complex

class Complex { double re, im; public: Complex(): re(0), im(0) {} Complex(double r, double i=0): re(r), im(i) {} friend Complex operator +(Complex c1, Complex c2); // funkce e problm: 1 + Complex(1,2) }; Complex operator +(Complex c1, Complex c2) { return Complex(c1.re + c2.re, c1.im + c2.im); } Complex a(0,1), b(1,0), c; c = a + b; // peten opertor + c = operator+(a,b); // opertorov funkce Petovn opertoru piazen class String { // odkaz na data public: String & operator = (const String & str) { if(&str!=this) // piazen dat return *this; } // ... }; nen-li definovn koprovac operator =, peklada jej vytvo jako piazen po jednotlivch slokch tdy nedd se (na rozdl od ostatnch opertorovch funkc) me bt virtuln Poznmky: pi implementaci je teba uvaovat i monost piazen typu a = a specifikac private meme zabrnit piazovn objekt (Jestlie nedefinujeme ani tlo opertoru, bude i pi jeho ppadnm pouit uvnit tdy hlena chyba pi sestavovn programu.) Petovn opertoru voln funkce operator()mus bt nestatick metoda me mt libovoln poet parametr Napklad voln x(a1,a2), kde x je objekt je interpretovno jako x.operator()(a1,a2).

Pouit: funkn objekty v STL

Petovn opertoru indexovn binrn opertor indexovn a[b] je interpretovn jako a.operator[](b) me bt definovn pouze jako nestatick metoda vcensobn indexovn: pomocn tda (vce td) s opertorem indexovn opertor indexovn zkladn tdy vrac referenci na objekt pomocn tdy pomocn objekt je opt indexovateln vsledkem mus bt reference na prvek vcerozmrnho pole Petovn pstupovho opertoru -> Pstupov opertor -> je povaovn za unrn opertor a mus bt definovn jako nestatick metoda. Vraz x->m, je interpretovn jako (x.operator->())->m, take funkce operator->() mus vracet bu ukazatel na objekt tdy nebo objekt tdy pro kterou je opertor -> definovn.

Omezen pro doasn objekty C++ nedovol volat metody pro doasn promnn (vytvoen napklad implicitn konverz).

Pklad: class X { int i; public: X(int _i=0) : i(_i) {} X operator + (const X &b) const { return X(i + b.i); } }; X a, b; a = 5 + b; // nelze Petovn funkc monost deklarovat vce funkc se stejnm jmnem

rozliuj se podle potu a typu argument pi voln souvislost s typovou kontrolou Pklad: void print(double); void print(long); void F() { print(1L); // tiskne long print(1.0); // tiskne double print(1); // chyba: nejednoznanost } pravidla pro vyhledn funkc problm nejednoznanosti nelze rozliit jen podle nvratovho typu opertory pouvaj jin pravidla pstupov prva se berou v vahu a po kontrole jednoznanosti Poznmka: typedef nedefinuje samostatn typ

Pravidla pro prohledvn prostor jmen Pokud v programu pouijeme funkci f s ppadnmi parametry, bude se hledat odpovdajc mnoina kandidtskch funkc takto: pro vyhledvn funkce v prostoru jmen se pouije pouze jmno funkce v hierarchii prostor jmen hled se od aktulnho smrem ke globlnmu (pro tento el je tda prostorem jmen) najde-li se funkce stejnho jmna, provd se rozlien funkce podle typu a potu parametr ("viable functions" - viz dle) nenajde-li se odpovdajc funkce hls se chyba Poznmka: void f(int); void f(const int); // chyba - nelze rozliit void g(int*); void g(const int*); // ukazatele lze rozliit Pravidla pro vbr odpovdajc funkce Z mnoiny kandidtskch funkc se vyberou "viable" funkce podle:

potu argument monch konverz argument Z tchto funkc se vybere nejlpe vyhovujc funkce piblin podle nsledujcch pravidel: Shoda typ (bez konverz - krom nevyhnutelnch: pole ukazatel, jmno funkce ukazatel na funkci, T const T) Shoda typ po konverzi na int (char int, short int, atd.) a float double Shoda po proveden standardnch konverz (int double, odvozen-tda * bzov-tda *) Shoda po proveden uivatelem definovanch konverz Pouit nespecifikovanho potu argument (...) Nalezen dvou a vce stejn dobrch funkc vede k chyb - jde o nejednoznanost (ambiguity).

Poznmka: pravidla pro generick funkce

Pklad: nejednoznanost vbru peten funkce/opertoru void f(int); // globln funkce class T { public: T::T(int); // konverze int ---> T operator int(); // konverze T ---> int void f(long); // --- kandidt 1 void f(double); // --- kandidt 2 void m() { f(5); // chyba --- nejednoznanost ::f(5); // globln funkce } friend int operator + (T x, T y); }; T x, y; x = 5 + y; // 5+int(y) nebo T(5)+y ??? Mon een: definice dal metody void f(int) zkaz jedn z konverz, ppadn specifikace explicit u konstruktoru Vstup/vstupn operace s vyuitm stream stream (proud) - objekt, zobecnn pojmu soubor #include <iostream> #include <fstream>

tdy ios, istream, ostream, iostream, ifstream, ofstream, fstream a dal standardn streamy: cin, cout, cerr pouit opertor << a >> pro vstup/vstupn operace (jsou definovny pro vechny vestavn typy) monost doplovat opertory << a >> pro uivatelem definovan typy (bez zsahu do implementace stream) pozor na priority opertor! Definice a pouit vstup/vstupnch operac Zpis cerr << "x=" << x << '\n'; je ekvivalentn zpisu ((cerr.operator<<("x=")).operator<<(x)).operator<<('\n'); a tiskne x zpsobem, kter je definovn pro typ objektu x int x = 123; tiskne x=123 complex x(1,2.4) tiskne x=(1,2.4) Pklad: Definice vstup/vstupnch opertor // vstupn formt: (f,f) ostream& operator<< (ostream& s, Complex z) { return s <<'('<< real(z) <<','<< imag(z) <<')'; } // vstupn formty: f (f) (f,f) istream& operator>>(istream& s, Complex& a) { double re = 0, im = 0; char c = 0; s >> c; // te prvn nemezerov znak if( c == '(' ) { s >> re >> c; if( c == ',' ) s >> im >> c; if( c != ')' ) s.clear(ios::badbit); // nastav stav } else { s.putback(c); s >> re; } if( s ) a = Complex(re,im); return s; } Manipultory flush vyprzdn vyrovnvac pam

ws hex endl Pklad:

pesko mezery (oddlovae) pouije estnctkovou notaci nov dek

cout << x << flush << y << flush ; cin >> ws >> x; cout << 1234 << hex << 1234 << endl ; Manipultory s parametry setfill(char) vplov znak setprecision(int) pesnost setw(int) ka tisku Pklad: cout <<setw(4)<<setfill('#')<< 33 << "+" << 22 ; vstup: ##33+22 Poznmka: nastaven manipultoru setw() plat pouze pro jednu tisknutou poloku, ostatn manipultory plat a do dal zmny Prce se soubory Pro prci s diskovmi soubory jsou definovny tdy fstream, ifstream a ofstream. Navzn streamu na soubor lze provst pi vzniku objektu nebo volnm metody open.

Pklad: #include <fstream> ifstream from("soubor1.txt"); ofstream to("soubor2.txt"); fstream f("soubor3.txt", ios::in | ios::out); char ch; // me bt char (EOF se testuje jinak) while(from.get(ch)) // kopie souboru (pomal!) to.put(ch); if(!from.eof() || to.bad()) // test chyb error("chyba!");

Poznmka: Ddinost

Kombinace stream a C-funkc (printf,...) me vst k problmm v poad vstup.

klov koncept OOP odvozovn novch td z ji existujcch bzov a odvozen (nslednick, derivovan) tdy jednoduch a nsobn ddinost sdlen kdu - znovupouitelnost (reusability) sdlen rozhran - polymorfismus class C : public A { // tda C dd tdu A // nov poloky, nov a modifikovan metody }; tda dd vechny datov sloky bzov tdy a bn metody (ne konstruktory, destruktor, operator=) ze zddnch len tdy lze pouvat pouze ty co byly public nebo protected lze ovlivovat pstupov prva zddnch poloek Ddn private, public, protected je mon specifikovat pstupov prva u zddnch prvk: class D : public B1, protected B2, B3 {}; implicitn je private u class D, a public u struct D odvozen tda dd atributy pstupu takto: public bzov tda public i protected zstv nezmnno protected bzov tda public a protected bude protected private bzov tda vechny prvky budou private v odvozen td Lze ovlivovat pstupov prva i u jednotlivch zddnch poloek: lze je pouze obnovit, v ppad, e byly zpsnny ddnm pouit using deklarace (viz. prostory jmen) Poad voln konstruktor a ddinost Konstruktor odvozen tdy je sloen z: voln konstruktoru bzov tdy, voln ppadnch konstruktor loklnch objekt (v poad jak jsou uvedeny ve td) a nakonec se provd tlo konstruktoru. Pedn parametr konstruktorm je mon za dvojtekou v seznamu inicializtor konstruktoru (viz pklad).

Pklad:

s chybou

class base { int x; public: base (int i): x(i) {} }; class derived : base { int a; public: derived(int i) : a(i*10), base(a) {} // chyba! // do base je pedna neinicializovan hodnota a ! // konstruktor provede: // 1) base::base(a) neinicializovan hodnota a // 2) a(i*10) inicializace a (pozd) }; Pklad: class base { //.... public: base(int i=0) { } }; class derived : base { complex x; // vnoen objekty complex y; int z; public: derived() : x(2,1) { f(); } // konstruktor provede: // 1) base::base() // 2) complex::complex(2,1) pro x // 3) complex::complex() pro y // z nen inicializovno = nekorektn kd // 4) f() }; Poznmka: Destruktory jsou vdy volny v pesn obrcenm poad ne jim odpovdajc konstruktory. Virtuln metody metody oznaen klovm slovem virtual

virtuln metody umouj polymorfismus: v bzov td definuj rozhran spolen vem odvozenm tdm v odvozench tdch je definovna odpovdajc implementace metod pi pouit spolenho rozhran nen teba znt pesn tdu objektu (jet nemus existovat) a pesto je pi bhu programu zajitno voln odpovdajcch metod - tzv. pozdn vazba (late binding). Polymorfn voln m typicky tvar: ukazatel->vmetoda() lze definovat virtuln destruktory, kter umouj korektn ruit prvky datovch struktur Poznmka: Virtuln metody se mohou liit ve vracenm typu jestlie spluj nsledujc podmnky: pedefinovan virtuln metoda vrac ukazatel nebo referenci na bzovou tdu pepisujc funkce vrac ukazatel nebo referenci na odvozenou tdu Pklad: class B { public: virtual B* vf1() { cout << "B"; return this; } void f() { cout << "B"; } }; class C : public B { public: C* vf1() { cout << "C"; return this; } // virtual void f() { cout << "C"; } }; class D : public B { public: virtual D* vf1() { cout << "D"; return this; } void f() { cout << "D"; } }; int main() { B b; C c; D d; b.f(); c.f(); d.f(); // "B" - obyejn metoda // "C" // "D"

b.vf1(); // "B" - stejn

c.vf1(); // "C" d.vf1(); // "D" B *bp = &c;// uk. na bzovou tdu - rozhran bp->vf1(); // "C"-podle skuten tdy objektu c bp->f(); // "B"-podle typu ukazatele bp bp = &d; // ukazuje na objekt tdy D bp->vf1(); // "D"-podle skuten tdy objektu d bp->f(); // "B"-podle typu ukazatele bp } Poznmka: Pro pochopen virtulnch metod je vhodn vdt, jak je uveden mechanismus obvykle implementovn: Kad tda s virtulnmi metodami m tzv. tabulku virtulnch metod (VMT - Virtual Method Table), ve kter jsou odkazy na vechny virtuln metody tdy. Pi ddn (pi pekladu) se pevezme obsah VMT bzov tdy, odkazy na virtuln metody, kter byly pedefinovny se nahrad novmi a na konec VMT se dopln odkazy na ppadn nov virtuln metody. Kad objekt tdy s virtulnmi metodami obsahuje odkaz na tabulku virtulnch metod Polymorfn voln pouije ukazatel v objektu, vybere odpovdajc poloku z VMT a zavol metodu. Pklad implementace polymorfismu class B { public: virtual void vf1(); // rozhran // ... } b; class C : public B { // mus bt public public: virtual void vf1(); // ... } c; B *bp = &c; // polymorfn rozhran: bp->vf1()

Volme-li virtuln metodu, je volna nepmo pes VMT - to umouje volat odpovdajc metodu i kdy tda objektu nen pekladai znma (mme pouze ukazatel na objekt bzov tdy). Informace o td objektu (s virtulnmi metodami) je vlastn ukryta v odkazu na VMT tto tdy, kter je soust kadho objektu.

Mme-li ukazatel na objekt bzov tdy B, meme do nj piadit ukazatel na tdu z n odvozenou. Pomoc tohoto ukazatele meme potom volat metody definovan ve td B. Pokud jsou tyto metody virtuln, budou volny metody, kter pslu skuten td objektu na kter se ukazuje. Meme definovat bzovou tdu tak, aby poskytovala vhodn rozhran pro celou skupinu odvozench td (kter mohou bt definovny pozdji) a pracovat potom s objekty (pes toto rozhran) nezvisle na jejich td. Pkladem me bt bzov tda PrvekSeznamu, kter definuje obecn vlastnosti elementu seznamu, se kterm um pracovat tda Seznam. Potom lze ze tdy PrvekSeznamu odvodit jakoukoli novou tdu a jej objekty ukldat do seznamu, i kdy vechny jejich vlastnosti nebyly jet znmy v dob psan implementace tdy Seznam (bylo znmo pouze rozhran definovan tdou PrvekSeznamu).

Poznmka:

Polymorfn tdy by vdy mly mt virtuln destruktor.

Poznmka: Pi provdn konstruktor (a destruktor) se mechanismus voln virtulnch funkc neuplatuje - konstruktor vdy nastav svoji tabulku virtulnch metod. Dvodem jsou mon problmy pi voln virtuln metody, kter pracuje s jet neinicializovanmi slokami objektu.

Pklad: class A { public: A() { m(this); } void m(A *bp) { bp->V(); } virtual void V() { cout << 'A' ; } }; class B : public A { int i; public: B(): i(9) { m(this); } virtual void V() { cout << 'B' << i << ' ' ; } }; int main() { B b; // vytiskne AB9 a nikoli B?B9 A *bp = &b; bp->V(); // vytiskne B9 } ist virtuln metody (pure virtual functions)

virtuln metoda nemus bt definovna. Potom mus bt deklarovna jako tzv. ist virtuln metoda: class B { virtual void pvf(int) = 0; }; ve vech odvozench tdch se tato metoda dd jako ist virtuln, dokud nen definovna. jsou vhodn pro definovn rozhran v bzovch tdch Poznmka: Ve specilnch ppadech lze doplnit definici

Abstraktn tdy tdy s minimln jednou ist virtuln metodou pouiteln pouze jako bzov tdy pi ddn nelze vytvet dn objekty lze pout ukazatel/referenci na abstraktn tdu Pklad: class shape { // abstraktn tda - obrazec point center; public: // definice rozhran virtual void rotate(int) =0; virtual void move(int,int) =0; virtual void draw() =0; //... }; class Circle : public shape { // krunice int radius; public: virtual void rotate(int) {} // definice virtual void move(int,int); virtual void draw(); //... }; shape s; // nelze vytvoit objekt - chyba Circle c; // tda Circle nen abstraktn shape *sp=&c; // ukazatel na abstraktn tdu sp->rotate(); // voln pes polymorfn rozhran Opertor typeid

opertor pro zskvn informac o typu objektu za bhu programu: typeid ( vraz ) typeid ( typ ) peklada generuje typov informace a ty jsou dostupn pi bhu aplikace (RTTI - run-time type information) Vsledek typeid(vraz) je typu const type_info& type_info reprezentuje popis typu vrazu vraz je reference na polymorfn typ nebo *ukazatel (je-li ukazatel==0, pak dojde k vjimce bad_typeid) class X { // polymorfn tda // ... virtual void f(); }; // ... void g(X *p) { typeid(p); // X* typeid(*p); // tda X nebo odvozen } Tda type_info je deklarovna v <typeinfo.h> napklad takto: class type_info { public: // rozhran: virtual ~type_info(); int operator==(const type_info&) const; int operator!=(const type_info&) const; int before(const type_info&) const; const char *name() const; private: // zakzan operace: type_info(const type_info&); type_info & operator= (const type_info&); // ... implementan zvisl reprezentace }; elem before je monost adit objekty type_info. Nen definovn dn vztah mezi ddinost a before.

Poznmka: Metoda name vrac etzec jednoznan reprezentujc typ, kter je implementan zvisl (nemus to bt jmno typu).

Opertory pro petypovn const_cast < TYP > ( vraz ) static_cast < TYP > ( vraz ) reinterpret_cast < TYP > ( vraz ) dynamic_cast < TYP > ( vraz ) doplnk k TYP(vraz) nebo (TYP)vraz Opertory static_cast, reinterpret_cast, const_cast pedstavuj specifick petypovn - vyjaduj tot co (TYP)vraz, krom petypovn na private bzovou tdu. Jejich elem je explicitn zvraznit mysl petypovn. const_cast<T>(e) petypuje e na typ T pesn jako (T)e za pedpokladu, e T a typ vrazu e se li pouze v const a volatile modifiktorech a jde o ukazatel nebo referenci, jinak dojde k chyb. Ostatn opertory respektuj 'konstantnost' - nemohou ji mnit. static_cast<T>(e) petypuje e na typ T pokud: meme deklarovat doasnou promnnou T pom(e); typ T je void jde o petypovn reference/ukazatele na bzovou tdu na referenci/ukazatel na odvozenou tdu existuje inverzn standardn konverze, intenum, void*Cls*, D::*pB::*p jinak dojde k chyb. reinterpret_cast<T>(e) petypuje e na typ T kdy jde o konverzi ukazatel na: celoseln typ nebo enum a naopak funkce rznho typu objekty rznho typu (i reference) leny td rznho typu jinak dojde k chyb. Ukazatele a reference uvauje jako nepln typy (vztahy bzov/odvozen tda neovlivn vznam petypovn). Vsledky reinterpret_cast se obvykle mus dle petypovvat na svj originln typ, aby byly pouiteln.

Pklad: void f(char *p) { *p = 'x'; } typedef void (*FP) (const char*); int main() { FP p = reinterpret_cast<FP>(&f); p("text"); // pozor - nemus fungovat (coredump) int *x=static_cast<int*>(malloc(9*sizeof(int))); long *y = reinterpret_cast<long*>(0x1FF0);

// long *z = static_cast<long*>(0x1FF0); // chyba } Poznmka: Minimalizovat pouit tchto opertor dynamic_cast<T>(v) je speciln petypovn s kontrolou pi bhu programu. Typ T mus bt ukazatel nebo reference na tdu nebo void*. Je-li T ukazatel a v je ukazatel na odvozenou tdu, potom je vsledkem ukazatel na uniktn podobjekt. Je-li T reference a v objekt tdy odvozen z T, potom je vsledkem reference na uniktn podobjekt. Kdy T je typ void*, potom v mus bt ukazatel a vsledek je ukazatel na kompletn objekt. Jinak v mus bt ukazatel nebo reference na polymorfn typ a je provedena kontrola za bhu programu, zda v me bt konvertovn na typ T. Kdy ne, operace skon nespn - vsledn hodnota po petypovn bude 0, v ppad reference je vyvolna vjimka bad_cast. Pklad: (peklada mus podporovat RTTI) class B { /* min. jedna virtuln metoda */ }; class D : public B { /* ... */ }; B *pb1 = new B; B *pb2 = new D; D *pd1 = dynamic_cast<D*>(pb1); // 0 (nelze) D *pd2 = dynamic_cast<D*>(pb2); // uk. na objekt D ablony ablony (templates) umouj generick programovn typy parametrizovan jinm typem klov slova: template, typename, export ablony funkc, ablony td instanciace, specializace a sten specializace Pklady: deklarace ablon template<class R, class T> R funkce(T); template<class T> class Vector; Pklady: pouit ablon, instanciace int i = funkce<int>(3.14); double d = funkce<double,double>(3); Vector<int> vec; Vector< Vector<int> > vec2; // pozor na >>

std::map<std::string,int> m; std::basic_string<unsigned char> us; Parametry ablon ablony lze parametrizovat: typem - napklad class T nebo typename T hodnotou - napklad int i Lze pout pouze celoseln typy, vet, ukazatel/referenci na objekt/funkci nebo ukazatel na len tdy. Odpovdajc argument mus bt konstantn vraz. ablonou - napklad template<class T> class K ablona me mt vce parametr: template< class T, T v, class U > class S; Lze definovat implicitn hodnoty parametr ablon: template< class T, int c = 10 > class S; template< template<class T> class p = S > class X; template< class T, int size = 256 > class Buffer { /*...*/ }; Buffer<long,1024> buf1; ablony funkc template <class T> T max(T x, T y) { // definice return (x>y)?x:y; } Pi prvnm pouit max peklada generuje odpovdajc funkci (instanci ablony) podle typu argument voln funkce. MyClass a, b; int j = max(5,0); // dedukce: max<int>(5,0) MyClass m = max(a,b); // max<MyClass>(a,b) Omezen: ablonu max lze pout pro libovoln typ, kter m definovn operator >, koprovac konstruktor a destruktor. Je mon definovat dal funkce max, napklad: const char *max(const char *x, const char *y) { return (strcmp(x,y)>0) ? x : y; } const char *s = max("a", "aaa"); Potom m tato funkce pednost ped ablonou.

Pro generick funkce se neprovd dn implicitn konverze argument (pouze triviln: poleukazatel, ...): void f(int i, char c) { max(i,i); // vol max(int,int) max(c,c); // vol max(char,char) max(i,c); // nen funkce max(int,char) =chyba! max(c,i); // nen max(char,int) =chyba! } Pokud bychom pedem explicitn deklarovali funkci int max(int,int); k chyb by nedolo, protoe v takovm ppad se provedou rozen char na int. Poznmka: Parametry ablony lze dedukovat pouze podle argument voln funkce. ablony td

Pklad: ablona Vector template<class T> class Vector { T * data; int size; public: Vector(int); //... }; // definice metody - konstruktoru: template<class T> Vector<T>::Vector(int n) { //... } int main() { Vector<int> x(5); // generuje instanci vektoru for(int i = 0; i<5; i++) x[i] = i; //... } Specializace ablon Lze explicitn definovat speciln ppady: template<class T> class Vector<T*> { /*...*/ };

template<> class Vector<char*> { /*...*/ }; template<class T> T* max(T*a, T*b) { /*...*/ } template<> char* max<char*>(char*a, char*b); template<> int* max<>(int*a, int*b) { /*...*/ } template<> void* max(void*a, void*b) { /*...*/ } specializace mus nsledovat a po definici obecn ablony pro speciln ppady zabrn automatickmu vytven instance z obecn ablony template<class T> class Vector. pouije se vdy nejvce specializovan ppad: Vector<int> v1; // - obecn ablona <T> Vector<int*> v2; // - sten specializace <T*> Vector<char*> v3; // - specializace <char*> Identifiktor Vector vtinou nelze pout bez specifikace parametru <> (krom nkterch ppad uvnit popisu ablony). Pklad: Seznam s typovou kontrolou Problmem nsledujc implementace seznamu je nemonost typov kontroly vkldanch prvk. class Glist { public: void insert(void *); void *get(); // ... }; Doplnn typov kontroly doshneme takto: template<class T> class List : public Glist { public: void insert(T *t) { Glist::insert(t); } T *get() { return (T *)Glist::get(); } // ... }; Vyuit tohoto pstupu zkracuje kd programu a je pitom velmi efektivn (v pedchozm ppad typov kontrola nic nestoj, protoe na petypovn se negeneruje dn kd a metody jsou inline). Poznmky ablony lze definovat bu v hlavikovch souborech, nebo s vyuitm export pouze deklarovat a definici peloit jako samostatn moduly (ne vechny pekladae to podporuj). Kad instance ablony m svoje statick prvky. Je mon definovat ablony metod. Pro specifikaci, e jde o jmno typu zskanho z parametru ablony se pouv klov slovo typename: template<class T>

class X { typedef typename T::TypeU U; // vnoen typ public: int m(U o); } Explicitn instanciace m tvar template deklarace: template class Vector<int>; Knihovna STL (Standard Template Library), je cel postavena na vyuit ablon. Tato knihovna tvo zklad standardn knihovny jazyka ISO C++. Pouit ablon pin zcela nov pstupy k programovn - generick programovn. Vdy, kdy potebujeme mnoho tm stejnch vc, je vhodn pout generick tdy. Obsluha vjimek Obsluha chyb vznikajcch pi bhu programu Mon pstupy: ukonen programu vrcen hodnoty, kter reprezentuje chybu (nap. fopen) vrcen legln hodnoty a ponechn programu v nesprvnm stavu (nevyhovujc) voln speciln funkce, kter chyby oet (nap. matherr, terminate) Jazyk ISO C++ poskytuje prostedky pro strukturovan een vjimench situac. Klov slova: try - vymezen obsluhovan oblasti throw - generovn vjimky catch - zachycen vjimky Pklad: tda Vector - pole s kontrolou indexu class Vector { int *p; int sz; public: class Range {}; // typ vjimky int &operator[] (int i) { if(i>=0 && i<sz) return p[i]; else throw Range(); // vznik vjimky } // ... }; void f(Vector &v) { // ...

try { // "hldan" oblast v[x] = 5; f2(); // ... } catch(Vector::Range) { // obsluha vjimky Vector::Range // tento kd se provede jen kdy se // v sekci try vyskytne index mimo rozsah } // ... } Rozlien vjimek Pkaz catch me mt parametr typu T, const T, T&, const T&. Takov pkaz zachyt vjimky: stejnho typu typu pro kter je T public bzovou tdou je-li T ukazatel, vjimka mus bt typu ukazatel, kter lze zkonvertovat standardn konverz na T Pklad: tda Vector - pole s kontrolou indexu a rozmru class Vector { int *p; int sz; public: enum { max = 32000 }; class Range {}; // vjimka - rozsah indexu class Size {}; // vjimka - chybn velikost Vector(int size) { if(size<0 || size>max) throw Size(); // ... } int &operator[] (int i); }; void f() { try { use_vectors(); // pouit tdy Vector } catch(Vector::Range) { // obsluha vjimky Vector::Range } catch(Vector::Size) { // obsluha vjimky Vector::Size }

} Poznmka: Funkce f nemus obsluhovat vechny mon vjimky - jejich zpracovn je mon provst ve funkcch, kter ji zavolaly.

Poznmka: Obsluhu vjimek lze vnoovat, tj. v obsluze vjimky me bt dal blok try. Vjimky s parametry Vjimky mohou obsahovat uiten informace

Pklad: tda Vector - s pednm hodnoty indexu class Vector { // ... public: struct Range { // tda vjimky int index; // hodnota chybnho indexu Range(int i): index(i) {} }; int &operator[] (int i) { if(i>=0 && i<sz) return p[i]; throw Range(i); // pedn hodnoty } // .... }; void f(Vector &v) try { // 'hldan' oblast - cel funkce v[x] = 5; // .... } catch(Vector::Range r) { cerr << "chybn index" << r.index << '\n' ; // ... } Sdruovn vjimek

Pklad: odvozen vjimky class Matherr {}; // bzov tda class Overflow: public Matherr {}; // peteen class Underflow: public Matherr {}; // podteen

class Zerodivide: public Matherr {}; // dlen nulou void f() try { // ... } catch(Overflow) { // obsluha vjimek typu Overflow a odvozench } catch(Matherr) { // vechny ostatn odvozen z Matherr } Vyhodnocovn obsluhy vjimek probh v poad, ve kterm jsou uvedeny pkazy catch.

Poznmka: Vechny jet neobslouen vjimky je mono zpracovat v sekci catch(...) Pidlovn zdroj Tradin een: void use_file(const char *jmeno) { // pouit souboru FILE *f = fopen(jmeno,"r"); // oteven // pouit souboru f fclose(f); // uzaven } V ppad vskytu vjimky uvnit funkce je peskoen pkaz fclose a soubor zstane oteven! Triviln (a nevhodn) een: void use_file(const char *jmeno) { FILE *f = fopen(jmeno,"r"); try { // pouit souboru f } catch(...) { // pro vechny vjimky ... fclose(f); // uzave soubor throw; // znovu vyvol tut vjimku // (pole ji volajc funkci) } fclose(f); } een pidlovn zdroj zdroje ve form loklnch objekt: pidlen zdroje = inicializace (voln konstruktoru) automatick uvolnn (voln destruktoru)

Pklad: tda FilePtr, kter se chov jako FILE* class FilePtr { FILE *p; public: FilePtr(const char *name, const char *atr) { p = fopen(name,atr); } ~FilePtr() { fclose(p); } operator FILE*() { return p; } } void use_file(const char *jmeno) { FilePtr f(jmeno,"r"); // oteven souboru // pouit souboru f } // automatick uzaven souboru Konstruktory, destruktory a vjimky Pi vzniku vjimky v konstruktoru jsou volny destruktory vech objekt, jejich konstruktory byly bezchybn dokoneny.

Pklad: pidlovn pamti class X { int *p; public: X(int s) { p = new int[s]; init(); } ~X() { delete [] p; } // ... }; Pouit tto tdy nen vhodn, protoe pi vjimce vznikl v init() se nezavol destruktor, protoe nebyl kompletn dokonen konstruktor. Bezpen een: template<class T> class MemPtr { T *p; public: MemPtr(size_t s) { p = new T[s]; } ~MemPtr() { delete [] p; } operator T* () { return p; } }; class X {

MemPtr<int> cp; // ukazatel - objekt // ... public: X(int s): cp(s) { init(); } // ... }; Vjimka v init() nyn vdy vede ke korektnmu uvolnn pamti. Poznmka: std::auto_ptr<T> Specifikace rozhran vjimek ISO C++ dovoluje specifikaci mnoiny vjimek, kter mohou bt vyvolny, v prototypu funkce. Napklad: void f() throw (x2,x3); specifikuje, e funkce f me vyvolat vjimky x2 a x3 (a vechny odvozen), avak dn jin. Funkce void f() throw (x2,x3) { // kd funkce } je ekvivalentn funkci void f() try { // kd funkce } catch(x2) { throw; } // vjimka pokrauje catch(x3) { throw; } catch(...) { unexpected(); // chybov ukonen programu } Funkce bez specifikace me vyvolat jakoukoli vjimku int f(); // me vyvolat libovolnou vjimku Funkce, kter nebude vyvolvat dnou vjimku: int g() throw(); Specifikace vjimek nen soust typu funkce.

Poznmka: U virtuln metody mus mt vechny metody, kter ji pedefinovvaj v odvozench tdch, specifikaci stejnou nebo vce omezujc mon vjimky.

Poznmka: Do ukazatele na funkci, kter specifikuje vjimky, lze piadit ukazatel na funkci, kter m specifikaci stejnou nebo vce omezujc mon vjimky.

Neoekvan vjimky Neopatrn pouit specifikace vjimek vedou k voln funkce unexpected, co je obvykle nedouc. Tomu lze pedchzet pelivou organizac vjimek: napklad podsystm Y by ml mt vechny vjimky odvozen z bzov tdy Yerr. Je definovna funkce set_unexpected, kter mn vznam voln funkce unexpected typedef void(*PFV)(); PFV set_unexpected(PFV); class STC { PFV old; public: STC(PFV f) { old = set_unexpected(f); } ~STC() { set_unexpected(old); } }; void rethrow() { throw; } void g2() { STC xx(&rethrow); // unexpected() bude volat rethrow() g(); // pvodn funkce } Poznmky: pokud by se rethrow nevolalo z catch(...), dolo by k vyvoln funkce terminate unexpected se nikdy nevrac (mus vyvolat vjimku, nebo terminate()) Neobslouen vjimky nen-li vjimka obslouena dnm pkazem catch je implicitn volna funkce terminate, kter ukon program. Efekt voln terminate() lze pedefinovat funkc set_terminate: typedef void(*PFV)(); // ukazatel na funkci PFV set_terminate(PFV); Implicitn plat, e unexpected() vol terminate() a terminate() vol abort()

Poznmka:

pouit vjimek vede na vt kd, vlastn vyvoln vjimky je pomal

Standardn vjimky <exception>: class exception bze pro std vjimky class bad_exception <new>: class bad_alloc <typeinfo>: class bad_cast class bad_typeid <stdexcept>: class logic_error logick chyby: class domain_error class invalid_argument class length_error class out_of_range class runtime_error chyby pi bhu programu class range_error class overflow_error class underflow_error Vechny tyto tdy maj definovnu metodu virtual const char* what() const throw(); kter vrac etzec s popisem vjimky. Nsobn ddinost Ddn z nkolika bzovch td souasn: class C : public A, public B { // leny tdy };

hierarchie td:

objekt:

Poznmky: Poad td v deklaraci nen vznamn krom poad voln konstruktor, destruktor a uloen v pamti. Pozor na konverze ukazatel! Pouit nsobn ddinosti: lo + letadlo = hydropln Problmy nsobn ddinosti

Mon nejednoznanost: dv bzov tdy maj stejn pojmenovan len -- jejich pouit lze rozliit kvalifikac -- napklad A::i nebo B::i Ddit dvakrt tut tdu lze jen nepmo: class X { .... }; // bzov tda class A : X { .... }; class B : X { .... }; class C : A,B { .... }; Tda C obsahuje dv instance tdy X. Virtuln bze class X { .... }; class A : virtual X { .... }; class B : virtual X { .... }; class C : A,B { .... }; Tda C obsahuje pouze jednu instanci tdy X. Poad voln konstruktor a nsobn ddinost Konstruktory bzovch td jsou volny ped provedenm konstruktoru dan tdy v poad deklarace bzovch td v hlavice tdy. Konstruktory virtulnch bzovch td jsou vyvolny ped konstruktory nevirtulnch bzovch td (je-li jich vce volaj se v poad jejich uveden v deklaraci). Je-li v hierarchii td vce instanc te virtuln bzov tdy je jej konstruktor voln pouze jednou. Jsou-li instance bzov tdy virtuln i nevirtuln, potom je konstruktor voln jednou pro vechny instance virtuln a jednou pro kadou instanci nevirtuln -- destruktory jsou volny v pesn obrcenm poad ne jim odpovdajc konstruktory. Poznmka: Monost parametrizace konstruktoru virtuln bzov tdy X:

C::C(): X(1), A(2), B(3) { .... } Ukazatele na leny td Nejde o bn ukazatele, nelze na n aplikovat bn pravidla pro petypovn, nelze je konvertovat na void *

Pklad: Deklarace ukazatel na metody int (T::*p1)(); void (T::*const p2)(int) = &T::Metoda2; p1 = &T::Metoda1; // piazen Metoda mus bt kompatibiln s ukazatelem.

opertor prvn operand druh operand .* objekt tdy T nebo odvozen tdy ukazatel na len tdy T ->* ukazatel na objekt tdy T nebo odvozen ukazatel na len tdy T T objekt; T *ukazatel_na_objekt = &objekt; (objekt.*p1)(); (ukazatel_na_objekt->*p2)(parametr); Poznmka: Vzhledem k prioritm opertor je nutn pouvat zvorky.

Poznmky: Jestlie vsledkem opertoru .* nebo ->* je metoda, potom jej lze pout pouze jako operand pro opertor (). Pouit - napklad pedvn ukazatele na metodu jako parametru funkce. Pklad: zklady pouit opertor .* a ->* struct A { int i; void M() { i = 0; } }; void (A::*u1)(); int (A::*u2); int main() { A a; A *u = &a; u1 = &A::M; // ukazatel na metodu M u2 = &A::i; (a.*u1)(); // voln metody objektu a (u->*u1)(); // voln pes ukazatel na objekt a.*u2 = 5; // piazen do a.i } Prostory jmen (namespaces) definice-prostoru-jmen: namespace identifiktoropt { seznam-deklarac } alias-definice-prostoru-jmen: namespace identifiktor = jmno-prostoru ;

jmno-prostoru: ::opt identifiktor jmno-prostoru :: identifiktor definice se mohou opakovat jmno mus bt uniktn (nesm se shodovat se jmnem tdy, objektu, typu, ...) definice prostoru jmen je deklarac prostory jmen lze vnoovat existuje nepojmenovan prostor jmen funkce deklarovan jako extern "C" je svzna s C funkc bez kvalifikace: namespace X { extern "C" void f(); // C-funkce f() } Pklad: Definice a pouit prostoru jmen namespace A { class String { /* ... */ }; void f(String); } namespace B { class String { /* ... */ }; void f(String); } void g() { A::String s; // explicitn kvalifikace A::f(s); } Poznmky: leny prostoru jmen lze definovat vn tohoto prostoru: void A::f(String s) // A::String { String ss = "aaa"; // A::String // ... } extern nebo friend funkce pat do prostoru ve kterm jsou deklarovny Using deklarace a direktivy using-deklarace: using jmno-prostoru :: identifiktor ;

using-direktiva: using namespace jmno-prostoru ; using deklarace nen definic (jsou dovoleny redundantn deklarace) void h() { using A::String; using A::f; String s; f(s); // A::String // A::f

} using direktiva nedeklaruje dn nov jmna (pouze zpstupn) void k() { using namespace A; String s; // A::String f(s); // A::f } using deklarace ani using definice neovlivn ji deklarovan jmna Tdy a prostory jmen pro ely hledn jmen je tda prostorem jmen using lze aplikovat stejn jako u prostoru jmen class B { public: virtual void f(int); virtual void f(double); // ... }; class C : protected B { public: using B::f; // B::f(int), B::f(double) dostupn virtual void f(int); // pekryt B::f(int) virtual void f(char); // nov f(char) // ... }; using deklarace pouit uvnit tdy jako lensk deklarace mus odkazovat na pstupn leny bzovch td using direktiva neme bt pouita jako lensk deklarace uvnit tdy nelze definovat prostor jmen prostor jmen td nelze rozdlit do vce deklarac Nepojmenovan prostor jmen Pouit je stejn jako static v C - symboly nejsou dostupn z jinch modul.

namespace { void f(); // pstupn pouze z aktulnho modulu } void g() { // extern funkce pstupn vude f(); } Poznmky: nepouvat globln tdu pamti static, ale nepojmenovan prostor jmen nepouvat zastaral deklarace pstupu uvnit td, ale using deklarace Klov slovo mutable mutable - tda pamti, kter me bt aplikovna na leny tdy bez specifikace const nebo static. Takto oznaen len tdy nen nikdy konstantn - a to ani uvnit konstantnho objektu.

Pklad: class T { mutable unsigned refcount; int data; public: T(): refcount(0), data(0) {} const T * ref() const { refcount++; return this; } void setdata(int n) { data = n; } }; const T o; const T * g() { o.setdata(4); // chyba: nelze modifikovat const return o.ref(); // modifikace konstantnho objektu } Standardn knihovny Direktiva #include nevyaduje pponu jmna souboru Norma ISO C++ umouje pouit ISO C90 standardn knihovny: rozhran <cassert> <cctype> co obsahuje Makro assert pro ladn. Makra pro klasifikaci znak.

<cerrno> konstanty - chybov kdy <cfloat> Parametry pro floating-point <ciso646> podpora omezench zn. sad <climits> rozsahy celch sel <clocale> nrodn/jazykov podpora <cmath> Matematick funkce. <csetjmp> Typy pro longjmp() a setjmp(). <csignal> deklarace pro signal() a raise() <cstdarg> prce s promnnm potem argument <cstddef> Nkter makra a datov typy. <cstdio> Definice pro standardn vstup/vstup <cstdlib> Obecn pouiteln funkce <cstring> Funkce pro prci s etzci a pamt. <ctime> Typy a funkce pro prci s asem. <cwchar> prce s wchar_t <cwctype> makra pro klasifikaci wchar_t Vechny definice jsou umstny v prostoru jmen std. Pehled rozhran standardn knihovny C++ rozhran co obsahuje <algorithm> algoritmy <bitset> posloupnost bit pevn dlky <complex> komplexn sla <deque> obousmrn fronta <exception> obsluha vjimek - unexpected, terminate <fstream> soubory - vstup/vstupn streamy <functional> funkn objekty (unrn, binrn) <iomanip> manipultory pro streamy <ios> bzov tda pro streamy <iosfwd> forward deklarace pro streamy <iostream> vstup/vstupn streamy <istream> vstupn streamy <iterator> itertory <limits>implementan limity - mezn hodnoty typ <list> seznam <locale> lokalizace - nrodn abecedy, isalpha, ... <map> asociativn kontejner - kl-hodnota <memory> sprva pamti - aloktor, ... <new> sprva dynamick pamti <numeric> numerick operace (accumulate,...) <ostream> vstupn streamy <queue> fronta (pokraovn)

(pokraovn pehledu) rozhran co obsahuje <set> asociativn kontejner - mnoina kl <sstream> etzcov streamy <stack> zsobnk <stdexcept> standardn typy vjimek <streambuf> vyrovnvac pam pro streamy <string> obecn etzce (basic_string, ...) <typeinfo> typov informace - tda type_info <utility> relan operace <valarray> pole hodnot <vector> vektor Vechny definice jsou umstny v prostoru jmen std.

Poznmka: STL -- Standard Template Library -- je zkladem pro definice kontejner, itertor, algoritm, atd.

Poznmka:

Na Internetu jsou dostupn rozshl pehledy dalch knihoven pro C/C++.

About this document ... Jazyky C a C++ This document was generated using the LaTeX2HTML translator Version 2K.1beta (1.48) Copyright 1993, 1994, 1995, 1996, Nikos Drakos, Computer Based Learning Unit, University of Leeds. Copyright 1997, 1998, 1999, Ross Moore, Mathematics Department, Macquarie University, Sydney. The command line arguments were: latex2html -split +0 -no_footnode CPP.tex The translation was initiated by Petr Peringer on 2002-05-15 Petr Peringer 2002-05-15

You might also like