PB161 Programování v jazyce C++ Přednáška 3

Podobné dokumenty
PB přednáška (5. října 2015)

PB161 Programování v jazyce C++ Přednáška 4

PB161 Programování v jazyce C++ Přednáška 2

PB161 Programování v jazyce C++ Přednáška 7

PB161 Programování v jazyce C++ Přednáška 7

PB161 Programování v jazyce C++ Přednáška 4

Programování v C++ 1, 6. cvičení

PB161 Programování v jazyce C++ Přednáška 2

Programování v C++ 1, 5. cvičení

PB161 Programování v jazyce C++ Přednáška 9

Dědění, polymorfismus

Generické programování

Virtuální metody - polymorfizmus

PREPROCESOR POKRAČOVÁNÍ

Obsah přednášky 9. Skrývání informací. Skrývání informací. Zapouzdření. Skrývání informací. Základy programování (IZAPR, IZKPR) Přednáška 9

TŘÍDY POKRAČOVÁNÍ. Události pokračování. Příklad. public delegate void ZmenaSouradnicEventHandler (object sender, EventArgs e);

Více o konstruktorech a destruktorech

PŘETĚŽOVÁNÍ OPERÁTORŮ

PB161 Programování v jazyce C++ Přednáška 1

Programování v C++ 2, 4. cvičení

Principy OOP - rozhraní, dědičnost PB161

PB161 Programování v jazyce C++ Přednáška 10

PB161 Programování v jazyce C++ Přednáška 8

Definice třídy. úplná definice. public veřejná třída abstract nesmí být vytvářeny instance final nelze vytvářet potomky

NPRG031 Programování II 1 / :25:46

NMIN201 Objektově orientované programování 1 / :36:09

PB161 Programování v jazyce C++ Přednáška 10

PRINCIPY OOP, DĚDIČNOST. PB161 Principy OOP - Zapouzdření

PB161 Základy OOP. Tomáš Brukner

Polymorfismus. Časová náročnost lekce: 3 hodiny Datum ukončení a splnění lekce: 30.března

Úvod Třídy Rozhraní Pole Konec. Programování v C# Hodnotové datové typy, řídící struktury. Petr Vaněček 1 / 39

24. listopadu 2013, Brno Připravil: David Procházka

Jazyk C++ I. Šablony 2

Třídy. Instance. Pokud tento program spustíme, vypíše následující. car1 má barvu Red. car2 má barvu Red. car1 má barvu Blue.

PB161 Programování v jazyce C++ Přednáška 8

Jazyk C++ I. Polymorfismus

Jazyk C++ 1. Blok 3 Objektové typy jazyka C++ Třída. Studijní cíl. Doba nutná k nastudování. Průvodce studiem

Programování v C++ 3, 3. cvičení

PB161 Programování v jazyce C++ Přednáška 9

Obsah přednášky 7. Základy programování (IZAPR) Přednáška 7. Parametry metod. Parametry, argumenty. Parametry metod.

Mělká a hluboká kopie

Jazyk C# (seminář 3)

Dynamicky vázané metody. Pozdní vazba, virtuální metody

přetížení operátorů (o)

PB přednáška (12. října 2015)

Zapouzdření. Tomáš Pitner, upravil Marek Šabo

Chování konstruktorů a destruktorů při dědění

11 Diagram tříd, asociace, dědičnost, abstraktní třídy

Abstraktní třídy, polymorfní struktury

Michal Krátký. Úvod do programovacích jazyků (Java), 2006/2007

PB161 Programování v jazyce C++ Přednáška 9

IRAE 07/08 Přednáška č. 1

konstruktory a destruktory (o)

Programování II. Polymorfismus

Michal Krátký. Úvod do programovacích jazyků (Java), 2006/2007

Definice třídy. úplná definice. public veřejná třída abstract nesmí být vytvářeny instance final nelze vytvářet potomky

typová konverze typová inference

přetížení operátorů (o)

Jazyk C++, některá rozšíření oproti C

PB přednáška (21. září 2015)

2) Napište algoritmus pro vložení položky na konec dvousměrného seznamu. 3) Napište algoritmus pro vyhledání položky v binárním stromu.

<surface name="pozadi" file="obrazky/pozadi/pozadi.png"/> ****************************************************************************

