Literatura. Zdroje informací. Petr Peringer peringer AT fit.vutbr.cz



Podobné dokumenty
Datové struktury a datové typy.

Fakulta informačních technologií Vysoké učení technické v Brně. Jak na projekt

Prezentace a vysvětlení programového prostředí NXC

D A T A B Á Z O V É S Y S T É M Y

3 Současný pohled na jednotlivé směry SWI

Základy programování v GNU Octave pro předmět PPAŘ

CCC PPPP / M M C C P P / M M C P P / MM MM 2 2 C PPPP / M M M 2 2 C C P / M M CCC P / M M

Virtuální metody - polymorfizmus

The BlueJ Tutorial verze 1.4 pro BlueJ verze 1.2.x

PROGRAMOVÁNÍ V SQL Podpora výuky databázových systémů na SOŠ, založené na technologiích společnosti ORACLE.

Vlákna v C# Překlad Threading in C# od Josepha Albahari. Jakub Kottnauer. Z původního seriálu vydaného na Programujte.com

Ukazatel (Pointer) jako datový typ - proměnné jsou umístěny v paměti na určitém místě (adrese) a zabírají určitý prostor (počet bytů), který je daný

Tvorba mapové aplikace pro sledování polohy v Cloud serverová část Windows Azure

GLOBÁLNÍ ARCHITEKTURA ZÁKLAD- NÍCH REGISTRŮ DOPLNĚK

}w!"#$%&'()+,-./012345<ya

Manuál pracovních postupů v GIS pro oblast sociálního výzkumu a sociální práci

Vysoká škola ekonomická v Praze Fakulta informatiky a statistiky Vyšší odborná škola informačních služeb v Praze. Jan Šedivý.

FIT, Brno University of Technology, Czech Rep.,

- mikrokontrolér pro začátečníky a snadné použití

O S T R A V S K Á U N I V E R Z I T A. Cvičení z biostatistiky Základy práce se softwarem R. Pavel Drozd

LINUX DOKUMENTAČNÍ PROJEKT Computer Press

Abstraktní datový typ

GNU Image Manipulation Program 1 / 317. GNU Image Manipulation Program

Využití ontologií k řízení přístupu

FAKULTA STAVEBNÍ GEODÉZIE, KARTOGRAFIE A GEOINFORMATIKA

Božetěchova 1/2, , Brno 2 MFF, Univerzita Karlova v Praze. Abstrakt. Cílem bylo vytvořit stematizační algoritmus pro český jazyk

RELAČNÍ ALGEBRA - ÚVOD

MRP Základ vizuálního systému

Linux From Scratch. Michal Pecha

JAK NAPSAT BAKALÁŘSKOU PRÁCI

Transkript:

Úvod Jazyk Knihovny C++11 Úvod Úvod Jazyk Knihovny C++11 Literatura Seminář C++ Petr Peringer peringer AT fit.vutbr.cz Vysoké učení technické v Brně Fakulta informačních technologií, Božetěchova 2, 61266 Brno Tyto slajdy jsou určeny pro předmět ICP na FIT VUT v Brně. Obsahují základní popis jazyka C++ vhodný pro studenty, kteří již zvládli jazyk C. Obsah slajdů je velmi stručný, podrobnější informace jsou součástí výkladu. (Verze 2015-02-09) Přeloženo: 10. února 2015 ICP Seminář C++ 1/245 ICP Seminář C++ 2/245 Úvod Jazyk Knihovny C++11 Literatura Zdroje informací Literatura Úvod Jazyk Knihovny C++11 Literatura Stroustrup, B.: The C++ programming language, 4th edition, Addison-Wesley, 2013 Dobrá literatura http://www.fit.vutbr.cz/study/courses/icp/public/ WWW: FAQ, přehledy knihoven databáze programu man (sekce 3) GNU info a další dokumentace... The C++ Standard: Incorporating Technical Corrigendum No.1, Wiley, 2003 (C++98) C++11: Working Draft, Standard for Programming Language C++, http://www.open-std.org/jtc1/sc22/wg21/ /docs/papers/2012/n3337.pdf [2012-01-16] C++14: Working Draft, Standard for Programming Language C++, http://www.open-std.org/jtc1/sc22/wg21/ /docs/papers/2013/n3797.pdf [2013-10-13] Gamma E. et al.: Design Patterns: Elements of Reusable Object-Oriented Software, Addison-Wesley, 1994 ICP Seminář C++ 3/245 ICP Seminář C++ 4/245

