Dynamika objektů. Karel Richta a kol. katedra počítačů FEL ČVUT v Praze

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

Konstruktory a destruktory

Přetěžování operátorů, dynamika objektů 2

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

Více o konstruktorech a destruktorech

Datové struktury. alg12 1

Datové struktury. Obsah přednášky: Definice pojmů. Abstraktní datové typy a jejich implementace. Algoritmizace (Y36ALG), Šumperk - 12.

Mělká a hluboká kopie

PREPROCESOR POKRAČOVÁNÍ

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

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

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

Abstraktní datové typy

Dědění, polymorfismus

Ukazatele, dynamická alokace

Generické programování

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

Programování II. Návrh programu I 2018/19

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

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

Základy objektové orientace I. Únor 2010

IB111 Programování a algoritmizace. Objektově orientované programování (OOP)

Jazyk C++ I. Šablony 2

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

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

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

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

konstruktory a destruktory (o)

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

Základní datové struktury

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.

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

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

Základní pojmy. Úvod do programování. Základní pojmy. Zápis algoritmu. Výraz. Základní pojmy

ADT/ADS = abstraktní datové typy / struktury

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

Abstraktní datové typy: zásobník

IUJCE 07/08 Přednáška č. 6

Úvod do programovacích jazyků (Java)

Jazyk C# (seminář 6)

Abstraktní třídy, polymorfní struktury

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

Teoretické minimum z PJV

Sdílení dat mezi podprogramy

Pokročilé programování v jazyce C pro chemiky (C3220) Třídy v C++

Základy C++ I. Jan Hnilica Počítačové modelování 18

PROMĚNNÉ, KONSTANTY A DATOVÉ TYPY TEORIE DATUM VYTVOŘENÍ: KLÍČOVÁ AKTIVITA: 02 PROGRAMOVÁNÍ 2. ROČNÍK (PRG2) HODINOVÁ DOTACE: 1

Kolekce, cyklus foreach

Výrazy, operace, příkazy

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

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

Správa paměti. Karel Richta a kol. Katedra počítačů Fakulta elektrotechnická České vysoké učení technické v Praze Karel Richta, 2016

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

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

Programování v jazyce C a C++

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

Jazyk C++ I. Šablony

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

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

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

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

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

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

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

Programování v jazyce C a C++

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

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

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

PROGRAMOVÁNÍ V C++ CVIČENÍ

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

Spojová implementace lineárních datových struktur

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

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

Programování II. Polymorfismus

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

Objektově orientované programování. Úvod

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

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

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

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

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

Objektové programování

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

Algoritmizace prostorových úloh

7. přednáška - třídy, objekty třídy objekty atributy tříd metody tříd

Dědičnost (inheritance)

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

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

Lineární datové struktury

Výčtový typ strana 67

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

Správné vytvoření a otevření textového souboru pro čtení a zápis představuje

ZPRO v "C" Ing. Vít Hanousek. verze 0.3

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

int ii char [16] double dd název adresa / proměnná N = nevyužito xxx xxx xxx N xxx xxx N xxx N

Zpracoval:

1. Programování proti rozhraní

Zápis programu v jazyce C#

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

C++ objektově orientovaná nadstavba programovacího jazyka C

Transkript:

Dynamika objektů Karel Richta a kol. katedra počítačů FEL ČVUT v Praze Přednášky byly připraveny s pomocí materiálů, které vyrobili Ladislav Vágner, Pavel Strnad Karel Richta, Martin Hořeňovský, Aleš Hrabalík, 2016 Programování v C++, A7B36PJC 03/2016, Lekce 5 https://cw.fel.cvut.cz/wiki/courses/a7b36pjc/start

Třídy vs Instance Třída je abstraktní popis nějaké celku. Data + operace nad daty Například osoba může obsahovat řetězec jméno Zároveň definuje metody které umožní například získat příjmení Instance se tvoří z třídy a obsahuje konkrétní data Instance může obsahovat jméno Vincent van Gogh getlastname() umožní získat van Gogh 2

Proč objekty? Zapouzdření (kód je pohromadě se zpracovávanými daty): Uživatel nespoléhá na detaily implementace. Zvýšení bezpečnosti a robustnosti, zamezení nekorektního použití. Usnadnění budoucích modifikací. Polymorfismus (objekty jsou zaměnitelné) Volání metody na objektu je poslání zprávy, že se má něco vykonat. Objekt sám rozhodne, jak na zprávu zareaguje. Objekty různých typů mohou na stejnou zprávu reagovat různě. Dědičnost: Tvorba nových tříd na základě stávajících disciplinovaným způsobem. Mohu přidat data a metody, případně měnit existující metody. 3