Dědičnost. Časová náročnost lekce: 3 hodiny Datum ukončení a splnění lekce: 23.března

Jazyk C++ II. Šablony a implementace

Jazyk C++ I. Šablony

IRAE 07/08 Přednáška č. 2. atr1 atr2. atr1 atr2 -33

Dědičnost (inheritance)

Konstruktory a destruktory

PB161 Programování v jazyce C++ Přednáška 11

Úvod do programovacích jazyků (Java)

Objekty v PHP 5.x. This is an object-oriented system. If we change anything, the users object.

Programování II. Abstraktní třída Vícenásobná dědičnost 2018/19

Pokročilé programování v jazyce C pro chemiky (C3220) Operátory new a delete, virtuální metody

20. Projekt Domácí mediotéka

4. ZÁKLADNÍ POJMY Z OBJEKTOVĚ ORIENTOVANÉHO PROGRAMOVÁNÍ

Programování v C++ 1, 1. cvičení

Obsah. Předmluva 13 Zpětná vazba od čtenářů 14 Zdrojové kódy ke knize 15 Errata 15

Pokročilé programování v jazyce C pro chemiky (C3220) Pokročilá témata jazyka C++

Pokročilé programování v jazyce C pro chemiky (C3220) Statické proměnné a metody, šablony v C++

Programování v Javě I. Leden 2008

Zpracoval:

Základy objektové orientace I. Únor 2010

Programování v C++ VI

Jazyk C++ I. Polymorfismus

Teoretické minimum z PJV

Dynamická identifikace typů v C++.

Ukazatele, dynamická alokace

Programování v Javě I. Únor 2009

Programování II. Návrh programu II

C++ přetěžování funkcí a operátorů. Jan Hnilica Počítačové modelování 19

Ukazka knihy z internetoveho knihkupectvi

Osnova přednášky. Programové prostředky řízení Úvod do C# II. Přístup ke členům. Členy (Members)

Počítačové laboratoře bez tajemství aneb naučme se učit algoritmizaci a programování s využitím robotů CZ.1.07/1.3.12/

8 Třídy, objekty, metody, předávání argumentů metod

Bridge. Známý jako. Účel. Použitelnost. Handle/Body

Definice třídy. úplná definice. public veřejná třída abstract nesmí být vytvářeny instance final nelze vytvářet potomky

Programování v C++ 2, 7. cvičení

1. Dědičnost a polymorfismus

Programování v C++ 2, 8. cvičení

Dědičnost. Karel Richta a kol. katedra počítačů FEL ČVUT v Praze. Karel Richta, Aleš Hrabalík a Martin Hořeňovský, 2016

Transkript:

PB161 Programování v jazyce C++ Přednáška 3 Reference, const Přetěžování funkcí Statické atributy a metody Dědičnost a kompozice Nikola Beneš 5. října 2015 PB161 přednáška 3: reference, const, přetěžování, static, dědičnost 5. října 2015 1 / 56

Organizační Vnitrosemestrální test v době přednášky 2. 11. 2015 dvě skupiny (12 13, 13 14) papírový odpovědník, max. 20 bodů náplň předchozích přednášek PB161 přednáška 3: reference, const, přetěžování, static, dědičnost 5. října 2015 2 / 56

Reference, const PB161 přednáška 3: reference, const, přetěžování, static, dědičnost 5. října 2015 3 / 56

Motivace void swap(int * x, int * y) { int temp = *x; *x = *y; *y = temp; } swap(&a, &b); Problémy s ukazateli neinicializovaný ukazatel NULL (v C++11 nullptr) Odbočka: Proč nullptr? PB161 přednáška 3: reference, const, přetěžování, static, dědičnost 5. října 2015 4 / 56

Reference Syntax: typ & proměnná alternativní jméno pro objekt/proměnnou (alias) int a = 1; int b = 2; int & refa = a; // refa je reference na a int & refa2 = a; // refa2 je také reference na a int & ref; // CHYBA! a += 9; refa += 17; refa2 += 15; // teď je v proměnné a hodnota 42 PB161 přednáška 3: reference, const, přetěžování, static, dědičnost 5. října 2015 5 / 56

Reference vs. ukazatele Reference musí být inicializovaná int * ptr; // OK int & ref; // CHYBA! PB161 přednáška 3: reference, const, přetěžování, static, dědičnost 5. října 2015 6 / 56