Programovací jazyk C++ Historie 1973 vznik jazyka C: Kernighan, Ritchie, (K&R C) 1980 vznik C with classes - později C++: Bjarne Stroustrup 1990 ISO C: mezinárodní norma (C90) 1998 ISO C++: mezinárodní norma (C++98) 1999 ISO C: (C99) 2003 TC1: aktualizace normy C++ (C++03) 2011 ISO C++: norma C++ (C++11) 2011 ISO C: aktuální norma jazyka C (C11) 2014 ISO C++: aktuální norma C++ (C++14) Původní definicí je kniha Stroustrup: The C++ Programming Language (Addison-Wesley 1985, 1991, 1997, 2013). Platí norma ISO/IEC 14882:2011. Poznámka: Tento text předpokládá znalost jazyka ISO C ICP Seminář C++ 5/245 Charakteristika jazyka C++ Překladače C++ Existuje celá řada překladačů a vývojových prostředí pro jazyk C++. Aktuální přehled najdete na WWW stránce. Doporučené prostředí GNU C++ (Existuje pro všechny běžné platformy. Je třeba používat novější verzi, protože ty starší se příliš odchylují od normy.) Poznámka: Integrovaná prostředí (Eclipse,Netbeans,Anjuta,KDevelop,...) nebo editory (VIM,Emacs,...) + program make ICP Seminář C++ 6/245 Nevýhody C++ Obecně využitelný programovací jazyk vyšší úrovně. Je standardizovaný (ISO) Podporuje abstraktní datové typy a vytváření knihoven. Nástupce jazyka C (zpětná kompatibilita) Vysoká efektivita Objektová orientace (třídy, dědičnost) Možnost přetěžovat operátory Generické třídy a funkce (šablony) Obsluha výjimek Std. knihovna (kontejnery, vlákna, regexp, random,...) Mnoho různých implementací překladačů Množství knihoven pro různé aplikace (Boost, Qt,...) Je podstatně větší a složitější než C Není čistě objektově orientovaný (např. typ int není třída a nelze z něj dědit) Zdědil některé problémy jazyka C (indexování polí se nekontroluje, manuální správa paměti,...) Není zcela kompatibilní s jazykem C (restrict, complex,...) Ne všechny překladače dostatečně vyhovují normě. Poznámka: Citace z Internetu: There are only two kinds of programming languages: those people always bitch about and those nobody uses. ICP Seminář C++ 7/245 ICP Seminář C++ 8/245

Překlad a sestavení programu Optimalizace a ladění Soubor ahoj.cc: #include <iostream> // bez přípony int main() { std::cout << "Ahoj!\n"; // tisk řetězce Způsob zpracování (UNIX, překladač GNU C++): g++ -o ahoj ahoj.cc # překlad, sestavení./ahoj # spuštění clang++ -o ahoj ahoj.cc # překladač clang/llvm Optimalizace kódu překladačem (UNIX, GNU C++): g++ -O2 -o prog prog.cc Poznámka: Nejlepší úroveň optimalizace je třeba vyzkoušet Ladění (Linux, GNU C++, GNU debugger): g++ -g -o prog prog.cc # +ladicí informace gdb prog # ladění v příkazové řádce Poznámka: Možné přípony:.cc,.cpp,.c,.c++,.cxx ICP Seminář C++ 9/245 ICP Seminář C++ 10/245 Příklad: čtení a tisk C++ řetězce Příklad: čtení a tisk C řetězce v C++ (NEVHODNÉ) #include <iostream> #include <string> // std::string int main() { using namespace std; // nemusíme psát std:: cout << "C++ string" << endl; string s; cout << "s = " << s << endl; cout << "string s (libovolná délka): " << flush; cin >> s ; // sledujte jak funguje (čte slova) cout << "s = " << s << endl; // hrozí chyba typu "buffer overflow" [NEPOUŽÍVAT] #include <iostream> #include <string> using namespace std; // nemusíme psát std:: int main() { 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; ICP Seminář C++ 11/245 ICP Seminář C++ 12/245

Příklad: četnost slov Příklad: četnost slov (nemoderní, C++98) // g++ -std=c++11 (nebo c++0x) #include <iostream> #include <string> #include <map> // kontejner std::map int main() { std::string word; std::map<std::string,int> m; // asociativní pole while( std::cin >> word ) // čte slova m[word]++; for(auto x: m) // iterace a tisk std::cout << x.first <<"\t"<< x.second <<"\n"; #include <iostream> #include <string> #include <map> typedef std::map<std::string,int> typedef map_t::iterator // kontejner std::map map_t; mapiter_t; int main() { std::string word; map_t m; // asociativní pole while( std::cin >> word ) // čte slova m[word]++; for(mapiter_t i=m.begin(); i!=m.end(); ++i) // tisk std::cout << i->first <<"\t"<< i->second <<"\n"; ICP Seminář C++ 13/245 ICP Seminář C++ 14/245 Příklad: řazení čísel Příklad: řazení čísel (nemoderní, C++98) // g++ -std=c++11 #include <iostream> #include <vector> #include <algorithm> #include <iterator> // cout // vector // sort, copy // ostream_iterator int main() { using namespace std; vector<int> v{4, 2, 5, 1, 3; // inicializace sort(begin(v), end(v)); // řazení ostream_iterator<int> o(cout,"\n"); // iterátor copy(begin(v), end(v), o); // tisk #include <iostream> // cout #include <vector> // vector #include <algorithm> // sort, copy #include <iterator> // ostream_iterator typedef std::vector<int> vec_t; typedef std::ostream_iterator<int> outiter_t; int main() { 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 std::sort(v.begin(), v.end()); // řazení outiter_t o(std::cout, "\n"); // iterátor std::copy(v.begin(), v.end(), o); // tisk ICP Seminář C++ 15/245 ICP Seminář C++ 16/245

