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



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

Pokročilé programování v jazyce C pro chemiky (C3220) Dědičnost tříd v C++

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

Pokročilé programování v jazyce C pro chemiky (C3220) Vstup a výstup v C++

Více o konstruktorech a destruktorech

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

Programování II. Polymorfismus

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

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

Programování v C++ VI

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

Virtuální metody - polymorfizmus

Konstruktory a destruktory

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

Mělká a hluboká kopie

Dědění, polymorfismus

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

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

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

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

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.

Martin Flusser. Faculty of Nuclear Sciences and Physical Engineering Czech Technical University in Prague. December 7, 2016

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

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

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

Generické programování

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

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

Programování v jazyce C a C++

Abstraktní třídy, polymorfní struktury

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

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

PREPROCESOR POKRAČOVÁNÍ

Dynamická identifikace typů v C++.

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

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

Jazyk C# (seminář 6)

Algoritmizace a programování

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

Jazyk C++ I. Šablony 2

Programování v jazyce C a C++

III/2 Inovace a zkvalitnění výuky prostřednictvím ICT

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

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

Ukazatele, dynamická alokace

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

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

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

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

Programování v jazyce C pro chemiky (C2160) 6. Funkce, struktury

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

Funkční objekty v C++.

Jazyk C++ I. Polymorfismus

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

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

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

Pole a Funkce. Úvod do programování 1 Tomáš Kühr

7 Formátovaný výstup, třídy, objekty, pole, chyby v programech

III/2 Inovace a zkvalitnění výuky prostřednictvím ICT

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

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

Vector datový kontejner v C++.

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

Objektově orientované programování. Úvod

Práce s pamětí a předávání parametrů. Úvod do programování 1

Programování v jazyce C pro chemiky (C2160) 3. Příkaz switch, příkaz cyklu for, operátory ++ a --, pole

Objektov orientované programování. C++ Akademie SH. 7. Objektov orientované programování. Michal Kvasni ka. Za áte níci C++ 2.

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

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

konstruktory a destruktory (o)

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

Objektové programování

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

Př. další použití pointerů

Lineární spojový seznam (úvod do dynamických datových struktur)

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

typová konverze typová inference

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

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

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

Programování II. Dědičnost změna chování 2018/19

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

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

Množina v C++ (set, multiset).

III/2 Inovace a zkvalitnění výuky prostřednictvím ICT

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

Programování II. Objektová dekompozice Třída jako objekt 2018/19

Jazyk C++ I. Šablony

Jazyk C++ II. Výjimky

Strukturu lze funkci předat: (pole[i])+j. switch(výraz) velikost ukazatele

Ukazatele a pole. Chceme-li vyplnit celé pole nulami, použijeme prázdný inicializátor: 207 Čárka na konci seznamu inicializátorů

Operační systémy. Cvičení 4: Programování v C pod Unixem

Jazyk C++ II. STL knihovna kontejnery část 1

Ukazka knihy z internetoveho knihkupectvi

Pole a kolekce. v C#, Javě a C++

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

Úvod do programovacích jazyků (Java)

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

Martin Flusser. December 15, 2016

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

Transkript:

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

Dynamická alokace paměti Jazyky C a C++ poskytují programu možnost vyžádat si část volné operační paměti pro umístění proměnné, pracovat s ní a pak ji zase vrátit V jazyce C++ se pro přidělení paměti používá operátor new (v C se paměť přidělí voláním funkce malloc()) Operátor new vrací ukazatel na přidělenou paměť (tj. adresu v paměti kde začíná přidělená oblast paměti) Není-li k dispozici dostatek paměti, vrací operátor new hodnotu 0 Adresu přidělené paměti zpravidla přiřadíme do ukazatelové proměnné // Ukazatele definujeme tak ze pred jmenem promenne uvedeme * // Ukazatele inicializujeme nulovou hodnotou, // v C++ obvykle pouzivame 0 misto NULL pouzivaneho v C int *a = 0; a = new int; // Prideleni pameti v C++ if (a == 0) return 0; // Otestujeme uspesnost alokace // Tady bude dalsi kod 2

Operátor new Operátor new lze použí pro přidělení paměti proměnným základních typů (int, double,...) a také objektovým proměnnným Použijeme-li operátor new pro vytvoření objektové proměnné, je ihned po alokaci paměti zavolán konstruktor Pokud chceme zavolat konstruktor který přijímá parametry, můžeme mu příslušné hodnoty předat - uvedeme je v závorkách za jménem třídy // Na zacatku je deklarovana trida Circle Circle *circle1 = 0, *circle2 = 0, *circle3 = 0; circle1 = new Circle; // Bude se volat konstruktor bez parametru circle2 = new Circle(); // Take se bude volat konstruktor bez parametru circle3 = new Circle(150, 200, 50, 3); // Vola se konstruktor s parametry 3