Reference vs. ukazatele Reference musí být inicializovaná int * ptr; // OK int & ref; // CHYBA! Reference vždy odkazuje na skutečný objekt int * ptr = nullptr; // s referencemi nic takového nejde PB161 přednáška 3: reference, const, přetěžování, static, dědičnost 5. října 2015 6 / 56

Reference vs. ukazatele Reference musí být inicializovaná int * ptr; // OK int & ref; // CHYBA! Reference vždy odkazuje na skutečný objekt int * ptr = nullptr; // s referencemi nic takového nejde Reference se nedá přesměrovat int a = 1, b = 2; int * ptr = &a; // ptr ukazuje na a ptr = &b; // teď ptr ukazuje na b int & ref = a; // ref je reference na a ref = b; // do proměnné a se vloží hodnota 2 ref = &b; // CHYBA! PB161 přednáška 3: reference, const, přetěžování, static, dědičnost 5. října 2015 6 / 56

Reference vs. ukazatele (pokr.) není možno se přímo odkazovat na proměnnou typu reference reference skutečně funguje jako alias int * ptr = &a; fun1(ptr); // funkci fun1 se předal ukazatel ptr int & ref = a; fun2(ref); // funkci fun2 se předala proměnná a fun2(a); // stejný efekt jako předchozí řádek PB161 přednáška 3: reference, const, přetěžování, static, dědičnost 5. října 2015 7 / 56

Reference: použití Bezpečnější alternativa ukazatelů Předávání parametrů referencí umožňuje měnit hodnotu proměnné void swap(int & x, int & y) { int temp = x; x = y; y = temp; } int a = 3; int b = 7; swap(a, b); PB161 přednáška 3: reference, const, přetěžování, static, dědičnost 5. října 2015 8 / 56

Konstantní reference klíčové slovo const int a = 3; const int & refa = a; cout << refa; // OK, vypíše 3 a = 7; // OK, hodnota a je 7 refa = 17; // CHYBA! refa je konstantní PB161 přednáška 3: reference, const, přetěžování, static, dědičnost 5. října 2015 9 / 56

Konstantní reference: použití Předávání větších objektů deklarujeme záměr neměnit proměnnou (read-only) void comparepersons(const Person & p1, const Person & p2) { cout << p1.name << " is "; if (p1.age < p2.age) cout << "younger than"; else if (p1.age > p2.age) cout << "older than"; else cout << "the same age as"; cout << p2.name << endl; } PB161 přednáška 3: reference, const, přetěžování, static, dědičnost 5. října 2015 10 / 56

Konstantní reference: použití (pokr.) Předávání konstantní referencí vs. hodnotou void f1(bigobject x) { /*... */ } void f2(const BigObject & x) { /*... */ } BigObject y; f1(y); f2(y); // vytvoří kopii objektu y // nevytváří kopii, předává konstantní referenci Poznámka: situace je trochu složitější (optimalizace v překladačích, C++11 a move semantics, apod.) PB161 přednáška 3: reference, const, přetěžování, static, dědičnost 5. října 2015 11 / 56

Reference a (l/p)-hodnoty l-hodnoty vs. p-hodnoty l-hodnota (l-value) je něco, co může stát na levé straně přiřazení má to adresu p-hodnota (r-value) je něco, co může stát na pravé straně přiřazení např. číselná hodnota, dočasný objekt konstantní reference chytá všechno, nekonstantní jen l-hodnoty void lfun(int & x); void rfun(const int & x); int a = 7; lfun(a); lfun(17); rfun(a); rfun(17); // OK // CHYBA! // OK // OK PB161 přednáška 3: reference, const, přetěžování, static, dědičnost 5. října 2015 12 / 56

Reference jako návratová hodnota reference je možno i vracet, jsou to l-hodnoty (pokud nejsou konstantní) int & fun(int & x) { x += 17; return x; } int y = 10; fun(y) = 25; // v tuto chvíli je v y hodnota 25 PB161 přednáška 3: reference, const, přetěžování, static, dědičnost 5. října 2015 13 / 56