Příklad: řazení čísel varianta 2 Příklad: lambda funkce #include <vector> #include <algorithm> #include <iostream> #include <iterator> // vector // sort, copy // cout // ostream_iterator // g++ -std=c++11 #include <iostream> #include <vector> #include <algorithm> // cout // vector // sort, copy, for_each int main() { using namespace std; vector<int> v; int i; while ( cin >> i ) // čtení čísel ze vstupu v.push_back(i); // vektor se zvětšuje sort(v.begin(), v.end()); // řazení ostream_iterator<int> o(cout, "\n"); copy(v.begin(), v.end(), o); // tisk ICP Seminář C++ 17/245 int main() { using namespace std; vector<int> v{ 4, 2, 5, 1, 3 ; // inicializace sort(begin(v), end(v), [](int x, int y){return x>y; ); // řazení int a = 10; // lokální objekt for_each(begin(v), end(v), [&a](int &x){ x += a++; ); // "closure" for(auto x: v) // tisk cout << x << endl; ICP Seminář C++ 18/245 Rozdíly mezi C a C++ C++ vychází z jazyka C Dobře napsané C programy jsou též C++ programy (s několika výjimkami: nová klíčová slova, povinné prototypy funkcí, silnější typová kontrola,...) Rozdíly mezi C a C++ jsou zjištěny překladačem kromě několika výjimek: Znakové literály jsou typu char sizeof( a ) == sizeof(int) // C sizeof( a ) == sizeof(char) // C++... Výčtový typ není ekvivalentní typu int enum e { A ; sizeof(a) == sizeof(int) // C sizeof(a) == sizeof(e) // C++!= sizeof(int) Jméno struktury v C++ může překrýt jméno objektu, funkce, výčtu nebo typu v nadřazeném bloku: int x[99]; void f() { struct x { int a; ; sizeof(x); // pole v C, struktura v C++ ICP Seminář C++ 19/245 ICP Seminář C++ 20/245