Ukazatele a operátor -> Pro přístup ke členům třídy u ukazatelů používáme operátor -> // Tady je nekde deklarovana trida Circle Circle *circle = 0; circle = new Circle; circle >setvalues(150, 200, 50, 3); // U ukazatelu pristupujeme ke clenum // tidy pomoci operatoru > circle >x = 300; // Operator > muzeme take pouzit pro pristup k datovym // clenum tridy. Clenska promenna x by vsak musela byt // v tomto pripade definovana v sekci public 4

Operátor delete Operátor delete používáme pro uvolnění paměti která byla alokována operátorem new (v jazyce C se místo toho používá funkce free()) Při použití operátoru delete je nejdříve zavolán destruktor objektu a poté je paměť uvolněna Po uvolnění paměti je vhodné přiřadit ukazateli hodnotu 0 aby neukazoval na neplatnou adresu // Tady je nekde deklarovana trida Circle Circle *circle = 0; circle = new Circle; // Tady pracujeme s promennou circle // Kdyz uz promennou dale nepotrebujeme, uvolnime pridelenou pamet // operatorem delete delete circle; circle = 0; // Do circle priradime 0 aby neobsahovala neplatnou adresu 5

Pole ukazatelů V praxi často potřebujeme pracovat s polem ukazatelů Pole ukazatelů často používáme v situaci, kdy načítáme objekty (např. ze souboru) a postupně dynamicky alokujeme paměť pro jednotlivé objekty // Tady je nekde deklarovana trida Circle const int MAX_GRAPHIC = 1000; int cirlescount = 0; // Tady bude pocet nactenych kruznic Circle *circles[max_graphic]; // Definujeme pole ukazatelu while(/*nejaka podminka cyklu*/) circles[circlescount] = new Circle; circlescount++; // Zde by se provadely nejake operace s polem circles[] // Nakonec musime pridelenou pamet uvolnit for (int i = 0; i < circlescount; i++) delete circles[i]; circles[i] = 0; circlescount = 0; 6

Kontejner ukazatelů Místo polí je výhodnější použít kontejner vector, který dokáže zvětšit svoji velikost #include <vector> // Tady je nekde deklarovana trida Circle Circle *circle = 0; // Definujeme pomocny ukazatel vector<circle*> circlescontainer; // Definujeme kontejner ukazatelu while(/*nejaka podminka cyklu*/) circle = new Circle; circlescontainer.push_back(circle); for (int i = 0; i < circlescontainer.size(); i++) circlescontainer[i] >printvalues(); // Vypiseme informace o kruznici // Tady musime pridelenou pamet uvolnit for (int i = 0; i < circlescontainer.size(); i++) delete circlescontainer[i]; circlescontainer.clear(); // Metoda clear() nastavi velikost // kontejneru na 0 7

Překrytí metod předka Pokud definujeme v odvozené třídě metodu stejného jména jako v základní třídě, dojde k překrytí této metody Toto překrytí se však projeví pouze v metodách potomka, v metodách předka je stále volána původní metoda předka class Graphic public: void printvalues() cout << "Metoda Graphic::printValues\n"; ; void test() printvalues(); ; ; class Circle : public Graphic public: void printvalues() cout << "Metoda Circle::printValues\n"; ; ; Circle circle; circle.printvalues(); // Vola se metoda Circle::printValues(), ktera // prekryla metodu Graphic::printValues() circle.test(); // Vola se metoda Graphic::test(), kterou trida Circle // zdedila od Graphic. // Tato metoda vsak zavola Graphic::printValues() 8

Virtuální metody Deklarujeme-li překrytou metodu s klíčovým slovem virtual, bude v metodách předka volána příslušná virtuální metoda potomka Metodu musíme deklarovat jako virtuální v předkovi i v potomkovi class Graphic public: virtual void printvalues() cout<< "Metoda Graphic::printValues"; ; void test() printvalues(); ; ; class Circle : public Graphic public: virtual void printvalues() cout << "Metoda Circle::printValues" ; ; Circle circle; circle.printvalues(); // Vola se metoda Circle::printValues(), ktera // prekryla metodu Graphic::printValues() circle.test(); // Vola se metoda Graphic::test(), kterou trida Circle // zdedila od Graphic. Tato metoda vsak zavola // Circle::printValues(), protoze ta je virtualni. 9