Reference jako atributy Jak inicializovat? class Dog { Person & owner; public: Dog(Person & o) { owner = o; // CHYBA! } PB161 přednáška 3: reference, const, přetěžování, static, dědičnost 5. října 2015 14 / 56

Reference jako atributy Jak inicializovat? class Dog { Person & owner; public: Dog(Person & o) { owner = o; // CHYBA! } je třeba použít inicializační sekci konstruktoru: class Dog { Person & owner; public: Dog(Person & o) : owner(o) {} PB161 přednáška 3: reference, const, přetěžování, static, dědičnost 5. října 2015 14 / 56

Konstatní metody const za seznamem parametrů class Person { std::string name; int age; public: void setage(int a) { age = a; } int getage() const { return age; } konstantní metody se zavazují neměnit vnitřní stav objektu (hlídá překladač) PB161 přednáška 3: reference, const, přetěžování, static, dědičnost 5. října 2015 15 / 56

Konstantní metody a reference void funr(const Person & person) { cout << person.getage(); // OK person.setage(18); // CHYBA! } stejně to funguje s ukazateli void funp(const Person * person) { if (person) { cout << person->getage(); person->setage(42); } } // OK // CHYBA! doporučení: označovat jako const všechny metody, které nehodlají měnit vnitřní stav objektu PB161 přednáška 3: reference, const, přetěžování, static, dědičnost 5. října 2015 16 / 56

Přetěžování funkcí PB161 přednáška 3: reference, const, přetěžování, static, dědičnost 5. října 2015 17 / 56

Přetěžování (overloading) různé funkce/metody se stejným jménem, ale různou implementací musí se lišit typem nebo počtem parametrů nebo const void f(int x) { cout << "f s parametrem int: " << x << endl; } void f() { cout << "f bez parametrů" << endl; } void f(double d) { cout << "f s parametrem double: " << d << endl; } f(3); // zavolá void f(int) f(5.0); // zavolí void f(double) f(); // zavolá void f() Pozor! V C++ nestačí, pokud se liší pouze návratovým typem; proč? PB161 přednáška 3: reference, const, přetěžování, static, dědičnost 5. října 2015 18 / 56

Přetěžování (overloading) pokr. Pravidla pro přetěžování přesná shoda rozšíření typu typové konverze, class File { //... public: void write(int num); void write(std::string str); //... File f; //... f.write("hello"); // volá File::write(std::string) f.write(0.0); // volá File::write(int); PB161 přednáška 3: reference, const, přetěžování, static, dědičnost 5. října 2015 19 / 56

Přetěžování a reference nekonstantní reference má přednost void f(int &); void f(const int &); int x; f(x); // zavolá se první funkce f(5); // zavolá se druhá funkce int & ref = x; const int & cref = x; f(ref); // první f(cref); // druhá přetěžování pro referenci a hodnotu nejednoznačnost (ambiguity) PB161 přednáška 3: reference, const, přetěžování, static, dědičnost 5. října 2015 20 / 56

Přetěžování a NULL v C++03: NULL je definováno jako 0 void f(int x); void f(char * s); f(null); // zavolá se PRVNÍ funkce! proto máme v C++11 speciální ukazatel nullptr f(nullptr); // OK, zavolá se druhá funkce NULL může být v C++11 definováno různě, proto je lépe jej nepoužívat a zvyknout si na používání nullptr PB161 přednáška 3: reference, const, přetěžování, static, dědičnost 5. října 2015 21 / 56

Přetěžování Pro zvídavé: Jak to ve skutečnosti funguje? překladač C++ mění jména funkcí, přidává k nim typy parametrů tzv. name mangling není žádný standard, závisí na konkrétním překladači příklad (gcc): void fun(int, char) _Z3funic int fun(int &) _Z3funRi PB161 přednáška 3: reference, const, přetěžování, static, dědičnost 5. října 2015 22 / 56

Implicitní parametry Parametry s implicitní hodnotou funkce, metody, konstruktory, musí být nejvíce vpravo v seznamu parametrů void f(int x, int y = 10, int z = 20); f(3, 4, 5); // zavolá se f(3, 4, 5) f(3, 4); // zavolá se f(3, 4, 20) f(3); // zavolá se f(3, 10, 20) void g(int x = 10, int y); // chyba! PB161 přednáška 3: reference, const, přetěžování, static, dědičnost 5. října 2015 23 / 56

Implicitní parametry (pokr.) Oddělení deklarace a definice // soubor.h void f(int = 10, int = 20); // soubor.cpp void f(int x /* = 10 */, int y /* = 20 */) { //... } PB161 přednáška 3: reference, const, přetěžování, static, dědičnost 5. října 2015 24 / 56

Statické atributy a metody položky tříd patří objektům (instancím třídy) statické položky třídy: patří třídě samotné; nepatří žádnému objektu objekty k nim mohou přistupovat class Person { std::string name; int age; static int count; public: Person(std::string n, int a) : name(n), age(a) { ++count; } //... static int getcount { return count; } PB161 přednáška 3: reference, const, přetěžování, static, dědičnost 5. října 2015 30 / 56

Statické atributy a metody (pokr.) Inicializace statických atributů: mimo deklaraci třídy int Person::count = 0; Person franta("franta", 20); Person pepa("pepa", 21); Person jimmy("james Bond", 42); Volání statické metody bez konkrétního objektu cout << Person::getCount() << endl; // vypíše 3 PB161 přednáška 3: reference, const, přetěžování, static, dědičnost 5. října 2015 31 / 56

Statické atributy a metody (pokr.) Příklad použití statických atributů: automatické přidělování ID class Thing { int id; static int id_generator; public: Thing() : id(id_generator++) {} int getid() const { return id; } int Thing::id_generator = 0; Thing t1; Thing t2; Thing t3; // t3.getid() vrátí 2 PB161 přednáška 3: reference, const, přetěžování, static, dědičnost 5. října 2015 32 / 56

Dědičnost a kompozice PB161 přednáška 3: reference, const, přetěžování, static, dědičnost 5. října 2015 33 / 56

Motivace: Rozhraní Příklad: tiskárny // interface (čistě abstraktní třída bez atributů) class IPrinter { public: virtual std::string GetPendingDocuments() const = 0; virtual void PrintDocument(const string & document) = 0; virtual ~IPrinter() {} // konkrétní třída class HPLaserJet : public IPrinter { //... public: HPLaserJet(); std::string GetPendingDocuments() const; void PrintDocument(const string & document); ~HPLaserJet(); PB161 přednáška 3: reference, const, přetěžování, static, dědičnost 5. října 2015 34 / 56

Motivace: Rozhraní (pokr.) Použití rozhraní IPrinter IPrinter * printer = new HPLaserJet(); printer->printdocument("top_secret.txt"); //... delete printer; Poznámka: o new a delete si řekneme příště PB161 přednáška 3: reference, const, přetěžování, static, dědičnost 5. října 2015 35 / 56

Motivace: hierarchie abstrakce inkoustové a laserové tiskárny se od sebe liší, uvnitř těchto skupin je ale mnoho vlastností společných class InkPrinter : public IPrinter { //... class LaserPrinter : public IPrinter { //... class HPLaserJet : public LaserPrinter { //... PB161 přednáška 3: reference, const, přetěžování, static, dědičnost 5. října 2015 36 / 56

Dědičnost v C++ třída může dědit od jedné nebo více tříd Specifikátory přístupových práv public: zděděné položky dědí práva od předka protected: veřejné zděděné položky se měni na protected private: všechny zděděné položky se mění na private bez specifikátoru: u class jako private, u struct jako public virtual: lze kombinovat s jedním z předchozích, řeší problémy s vícenásobnou dědičností PB161 přednáška 3: reference, const, přetěžování, static, dědičnost 5. října 2015 37 / 56

Dědičnost a přístupová práva class A { public: // veřejné, vidí všichni int x; protected: // vidí potomci int y; private: // soukromé, vidí jen instance třídy A int z; class B : public A { /*... */ class C : protected A { /*... */ class D : private A { /*... */ PB161 přednáška 3: reference, const, přetěžování, static, dědičnost 5. října 2015 38 / 56

Dědičnost a reference víme: ukazateli na předka můžeme předat potomka podobně to funguje i s referencemi class Animal { /*... */ class Dog : public Animal { /*... */ class Person { //... public: void playwith(const Animal & animal); //... Person tommy; Dog lassie; tommy.playwith(lassie); PB161 přednáška 3: reference, const, přetěžování, static, dědičnost 5. října 2015 39 / 56

Dědičnost: vazba Časná vazba class Animal { public: void makesound() const { std::cout << "<generic sound>\n"; } class Dog : public Animal { public: void makesound() const { std::cout << "Whoof!\n"; } Dog lassie; Animal & refanimal = lassie; Animal * ptranimal = &lassie; lassie.makesound(); // "Whoof!" refanimal.makesound(); // "<generic sound>" ptranimal->makesound(); // "<generic sound>" PB161 přednáška 3: reference, const, přetěžování, static, dědičnost 5. října 2015 40 / 56

Dědičnost: vazba (pokr.) Pozdní vazba class Animal { public: virtual void makesound() const { std::cout << "<generic sound>\n class Dog : public Animal { public: // zde může i nemusí být virtual virtual void makesound() const { std::cout << "Whoof!\n"; } Dog lassie; Animal & refanimal = lassie; Animal * ptranimal = &lassie; lassie.makesound(); // "Whoof!" refanimal.makesound(); // "Whoof!" ptranimal->makesound(); // "Whoof!" PB161 přednáška 3: reference, const, přetěžování, static, dědičnost 5. října 2015 41 / 56

Dědičnost: vazba (pokr.) Pozor! typ předefinované metody musí být úplně stejný včetně const class Animal { public: virtual void makesound() const { std::cout << "<generic sound>\n class Dog : public Animal { public: // deklarujeme NOVOU metodu, která skrývá tu starou! virtual void makesound() { std::cout << "Whoof!\n"; } Dog lassie; Animal & refanimal = lassie; Animal * ptranimal = &lassie; lassie.makesound(); // "Whoof!" refanimal.makesound(); // "<generic sound>" ptranimal->makesound(); // "<generic sound>" PB161 přednáška 3: reference, const, přetěžování, static, dědičnost 5. října 2015 42 / 56

Overloading, overriding, hiding Přetěžování (overloading) deklarace několika metod se stejným názvem a různými parametry Předefinování (overriding) nahrazení definice virtuální metody ve třídě předka novou definicí ve třídě potomka Skrývání (hiding) v potomkovi deklarujeme metodu stejného jména jako v předkovi a buď není virtuální nebo má jiné parametry, případně se liší kvalifikátorem const PB161 přednáška 3: reference, const, přetěžování, static, dědičnost 5. října 2015 43 / 56

Overloading, overriding, hiding (pokr.) class Account { //... public: virtual void deposit(double amount); virtual std::string tostring() const; virtual std::string tostring(char delim) const; class InsecureAccount : public Account { //... public: virtual void deposit(double amount, Date date); virtual std::string tostring() const; PB161 přednáška 3: reference, const, přetěžování, static, dědičnost 5. října 2015 44 / 56

Overloading, overriding, hiding (pokr.) InsecureAccount iacc; Account & refacc = iacc; iacc.deposit(3.50); // chyba! refacc.deposit(3.50); // OK(?), volá Account::deposit(double) string s = refacc.tostring(); // OK, volá se InsecureAccount::toString() s = iacc.tostring(','); // chyba! Jak zabránit skrytí metody tostring(char)? class InsecureAccount : Account { //... public: using Account::toString; //... PB161 přednáška 3: reference, const, přetěžování, static, dědičnost 5. října 2015 45 / 56

Overriding v C++11 Specifikátor override umožňuje explicitně sdělit, že zamýšlíme metodu předefinovat class Animal { public: virtual void makesound() const { std::cout << "<generic animal sound>\n"; } class Dog : public Animal { public: void makesound() override { // chyba při překladu std::cout << "Whoof!\n"; } PB161 přednáška 3: reference, const, přetěžování, static, dědičnost 5. října 2015 46 / 56

Overriding v C++11 Specifikátor final metoda nesmí být předefinována; od třídy se nesmí dědit class A { public: virtual void f() final; class B : public A { public: void f(); // CHYBA! při překladu class D { /*... */ class E final : public D { /*... */ class F : public E { /*... */ // CHYBA! při překladu PB161 přednáška 3: reference, const, přetěžování, static, dědičnost 5. října 2015 47 / 56

Virtuální metody Doporučení pro virtuální metody rozmyslete si, zda má být daná metoda virtuální bude se od dané třídy dědit? je metoda určena k tomu, aby ji potomci předefinovali? pokud ano, pak: v předkovi pište virtual v potomcích můžete a nemusíte psát virtual, je ale vhodné psát override (ušetří vám to spoustu problémů) PB161 přednáška 3: reference, const, přetěžování, static, dědičnost 5. října 2015 48 / 56

Abstraktní třídy, rozhraní Abstraktní třída má alespoň jednu čistě virtuální metodu (speciální syntaxe = 0) nelze vytvářet instance class Abstract { public: virtual void method() = 0; //... virtual ~Abstract() {} Čistě abstraktní třída všechny metody jsou čistě virtuální (s případnou výjimkou destruktoru) Rozhraní (interface) čistě abstraktní třída bez atributů deklaruje pouze metody, které bude možno volat PB161 přednáška 3: reference, const, přetěžování, static, dědičnost 5. října 2015 49 / 56

Vícenásobná dědičnost kontroverzní, výhody i nevýhody použití v případech, kdy jeden objekt má více charakteristik časté použití spolu s rozhraními (interfaces) class IPrinter { /*... */ class IScanner { /*... */ class Copier : public IPrinter, public IScanner { /*... */ pokud se jednotliví předkové funkčně nepřekrývají, nemusí dojít k problémům class Animal { /*... */ class FlyingAnimal : public Animal { /*... */ class Mammal : public Animal { /*... */ class Bat : public Mammal, public FlyingAnimal { /*... */ PB161 přednáška 3: reference, const, přetěžování, static, dědičnost 5. října 2015 50 / 56

Vícenásobná dědičnost: problém diamantu class Animal { int weight; public: int getweight() const { return weight; } //... FlyingAnimal, Mammal, Bat jako předtím... Bat thebat; thebat.getweight(); // CHYBA! není jasné, která getweight() // se má volat Animal * animal = &thebat; // CHYBA! není jasné, // jak přetypovat PB161 přednáška 3: reference, const, přetěžování, static, dědičnost 5. října 2015 51 / 56

Vícenásobná dědičnost: problém diamantu (pokr.) Řešení: virtuální dědičnost class FlyingAnimal : virtual public Animal { /*... */ class Mammal : virtual public Animal { /*... */ Nevýhody: všichni potomci Animal musí Animal inicializovat volání metod Animal a přetypování je složitější a pomalejší Alternativy: změna hierarchie kompozice místo dědičnosti PB161 přednáška 3: reference, const, přetěžování, static, dědičnost 5. října 2015 52 / 56

Kompozice Dědičnost je vztah IS-A potomek má všechny vnější vlastnosti předka potomka je možno přetypovat na předka Kompozice je vztah HAS-A třída může mít jako atribut další třídu (hodnotou, referencí, ukazatelem) třída může mít i víc tříd jako atributy třída tím obsahuje všechny vlastnosti těchto tříd ale není jejich potomkem, nemůže je zastoupit PB161 přednáška 3: reference, const, přetěžování, static, dědičnost 5. října 2015 53 / 56

// kompozice class Laptop { CPU m_cpu; RAM m_ram; public: Laptop(unsigned cpufreq, unsigned ramsize) : m_cpu(cpufreq), m_ram(ramsize) {} unsigned getcpufreq() const { return m_cpu.getcpufreq(); } unsigned getramsize() const { return m_ram.getramsize(); } //... } PB161 přednáška 3: reference, const, přetěžování, static, dědičnost 5. října 2015 54 / 56 Kompozice (pokr.) Příklad // dědičnost, v tomto případě spíš nevhodná class Laptop : public CPU, public RAM { /*... */

Kompozice vs. dědičnost Vhodnost použití kompozice a dědičnosti obecně spíše preferovat kompozici dědičnost tam, kde to dává smysl kompozice může být kódově rozsáhlejší možná i kombinace obou přístupů PB161 přednáška 3: reference, const, přetěžování, static, dědičnost 5. října 2015 55 / 56

Shrnutí Reference alternativa k ukazatelům, použití pro volání odkazem Přetěžování funkcí a metod musí se lišit počtem nebo typy parametrů nebo const Statické atributy a metody patří třídě samotné, ne instancím (ty k nim mohou přistupovat) Dědičnost přístupová práva časná a pozdní vazba overloading X overriding X hiding abstraktní třídy a rozhraní vícenásobná dědičnost kompozice jako alternativa dědičnosti PB161 přednáška 3: reference, const, přetěžování, static, dědičnost 5. října 2015 56 / 56