Rozšíření C++11 proti C99 Rozšíření C++11 proti C99 pokračování typ reference anonymní unie (jsou v C11) přetěžování funkcí a operátorů operátory new, delete, new[] a delete[] třídy (class), abstraktní třídy automatická inicializace (konstruktory, destruktory) zapouzdření (private, public, protected) dědičnost, násobná dědičnost polymorfismus (virtuální funkce) uživatelem definované konverze jméno třídy a výčtu je jméno typu ukazatele na členy tříd v inicializaci statických objektů je dovolen obecný výraz generické datové typy šablony (template, typename) obsluha výjimek (try, catch, throw) prostory jmen (namespace, using) nové způsoby přetypování (static_cast, const_cast, reinterpret_cast, dynamic_cast) informace o typu za běhu programu (typeid, type_info) klíčové slovo mutable ICP Seminář C++ 21/245 ICP Seminář C++ 22/245 Novinky v C++11 R-hodnotové reference, move konstruktory constexpr Změny ve specifikaci dat POD = Plain Old Data extern template Inicializační seznamy (initializer_list<t>) Sjednocený zápis inicializace (int a{5;) Inference typů (auto, decltype) range for cyklus přes rozsah kontejneru Lambda funkce a výrazy Alternativní syntaxe funkcí []f(int x)->int{return x; Speciální identifikátory override, final nullptr ICP Seminář C++ 23/245 Novinky v C++11 pokračování Nové, silně typované výčty template<vector<t>> (byl problém v C++98) explicit pro konverzní operátory alias šablony (using) Šablony s proměnným počtem parametrů ( variadic templates ) Nové řetězcové literály Uživatelem definované literály (10kg, 12345_bignum) Podpora vláken (thread_local,...) default a delete konstruktory atd. long long static_assert Možnost implementovat garbage collector,... ICP Seminář C++ 24/245

Novinky v C++14 C++ Malé změny a zrušení různých omezení: auto f() {... return x; auto parametry lambda funkcí šablony proměnných inicializace {.field=value,... binární literály 0b0110 oddělovače v numerických literálech 10 000 000 vylepšení a rozšíření std knihovny... Poznámky /* text poznámky */ // text poznámky platí až do konce řádku Identifikátory Identifikátory obsahující dvojité podtržítko ( ), nebo začínající podtržením a velkým písmenem jsou vyhrazeny pro implementaci C++. ICP Seminář C++ 25/245 ICP Seminář C++ 26/245 Klíčová slova C++ asm dynamic_cast new switch auto else noexcept template bool enum nullptr this break explicit operator throw case private true catch extern protected try char false public typedef class float register typeid const for reinterpret_cast typename const_cast friend return union constexpr goto short unsigned continue if signed using decltype inline sizeof virtual default int static void delete long static_assert volatile do mutable static_cast wchar_t double namespace struct while ICP Seminář C++ 27/245 Alternativní reprezentace <% { and && and_eq &= %> bitand & bitor <: [ compl ~ not! :> ] not_eq!= or %: # or_eq = xor ^ %:%: ## xor_eq ^= Poznámka: Digraphs (<:) Poznámka: Trigraphs (např.??/) (bude zrušeno v C++17) // Provede se následující příkaz??/ i++; ICP Seminář C++ 28/245

Literály Typová kontrola Syntaxe běžných číselných literálů je stejná jako v C. C++11: uživatelem definované literály (operator "") Příklad: BigNumber operator "" _big(const char * literal_string); BigNumber some_variable = 12345_big; Znakové literály jsou typu: char int v C++ v C, v C++ pouze víceznakové (mbc) Poznámka: V C++ existují 3 různé znakové typy: char, unsigned char a signed char v C++ je silnější než v C: Deklarace: void (*funptr)(); je ukazatel na fci vracející void v C, ukazatel na fci vracející void bez parametrů v C++ Ukazatel na konstantní objekt nelze přiřadit do ukazatele na nekonstantní objekt. Typová kontrola při sestavování programu rozliší funkce s různými parametry Výčtové typy: lze přiřadit pouze konstantu daného typu lze vynechat klíčové slovo enum při použití sizeof výčtového typu závisí na hodnotách prvků ICP Seminář C++ 29/245 ICP Seminář C++ 30/245 Poznámky Typ reference Definice: T & x = Lhodnota_typu_T; Rozsah deklarace proměnné cyklu ve for for(int i=1; i<10; i++) { /* zde platí i */ Je chybou, když je příkazem skoku přeskočena inicializace proměnné Pozor na setjmp a longjmp Blízké ukazatelům (ale neexistuje obdoba NULL) Použitelné pro předávání parametrů odkazem Nelze vytvořit: referenci na referenci (např. T & & r), Pozor: v šablonách je dovoleno, ale jen nepřímo referenci na bitová pole, ukazatele na reference, pole referencí. Výhodou referencí je jednoduchost použití (na rozdíl od *ptr) ICP Seminář C++ 31/245 ICP Seminář C++ 32/245

Typ reference příklady Reference chybná nebo netypická použití double x = 1.23456; double & xref = x; // Typické použití const int & i = 7; // Vytvoří pomocnou proměnnou int & i = 7; // CHYBA! nelze pro nekonst. referenci double & yref; extern int & zref; // Předání parametru odkazem: void Transpose(Matrix & m); // CHYBA! chybí inicializace // extern může být bez inicializace // Vracení reference: int & f(param); // Pozor na to _co_ se vrací! f(p) = 1; // Volání funkce float f = 3.14; const int & ir = f; // pomocná_proměnná = 3 ir = 5; // CHYBA! konstantu nelze změnit Poznámka: Proč nelze použít R-hodnotu s nekonstantní referencí: void incr( int& refint ) { refint++; void g() { // pozor - toto není C++ double d = 1; incr(d); // záludná chyba: nezmění d! ICP Seminář C++ 33/245 ICP Seminář C++ 34/245 R-hodnotové reference (R-value references) Typ bool Definice: T && x = výraz; výraz nemusí být L-hodnota (Definice pojmu L-hodnota: &(výraz) funguje.) Použitelné pro optimalizaci (omezení kopírování) viz například move konstruktory Perfect forwarding při správném použití (dedukce typu) template<typename T> void f( T && x ); // R-value OR L-value reference auto && x = y; // univerzální reference (podle y) Pojmy: lvalue, xvalue, prvalue; glvalue, rvalue ICP Seminář C++ 35/245 Booleovské literály: false a true Implicitní konverze bool ---> int true ---> 1 false ---> 0 Konverze čísel, výčtů a ukazatelů na bool 0 ---> false jinak ---> true Výsledek relační operace je typu bool Příklad: bool test = false; test = (a > b); // bool test = 5; // int ---> bool ICP Seminář C++ 36/245

Přehled operátorů C++ (podle priority; neúplné) operátory asociativita ( ) [ ] -> ::.! ~ + - ++ -- & * (Typ) sizeof new delete.* ->* * / % + - << >> < <= > >= ==!= & ^ &&?: = *= /= %= += -= &= ^= = <<= >>=, ICP Seminář C++ 37/245 Operátory C++ operátor popis :: kvalifikátor.* dereference ukazatele na člen třídy přes objekt (o.*mptr) ->* dereference ukazatele na člen třídy přes ukazatel na objekt (ptr->*mptr) new dynamické vytvoření objektu delete zrušení objektu static_cast operátory přetypování C++ reinterpret_cast const_cast dynamic_cast alignof C++11 noexcept C++11 ICP Seminář C++ 38/245 Operátory příklady // alokace paměti operátorem new: T *p = new T[10*n]; // dynamická alokace pole T *p2 = new T(5); // dynamická alokace objektu // uvolnění paměti operátorem delete: delete [] p; // uvolnění paměti pole delete p2; // uvolnění paměti objektu // alokace a rušení pole bajtů: char *s = new char[100]; delete [] s; // char *s2 = static_cast<char*>(std::malloc(100)); // std::free(s2); ICP Seminář C++ 39/245 Operátor :: Přístup ke globální proměnné: double x; void f() { int x; // lokální x ::x = 3.1415926; // globální x Explicitní specifikace třídy: class T { int metoda(); // deklarace metody ; int T::metoda() { // definice mimo třídu Specifikace prostoru jmen: prostor::identifikátor std::cin prostor::podprostor::identifikátor ICP Seminář C++ 40/245

Standardní konverze v C++ I Implicitní konverze probíhají automaticky (jsou-li nutné) při vyhodnocování binárních operací: 1 Každý malý celočíselný typ se konvertuje takto: typ konverze na metoda char int podle nastavení unsigned char int doplní nuly signed char int rozšíří znaménko short int stejná hodnota unsigned short unsigned int stejná hodnota enum int stejná hodnota bool int 0 nebo 1 Potom je každá hodnota operandu bud int (včetně long a unsigned modifikátorů) double, float nebo long double. 2 Je-li některý operand long double, je druhý konvertován na long double ICP Seminář C++ 41/245 Standardní konverze v C++ II 3 Jinak, je-li operand double, konvertuje druhý na double 4 Jinak, je-li operand float, konvertuje druhý na float 5 Jinak, je-li operand unsigned long, konvertuje druhý na unsigned long 6 Jinak, je-li operand long, konvertuje druhý na long 7 Jinak, je-li operand unsigned, konvertuje druhý na unsigned 8 Jinak, jsou oba operandy typu int Výsledek odpovídá typu obou operandů po konverzi. ICP Seminář C++ 42/245 Konverze příklady Explicitní konverze Explicitní konverze uvádí programátor do textu programu (a přebírá za ně veškerou odpovědnost): Poznámka: Při porovnávání čísla int s číslem unsigned může dojít k (pro někoho neočekávaným) problémům: int i = -1; unsigned u = 1234U; (typ) výraz (C kompatibilita, nepoužívat) typ(výraz) static_cast<typ>(výraz) Příklady: Explicitní přetypování if(i<u) printf(" i < u "); // sledujte varování překladače // nevytiskne nic! double(int1)/int2 complex(3.14) int( c ) static_cast<char*>(ptr) reinterpret_cast<long>(ptr) ICP Seminář C++ 43/245 ICP Seminář C++ 44/245

extern "C" Preprocesor Možnost použití funkcí z knihoven jazyka C, případně jiných jazyků: extern "C" int f(int); extern "C" { int g(int); int h(int); Je stejný jako v ISO C, je vhodné minimalizovat jeho používání, protože máme lepší prostředky: #define K1 10 const int K1 = 10; lze nahradit za: #define f(x) (výraz_x) lze většinou nahradit za: inline int f(int x) { return výraz_x; případně lze použít generické funkce: Poznámka: Prostory jmen template<typename T> inline T f(t x) { return výraz_x; ICP Seminář C++ 45/245 ICP Seminář C++ 46/245 Základní principy OO přístupu Vývoj programů Tradiční přístup program = data + algoritmy(podprogramy) Modulární přístup program = moduly modul = data + algoritmy(podprogramy) Objektově orientovaný přístup program = objekty + komunikace každý objekt patří do nějaké třídy (klasifikace) hierarchie objektů (skládání) hierarchie tříd (dědičnost) analýza návrh implementace testování údržba Objektově orientovaná analýza (OOA) zkoumání požadavků z hlediska tříd a objektů Objektově orientovaný návrh (OOD) dekompozice popis systému a jeho charakteristik notace (grafy) Objektově orientované programování (OOP) program je skupina spolupracujících objektů každý objekt reprezentuje instanci nějaké třídy třídy jsou navzájem v relaci dědičnosti volba implementačního jazyka ICP Seminář C++ 47/245 ICP Seminář C++ 48/245

Objektový model Notace Hlavní principy Abstrakce Zapouzdření Modularita (fyz.) Hierarchie Vedlejší principy typování paralelismus persistence Použití grafů: diagramy tříd diagramy objektů diagramy komunikace objektů Poznámka: UML Poznámky: tyto principy nejsou nové dědičnost = hierarchie abstrakcí ICP Seminář C++ 49/245 ICP Seminář C++ 50/245 Třídy Třídy a objekty příklad třída = data + funkce + zapouzdření Rozšíření systému typů reprezentuje množinu objektů Definuje rozhraní a chování objektů Klíčová slova: class, struct a union C++ povoluje nekompletní deklarace tříd: class X; // => omezení při použití Příklad: Třída T class T { int i; // data (i jiné objekty) // specifikace přístupových práv void m(); // metody typedef int typ; // vnořené typy, atd. ; Příklad: Použití třídy T T x; // objekt třídy T T &refx = x; // reference na objekt T T *ptrx = &x; // ukazatel na objekt T T xarr[20]; // pole objektů třídy T T f(); // funkce vracející T T &&rref = f(); // C++11: R-value reference Poznámky: Přístup ke složkám třídy je stejný jako u struktur One definition rule ICP Seminář C++ 51/245 ICP Seminář C++ 52/245

Datové členy a vnořené objekty Datové členy a vnořené objekty příklad Datové složky třídy Běžné datové složky (jsou v každém objektu) Statické datové složky pouze jedna instance pro jednu třídu (tj. všechny objekty třídy sdílí tuto instanci) jsou přístupné i když neexistuje žádný objekt musí se definovat a inicializovat vně definice třídy (kromě konstant) Použití statických datových složek: Společný bank pro všechny objekty (např. počet vytvořených objektů dané třídy) Zapouzdření ochrana proti neoprávněnému přístupu Příklad různých datových složek třídy class X { static const int N = 100; // konstanta static int count; // jedna instance pro třídu int i; // je v každém objektu int j = 5; // C++11: inicializace enum XE { A=10, B, C, D, E, F e; string s; // v každém objektu double data[3]; // v každém objektu ; int X::count = 0; // Pozor! je nutná definice v modulu ICP Seminář C++ 53/245 ICP Seminář C++ 54/245 Kontrola přístupu ke členům tříd Kontrola přístupu ke členům tříd příklad Specifikace přístupu public private protected Implicitní nastavení: může být použit libovolnou funkcí pouze pro metody a friend funkce dané třídy jako private, ale navíc je dostupné v metodách a friend funkcích tříd odvozených z této třídy pro definici implicitně platí lze předefinovat? class private ano struct public ano union public ne Přístupové specifikace mohou být umístěny libovolně: class T { int i; // class => implicitně private int j; // public protected: int k; // protected int l; // public int m; private: int n; ; ICP Seminář C++ 55/245 ICP Seminář C++ 56/245

Friend funkce a třídy Friend funkce a třídy příklad klíčové slovo friend mají plná práva přístupu ke všem členům třídy vlastnost friend se nedědí vlastnost friend není tranzitivní Poznámky: používat jen výjimečně narušuje ochranu dat použitelné pro vytváření množin příbuzných tříd (například kontejner + iterátor) class Y; // nekompletní deklarace třídy Y class X { int data; // privátní data friend Y; // friend třída Y friend int f(x*);// deklarace friend funkce ; class Y { // definice třídy void m(x &o) { o->data = 0; // přístup je možný ; int f(x *ptr) { ptr->data = 1; // definice funkce // přístup je možný ICP Seminář C++ 57/245 ICP Seminář C++ 58/245 Metody Inline metody Kategorie metod Konstruktory (vznik objektu) Destruktor (zánik objektu) Statické metody Běžné metody (ne statické) Virtuální metody (pro polymorfismus) Operátory (různé operace: + - * /) Konverze (přetypování objektu na jiný typ) optimalizace (ale je možné i volání) vhodné pro krátké funkce (jinak code bloat ) musí být definována stejně pro každý modul metoda definovaná uvnitř třídy je automaticky inline: class X { char *i; char *f() const { // implicitně inline return i; ; s explicitním uvedením klíčového slova inline: inline char *X::f() const { return i; ICP Seminář C++ 59/245 ICP Seminář C++ 60/245

Jednoduchý příklad: třída interval Klíčové slovo this // třída čísel od jedné do deseti class Int_1_10 { int n; Int_1_10() { n = 1; // implicitní ctr Int_1_10(int n) { SetValue(n); void SetValue(int x); // deklarace metody int GetValue() const { return n; void Print() const; ; void Int_1_10::SetValue(int x) { // definice metody if(x<1 x>10) error("range error"); n = x; Implicitní parametr nestatických metod Ukazatel na objekt se kterým metoda pracuje: pro metodu třídy T je this typu T *const nebo const T *const pro konstantní objekty. V šablonách (template) se ve speciálních případech musí používat this->člen this lze použít pouze uvnitř nestatické metody (například pro předání odkazu na objekt do jiné funkce). ICP Seminář C++ 61/245 ICP Seminář C++ 62/245 Příklad použití this Statické metody class T { void f() { std::cout << "T\n"; void f() const { std::cout << "const T\n"; T clone() const { return *this; ; T o1; // nekonstantní objekt const T o2 = T(); // konstantní objekt int main() { o1.f(); // T *const this = &o1 o2.f(); // const T *const this = &o2 T o = o1.clone(); nemají this nesmí být virtuální chovají se jako obyčejné funkce, ale mají přístup k private složkám třídy použití mimo metody dané třídy se musí kvalifikovat T::staticka_metoda(parametry) lze je volat i když neexistuje žádný objekt vhodné např. po pomocné funkce pro třídu ICP Seminář C++ 63/245 ICP Seminář C++ 64/245

Statické metody příklad class X { static int count; // toto není definice! static int getcount(); // vrací počet objektů static void func(int i, X* ptr); // nevhodné? void g(); ; int X::count = 0; // definice a inicializace void g() { int i = X::getCount(); // nepotřebuje objekt X obj; // definice objektu třídy X::func(1, &obj); // objekt předán explicitně obj.g(); // obyčejná metoda ICP Seminář C++ 65/245 Vnořené typy příklad struct A { typedef int MujTyp; // vnořený typ struct B { // definice vnořené třídy void MetodaB(int); // deklarace metody ; class C; // deklarace vnořené třídy C ; class A::C { ; // definice C mimo třídu A void A::B::MetodaB(int i) { // definice metody int main() { A::B obj; // B je public A::MujTyp i = 5; obj.metodab(i); ICP Seminář C++ 67/245 Vnořené typy typy deklarované uvnitř třídy vnořená třída ( nested class ) typedef souvislost s prostory jmen lze použít neúplné deklarace vnořené třídy použití pro ukrytí implementačně závislých tříd (například iterátory v kontejnerech) ICP Seminář C++ 66/245 Operátory new a delete Umožňují dynamické vytváření a rušení jednotlivých objektů (new, delete) polí objektů (new[], delete[]) Lze je předefinovat, případně přetížit (vhodné například pro použití s jinou správou volné paměti). Alokace objektů new T 1 alokuje pamět pro objekt použije T::operator new(), pokud existuje jinak použije ::operator new() operator new při chybě vyvolá výjimku bad_alloc 2 po úspěšné alokaci je vyvolán konstruktor Příklad: (C++11) auto ptr = new vector<int>{1,2,3; ICP Seminář C++ 68/245

Alokace polí new T[velikost] 1 alokuje pamět pro pole použije T::operator new[](), pokud je definován není-li použije ::operator new[]() při chybě vyvolá výjimku bad_alloc 2 volá se implicitní konstruktor na každý prvek pole v rostoucím pořadí indexů Operátor delete Uvolnění paměti delete ptr delete[] ptr 1 volá destruktory v obráceném pořadí než při new 2 uvolní pamět voláním T::operator delete() nebo ::operator delete() (případně varianta s delete[] pro pole) Poznámka: Musí být uvedeny všechny rozměry pole. První rozměr nemusí být konstantní výraz. Příklad: T *pt = new T[10]; // pole 10 objektů Příklady: delete ukazatel; // ruší objekt alokovaný new T delete [] ptr; // ruší pole alokované new T[n] ICP Seminář C++ 69/245 ICP Seminář C++ 70/245 Speciální alokace paměti Operátor new (někdy i delete) může mít více parametrů. Toho se využívá například pro alokaci na konkrétní adresu ( Placement new ). new musí mít první parametr typu size_t delete musí mít první parametr typu void* Příklady volání operátoru new 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(22) T[5] operator new[](sizeof(t)*5 + y, 22) ( x a y jsou implementací definované hodnoty ) Speciální alokace paměti nothrow Identifikátor nothrow pro speciální variantu operátoru new(nothrow) vracející při nedostatku paměti hodnotu nullptr (0 v C++98) místo vyvolání výjimky bad_alloc. Použitelné pro systémy, kde je režie výjimek nežádoucí. Příklad: Použití nothrow T *p = new(nothrow) T; if( p==nullptr ) errorexit("málo paměti"); //... delete p; ICP Seminář C++ 71/245 ICP Seminář C++ 72/245

Definice new a delete pro třídu Speciální alokace objektů třídy příklad Pro třídu T lze definovat funkce: void * T::operator new(size_t); void * T::operator new[](size_t); void T::operator delete(void* ptr); void T::operator delete[](void* ptr); // jeden objekt // pole objektů Nejsou-li výše uvedené operace definovány, použijí se standardní (globální) operátory. class T { void * operator new (size_t s); void operator delete (void* ptr); ; void * T::operator new (size_t s) { char* ptr = new char[s]; // volá ::new //=== ZDE můžeme provést potřebné operace... return static_cast<void*>(ptr); void T::operator delete (void* ptr) { //=== ZDE můžeme provést potřebné operace, // např. vynulování z bezpečnostních důvodů delete[] static_cast<char*>(ptr); // ::delete ICP Seminář C++ 73/245 ICP Seminář C++ 74/245 Konstruktory Konstruktory příklad = speciální metody pro inicializaci objektů při vzniku lze definovat více konstruktorů (viz. přetěžování funkcí) jsou volány automaticky při vytváření objektů nesmí být static ani virtual lze je volat i pro const a volatile objekty delete nebo private: lze zakázat vytváření objektů nelze získat adresu konstruktoru C++11: delegating constructor volá jiný konstruktor Poznámka: Implicitní konstruktor je každý konstruktor, který lze zavolat bez parametrů (a může být pouze jeden pro jednu třídu). ICP Seminář C++ 75/245 class X { int i; ; X(): i{ { // implicitní konstruktor X(int x): i{x {; // konstruktor s parametrem X(T x): X{convtoint(x) {; // delegace X(const X&) =default; // kopírovací konstruktor X(X&&) =default; // "move"~ konstruktor X o; // volá se X::X() X o2{55; // X::X(int) X o3 = 55; // X::X(int) a X::X(X&&) X o4{o2; // X::X(const X&) X *px = new X; // X::X() X *px2 = new X{666; // X::X(int) ICP Seminář C++ 76/245

Implicitní vytváření metod překladačem 1 Pokud není definován explicitně, překladač může vytvořit: implicitní konstruktor X::X() kopírovací konstruktor X::X(const X&) move konstruktor X::X(X&&) operátor přiřazení X &X::operator = (const X&) move operátor přiřazení X &X::operator = (X&&) destruktor X::~X() Omezení: Např. pokud již je definován jiný konstruktor, pak k vytvoření X::X() nedojde. Překladačem vytvořené metody jsou vždy inline Pokud některý člen třídy nelze implicitně odpovídajícím způsobem zkonstruovat, je program chybně vytvořen. Někdy (typicky u tříd obsahujících ukazatel) implicitní verze operací nevyhovují a musíme je definovat. ICP Seminář C++ 77/245 Kopírovací konstruktor (Copy constructor) Implicitní vytváření metod překladačem 2 C++11: Příklad: Specifikace = default vytoří implicitní verzi. Specifikace = delete zakáže implicitní vytvoření. struct X { X() = default; X(int); ; // Bez tohoto se nevytvoří, // protože je tu jiný konstruktor. // Zákaz kopírovacího konstruktoru a přiřazení: X(const X&) = delete; X& operator=(const X&) = delete;... ICP Seminář C++ 78/245 Kopírovací konstruktor příklad má jeden parametr typu const X& (nebo nevhodně X&), je volán při vzniku objektu kopírováním: definice s inicializací jiným objektem, předávání parametru hodnotou, vracení hodnoty z funkce, vyvolání a zpracování výjimek, pokud je vytvořen překladačem, kopíruje objekty po složkách (jejich kopírovacím konstruktorem) X::X(const X& o): s1{o.s1, s2{o.s2 { Poznámky: Nezaměňovat s operátorem přiřazení! Možnost optimalizace (copy elision) Ukázka jaké konstruktory se použijí v různých situacích: X f(x p) { // * předání parametru hodnotou X a; // implicitní konstruktor X b{a; // kopírovací konstruktor X b2(a); // kopírovací konstruktor - X c = a; // kopírovací konstruktor - return a; // kopírovací konstruktor f(a); // * kopírovací konstruktor throw a; // kopírovací konstruktor ICP Seminář C++ 79/245 ICP Seminář C++ 80/245