Ukazatele a nevirtuální metody Všechny ukazatele obsahují adresu v paměti bez ohledu na typ ukazatele; to umožňuje přiřadit jednomu ukazateli hodnotu druhého ukazatele Typ ukazatele poskytuje překladači informaci o datových položkách objektu a metodách na které ukazatel ukazuje Pokud bychom ukazateli přiřadili ukazatel na zcela odlišnou proměnnou (např. do int* přiřadíme Circle*) došlo by k nesprávnému chování programu, proto překladač toto nedovolí Je však možné přiřadit ukazateli základní třídy hodnotu ukazatele odvozené třídy, v takovém případě však při práci s ukazatelem na základní třídu bude přístupováno pouze ke členům základní třídy // Zde budou definice trid Graphic a Circle, kazda z nich bude mit // definovanou nevirtualni metodu printvalues() (viz. dve stranky zpet) Graphic *graphic = 0; Circle *circle = new Circle; graphic = circle; graphic >printvalues(); circle >printvalues(); // Zavola se metoda Graphic::printValues() // Zavola se metoda Circle::printValues() 10

Ukazatele a virtuální metody Použijeme-li virtuální metody, obsahuje každý objekt informace o virtuálních metodách objektu (interní tabulku virtuálních metod) Tabulka virtuálních metod je k objektu přiřazena v okamžiku přidělení paměti (při použití dynamické alokace to je ihned po použití new) V okamžiku volání metody se z tabulky vybere příslušná metoda odpovídající původnímu objektu a to i v případě, že jsme ukazatel přiřadili do ukazatele základní třídy // Zde budou definice trid Graphic a Circle, kazda z nich bude mit // definovanou virtualni metodu printvalues() (viz. dve stranky zpet) Graphic *graphic = 0; Circle *circle = new Circle; // Zde se vytvori interni tabulka // virtualnich metod graphicle = circle; graphic >printvalues(); // V tabulce virtualnich metod objektu // se vyhleda ta virtualni metoda printvalues() // ktera odpovida tride pouzite pro vytvoreni // objektu a zavola se, takze se zavola // metoda Circle::printValues() 11

Využití virtuálních metod Typickým příkladem využití virtuálních metod je situace kdy potřebujeme pracovat se souborem různých objektů (např. Circle, Rectangle, CircleFilled) které mají společného předka (např. Graphic) V takovém případě vytvoříme pole ukazatelů na předka a dynamicky alokujeme jednotlivé objekty, které přidáváme do pole Pomocí virtuálních metod můžeme docílit odlišného chování jednotlivých prvků v poli 12

Využití virtuálních metod // Zde bude definovana trida Graphic a z ni odvozene Circle a Rectangle const int MAX_GRAPHIC = 1000; int graphicscount = 0; Graphic *graphicscontainer[max_graphic]; Circle *circle = 0; // Pomocna promenna Rectangle *rectangle = 0; // Pomocna promenna while(/*nejaka podminka cyklu*/) if (/*nejaka podminka*/) circle = new Circle; graphicscontainer[graphicscount] = circle; graphicscount++; else if (/*nejaka podminka*/) rectangle = new Rectangle; graphicscontainer[graphicscount] = rectangle; graphicscount++; for (int i = 0; i < graphicscount; i++) graphicscontainer[i] >draw(dev); // draw() je virtualni metoda 13

Zpracování virtuálních metod překladačem U nevirtuálních metod je již v době překladu rozhodnuto která metoda bude volána - mluvíme o časné vazbě U virtuálních metod je teprve v okamžiku volání metody vyhodnoceno která metoda se bude volat - mluvíme o pozdní vazbě Virtuální metody jsou v jazyce C++ široce používány v souvislosti s knihovnami tříd, kdy odvodíme vlastní třídu jako potomka knihovní třídy a v něm definujeme ty virtuální metody, jejichž chování chceme pozměnit 14

Cvičení 1. Vytvořte program vycházející z úlohy 1 ze cvičení 6 (načítání grafických objektů ze souboru a jejich ukládání do obyčejných polí), pro vykreslování však nepoužívejte šablonu. Program upravte následujícím způsobem: Ve třídě Graphic vytvořte metodu test() která volá metodu printvalues() (ta vypíše jméno třídy a metody, např. Circle::printValues). Předtím než zavoláte metodu draw() volejte vždy metodu test(), postupně pro všechny grafické objekty (kružnice, obdélníky, vyplněné kružnice) a sledujte výpis Všechny metody printvalues() změňte na virtuální a porovnejte výpis s předchozím Program dále modifikujte tak, že grafické objekty budou alokovány dynamicky a ukládány do pole ukazatelů 2 body 2. Předchozí program modifikujte následovně: Všechny grafické objekty budou alokovány dynamicky a ukládány do jednoho pole ukazatelů Graphic* Zároveň metody readfile(), printvalues() a draw() budou implementovány jako virtuální 2 body 3. Program modifikujte tak aby namísto pole ukazatelů používal kontejner vector s ukazateli. 1 bod 15