Zásobník Zásobník (stack) je abstraktní datový typ, který umožňuje vkládání a odebírání hodnot, přičemž naposledy vložená hodnota se odebere jako první. Zásobník je paměť typu LIFO (zkratka z angl. last-in first-out, poslední dovnitř, první ven). Základní operace: vložení hodnoty na vrchol zásobníku, v angličtině obvykle push odebrání hodnoty z vrcholu zásobníku, v angličtině obvykle pop test na prázdnost zásobníku, v angličtině obvykle is_empty 4

Deklarace třídy a definice metod using zas_typ = int; class zasobnik { public: zasobnik(int max_prvku); zas_typ vezmi(); void vloz(zas_typ prvek); bool je_prazdny(); private: int max_velikost; int aktualni_pozice; zas_typ* prvky; ; zasobnik::zasobnik(int max_prvku){ max_velikost = max_prvku; aktualni_pozice = 0; prvky = new zas_typ[max_prvku]; bool zasobnik::je_prazdny() { return aktualni_pozice == 0; 5

Datové položky, metody, viditelnost Členská data a metody mají jednu ze 3 možných viditelností Private (soukromé) pouze metody daného objektu mají přístup Protected (chráněné) metody daného objektu a dědících objektů mají přístup Public (veřejné) volný přístup odkudkoliv Výchozí viditelnost je private pro třídy (class) a public pro struct. int main() { zasobnik z; //z.aktualni_pozice == 0; // nelze z.je_prazdny(); // OK //z.prvky[0] = 1; // nelze z.vloz(1); // OK 6

Členské funkce třídy Funkce uvedené v deklaraci třídy se jmenují členské funkce třídy (member functions) nebo metody Metody s viditelností public tvoří veřejné rozhraní třídy a dají se volat odkudkoliv Metody, které nechceme zpřístupňovat, mají viditelnost private. Metody třídy jsou zodpovědné za udržení invariant třídy. void zasobnik::vloz(zas_typ prvek) { if (aktualni_pozice == max_velikost) { throw std::runtime_error("zasobnik je plny"); prvky[aktualni_pozice++] = prvek; bool zasobnik::je_prazdny() { return aktualni_pozice == 0; 7

Vložené členské metody (definice v deklaraci) Metoda může být v těle třídy nejen deklarována, ale i definována. Takové metodě se říká vložená (inline) a je implicitně označena inline Používá se pro jednoduché funkce. Ekvivalentní s použítím inline v deklaraci (uvnitř hlavičky). class zasobnik { public: zasobnik(int max_prvku); bool je_prazdny() { return aktualni_pozice == 0; ; // Stejné, jako: inline bool zasobnik::je_prazdny() { return aktualni_pozice == 0; 8

Konstruktor Konstruktor je metoda, která vytvoří instanci třídy a nastaví její invarianty. Jmenuje se stejně jako třída a nemá návratový typ. Může být přetížen jako standardní funkce (metoda). Specifické signatury mají specifické jméno: T() tzv. základní (default) konstruktor, T(const T&) tzv. kopírující (copy) konstruktor, T(T&&) tzv. přesunující (move) konstruktor, Více viz později. Konstruktor je volán vždy při vytvoření objektu. Konstruktor je volán pouze při vytvoření objektu. 9

Příklad class zasobnik { public: zasobnik(int max_prvku);... private: int max_velikost; int aktualni_pozice; zas_typ* prvky; ; zasobnik::zasobnik(int max_prvku) { max_velikost = max_prvku; aktualni_pozice = 0; prvky = new zas_typ[max_velikost]; int main() { zasobnik z1(100); // do zásobníku z1 se vejde 100 prvků zasobnik z2(10); // do zásobníku z2 se vejde 10 prvků 10

Konstruktor inicializační sekce Probíhá před vykonáním těla konstruktoru. Přímá inicializace členských proměnných, důležité například pro konstantní proměnné a reference. Jednotlivé proměnné se inicializují v pořadí, v jakém jsou zmíněny v definici, ne v pořadí v jakém jsou zmíněny v inicializační sekci. Též se může použít pro předání argumentů konstruktoru rodiče. Doporučujeme v inicializační sekci inicializovat všechny proměnné. zasobnik::zasobnik(int max_prvku): max_velikost(max_prvku), aktualni_pozice(0), prvky(new zas_typ[max_velikost]) { 11

Základní konstruktor (default) Pokud programátor nevytvořil svůj konstruktor, je základní konstruktor definován překladačem. Pokud to jde, doporučujeme ho vždy vytvořit. Pokud programátor definoval jiný konstruktor, měl by definovat i základní konstruktor. Nebere žádné argumenty, ale může používat implicitní hodnoty argumentů. class zasobnik { public: zasobnik(int max_prvku = 20);... ; int main() { zasobnik z1; // do zasobniku se vejde 20 prvku 12

Přetížení a delegace konstruktorů Konstruktory lze přetěžovat stejným způsobem jako funkce Konstruktory mohou volat ostatní konstruktory. (Delegace) Základní konstruktor lze snadno řešit jako delegující konstruktor struct vec3 { int x, y, z; vec3(): vec3(0, 0, 0) { vec3(int x, int y): vec3(x, y, 0) { vec3(int x, int y, int z): x(x), y(y), z(z) { ; int main() { vec3 v1; // Nulový vektor vec3 v2(1, 2); // Varianta s dvěmi argumenty vec3 v3(1, 2, 3); // Varianta s třemi argumenty 13

Destruktor Destruktor je inverzní funkce ke konstruktoru, stará se o zrušení invariant. Jeho signatura je vždy ~T(), pro dané T může existovat pouze jeden. Pokud není explicitně definován, kompilátor ho doplní. Pro každý zkonstruovaný objekt se někdy musí provést destruktor. Pokud k tomu nedojde, je to chyba. class zasobnik {... public: ~zasobnik() { delete[] prvky; ; 14

Destruktor Destruktor nelze volat explicitně v programu. Je volán při ukončení platnosti objektu: Globální nebo statický objekt na konci programu. Dynamický objekt řídí uživatel (operátory new a delete). Automatický objekt ukončen na konci bloku, kde byl definován. class zasobnik {... public: ~zasobnik(); ; zasobnik::~zasobnik() { delete[] prvky; 15

Automatické volání destruktorů Jak jsme si již řekli, automatické proměnné žijí na zásobníku. Programový zásobník funguje podobně jako klasický zásobník. Ve chvíli definice proměnné se spustí její konstruktor a po jeho proběhnutí je vložena na zásobník. Ve chvíli kdy skončí blok, je každá proměnná v něm definovaná vytažena ze zásobníku a je zavolán její destruktor. Toto probíhá zcela automaticky! 16

Animace <Anim 1> 17

Příklad <příklad 2> 18

RAII Jedná se o základní koncept C++ programování. Obvykle Resource Allocation Is Initialization My preferujeme Responsibility Acquisition Is Initialization Myšlenka: Při svém vzniku získá objekt nějakou zodpovědnost. Při svém zániku tuto zodpovědnost musí naplnit. std::vector má zodpovědnost za alokovanou paměť a naplní ji dealokací své paměti. Zodpovědnost může mít mnoho podob. std::fstream otevírá a zavírá soubor. 19

RAII Příklad Některé z příkazů return v následujícím kódu způsobí, že se chybně nezavolá fclose. Které? void Data::prectiZeSouboru(const char* nazevsouboru) { FILE* fp = std::fopen(nazevsouboru, "r"); if (!fp) return; int pocetpolozek; if (std::fscanf(fp, "%d", &pocetpolozek)!= 1) return; for (int i = 0; i < pocetpolozek; ++i) { int polozka; if (std::fscanf(fp, "%d", &polozka)!= 1) return; vec.push_back(polozka); std::fclose(fp); 20

RAII Příklad Některé z příkazů return v následujícím kódu způsobí, že se chybně nezavolá fclose. Které? void Data::prectiZeSouboru(const char* nazevsouboru) { FILE* fp = std::fopen(nazevsouboru, "r"); if (!fp) return; int pocetpolozek; if (std::fscanf(fp, "%d", &pocetpolozek)!= 1) return; for (int i = 0; i < pocetpolozek; ++i) { int polozka; if (std::fscanf(fp, "%d", &polozka)!= 1) return; vec.push_back(polozka); std::fclose(fp); 21 { std::fclose(fp); return;

RAII Příklad class FileSentry { public: FileSentry(FILE* in) : fp(in) { ~FileSentry() { fclose(fp); private: FILE* fp; ; void Data::prectiZeSouboru(const char* nazevsouboru) { FILE* fp = std::fopen(nazevsouboru, "r"); if (!fp) return; FileSentry sentry(fp); int pocetpolozek; if (std::fscanf(fp, "%d", &pocetpolozek)!= 1) return; for (int i = 0; i < pocetpolozek; ++i) { int polozka; if (std::fscanf(fp, "%d", &polozka)!= 1) return; vec.push_back(polozka); std::fclose(fp); 22

Odbočka k new a delete Operátor new alokuje paměť a spustí konstruktor typu. Uživatel ale dostane pointer na typ a destruktor pointeru je prázdná operace. Operátor delete paměť dealokuje a spustí destruktor typu. Pokud uživatel ale o pointer přijde, nebo na něj zapomene, destruktor se nikdy nezavolá. Této situaci říkáme memory leak. Nejde to lépe? 23

Příklad: memory leak zasobnik* vytvorzretezce(const char* str) { int len = std::strlen(str); zasobnik* z = new zasobnik(len); for (int i = 0; i < len; i++) { z->vloz(str[i]); return z; void vypisobracene(const char* str) { zasobnik* zas = vytvorzretezce(str); while (!zas->je_prazdny()) { std::cout << (char)zas->vezmi(); std::cout << '\n'; 24

Příklad: memory leak zasobnik* vytvorzretezce(const char* str) { int len = std::strlen(str); zasobnik* z = new zasobnik(len); for (int i = 0; i < len; i++) { z->vloz(str[i]); return z; void vypisobracene(const char* str) { zasobnik* zas = vytvorzretezce(str); while (!zas->je_prazdny()) { std::cout << (char)zas->vezmi(); std::cout << '\n'; delete zas; 25

std::make_unique, std::unique_ptr Co kdyby operátor new nevracel T*, ale typ který po sobě uklidí? std::unique_ptr je typ ze standardní knihovny, který se chová jako pointer, ale jeho destruktor volá delete. std::make_unique vrací std::unique_ptr. Při použití unique_ptr není možné zapomenout na dealokaci. 26

Příklad: memory leak zasobnik* vytvorzretezce(const char* str) { int len = std::strlen(str); zasobnik* z = new zasobnik(len); for (int i = 0; i < len; i++) { z->vloz(str[i]); return z; void vypisobracene(const char* str) { zasobnik* zas = vytvorzretezce(str); while (!zas->je_prazdny()) { std::cout << (char)zas->vezmi(); std::cout << '\n'; delete zas; 27

Příklad: unique_ptr std::unique_ptr<zasobnik> vytvorzretezce(const char* str) { int len = std::strlen(str); std::unique_ptr<zasobnik> z(new zasobnik(len)); for (int i = 0; i < len; i++) { z->vloz(str[i]); return z; void vypisobracene(const char* str) { std::unique_ptr<zasobnik> zas = vytvorzretezce(str); while (!zas->je_prazdny()) { std::cout << (char)zas->vezmi(); std::cout << '\n'; 28

Příklad: unique_ptr std::unique_ptr<zasobnik> vytvorzretezce(const char* str) { int len = std::strlen(str); auto z = std::make_unique<zasobnik>(len); for (int i = 0; i < len; i++) { z->vloz(str[i]); return z; void vypisobracene(const char* str) { auto zas = vytvorzretezce(str); while (!zas->je_prazdny()) { std::cout << (char)zas->vezmi(); std::cout << '\n'; 29

struct vec3 { int x, y, z; vec3() : x(0), y(0), z(0) { vec3(int x, int y) : x(x), y(y), z(0) { vec3(int x, int y, int z) : x(x), y(y), z(z) { void tisk() { std::cout << "(" << x << "," << y << "," << z << ")\n"; ; int main() { auto v1 = std::make_unique<vec3>(); auto v2 = std::make_unique<vec3>(11, 22); auto v3 = std::make_unique<vec3>(33, 44, 55); auto v4 = std::make_unique<vec3[]>(4); v1->tisk(); v2->tisk(); v3->tisk(); for (int i = 0; i < 4; i++) { v4[i].tisk(); (0,0,0) (11,22,0) (33,44,55) (0,0,0) (0,0,0) (0,0,0) (0,0,0) 30

Příklad: memory leak bool prectipalindrom(file* fp) { int length; if (std::fscanf(fp, "%d", &length)!= 1) return false; char* str = new char[length + 1]; std::fscanf(fp, "%s", str); int first = 0; int last = length - 1; for (; first <= last; first++, last--) { if (str[first]!= str[last]) { return false; delete[] str; return true; 31

Příklad: memory leak bool prectipalindrom(file* fp) { int length; if (std::fscanf(fp, "%d", &length)!= 1) return false; char* str = new char[length + 1]; std::fscanf(fp, "%s", str); int first = 0; int last = length - 1; for (; first <= last; first++, last--) { if (str[first]!= str[last]) { return false; delete[] str; delete[] str; return true; 32

Příklad: unique_ptr bool prectipalindrom(file* fp) { int length; if (std::fscanf(fp, "%d", &length)!= 1) return false; auto str = std::make_unique<char[]>(length + 1); std::fscanf(fp, "%s", str.get()); int first = 0; int last = length - 1; for (; first <= last; first++, last--) { if (str[first]!= str[last]) { return false; delete[] str; return true; 33

Vylepšení zásobníku unique_ptr class zasobnik { public:... private:... std::unique_ptr<zas_typ[]> prvky; ; zasobnik::zasobnik(int max_prvku) : max_velikost(max_prvku), aktualni_pozice(0), prvky(std::make_unique<zas_typ[]>(max_velikost)) { zasobnik::~zasobnik() {... // Destruktor už není potřeba 34

Konstantní členská funkce jen dotaz Nemění stav objektu, jedná se jen o dotaz. Značí se klíčovým slovem const za seznamem argumentů. Může se volat i na konstantním objektu. class zasobnik { public: bool je_prazdny() const;... ; bool zasobnik::je_prazdny() const { return aktualni_pozice == 0; void funkce(const zasobnik& z) { z.je_prazdny(); // ok, volame const metodu //z.vezmi() // nelze, vezmi() neni const 35

Konstanta platná ve třídě Existují dva způsoby jak zadefinovat konstantu pro třídu. Starý způsob přes anonymní enumerátor a nový, pomocí static const proměnné. Použití enumerátoru umožňuje definování pouze integrálního typu. Preferujte static const proměnné. class viewport { public: enum konstanty { max_sirka = 1920, max_vyska = 1080, ; static const double pomer; void zmen_vysku(int nova_vyska) { m_vyska = nova_vyska; m_sirka = static_cast<int>(std::ceil(m_vyska * pomer)); int m_vyska, m_sirka; ; // Mimo třídu kvůli ODR const double viewport::pomer = static_cast<double>(max_sirka) / max_vyska; 36

Ukazatel this Skrytý argument všech metod na objektu. Ukazuje na danou instanci. *this lze použít jako referenci na objekt samotný. Umožňuje zjistit, zda dvě reference odkazují na stejný objekt. struct dummy { dummy() { std::cout << "Creating dummy object at: " << std::hex << (uintptr_t(this) & 0xFFFF) << '\n'; ~dummy() { std::cout << "Destroying dummy object at: " << std::hex << (uintptr_t(this) & 0xFFFF) << '\n'; ; 37

Pole objektů Při vytvoření pole dojde k zavolání základních konstruktorů prvků. Při destrukci pole dojde k zavolání destruktorů prvků. Konstrukce probíhá zleva doprava, destrukce zprava doleva. int main() { auto foo = std::make_unique<dummy[]>(4); >>> Creating dummy object at address: 60e8 >>> Creating dummy object at address: 60e9 >>> Creating dummy object at address: 60ea >>> Creating dummy object at address: 60eb >>> Destroying dummy object at address: 60eb >>> Destroying dummy object at address: 60ea >>> Destroying dummy object at address: 60e9 >>> Destroying dummy object at address: 60e8 38

Organizace projektu v C++ --- třídy Třídy se obvykle rozdělují do dvou souborů Hlavičkový soubor s deklarací třídy, s příponou.hpp, jméno souboru dle třídy Implementační soubor s příponou.cpp a jménem dle třídy Například třída zasobnik by se rozdělila do zasobnik.hpp a zasobnik.cpp // zasobnik.h #ifndef ZASOBNIK_H #define ZASOBNIK_H using zas_typ = int; class zasobnik { public: zasobnik(int max_prvku = 20);... private: int max_velikost; int aktualni_pozice; std::unique_ptr<zas_typ[]> prvky; ; #endif // zasobnik.cpp #include "zasobnik.h" bool zasobnik::je_prazdny() const { return aktualni_pozice == 0; zasobnik::zasobnik(int max_prvku): max_velikost{ max_prvku, aktualni_pozice{ 0, prvky{ std::make_unique<zas_typ[]>(max_velikost) {... 39

The End 40