Globální moderátor Popular Post HighPrint 177 Odesláno: 18. Březen, 2017 Globální moderátor Popular Post Share Odesláno: 18. Březen, 2017 (upraveno) Úvod do OOP #1 Obsah: Úvod Pojmy Závěr 1. Úvod Jenom bych chtěl předem říci, že téma popisuji s nadsázkou, proto pokud objevíte nějakou blbost/nedostatek, tak mi to okomentujte a opravím/přidám. Co vlastně OOP je? Jedná se o Objektově-orientované programování a je jedním z nejvyužívanějších programovacích paradigmat1. Těch paradigmat je spoustu, určitě jste zaslechli o procedurální2, logické3 nebo funkcionální4 a další a další. Než si uvedeme nějaké základní pojmy, bylo by fajn si říct jaké jsou vlastně výhody OOP. Hlavní výhodou OOP je snažší údržba, rychlejší vývoj aplikace (z hlediska týmového), méně chybovost a rychlá orientace. Nevýhody – koncept třídy (vysvětlíme si později pojem) jedné osoby nemusí být sympatické té druhé. Většinou se proto dává důraz na to, že třídy se snaží být co nejvíce nezávislé nezasahujíc do něčeho co nemá zasahovat/co nemá v popisu práce. Dále chybou je zneužívání OOP, vytváření různých tříd na vše možné, co člověka napadne a špatně využití zapouzdření. Prakticky třídy vyžadují ohromnou dokumentaci a přípravu. 1 jednají se o styl, koncept a principy programování 2 nebo také imperativní – hlavní charakteristikou je výpočet pomocí posloupností příkazů a určuje přesný postup, např. C, PHP atd. Dělí se ještě do dalších podskupin, ale ty řešit nebudeme.3 vyhodnocování matematickou logikou, např. prolog 4 matematické funkce a jejich výpočetní vyhodnocování – lambda kalkul, lisp, Zpravidla se jednají o rekurentní výpočty. 1. Pojmy Třída (class) je abstrakce entity, popisuje datový typ. Udává nám jaké vlastnosti (členy) bude mít objekt (také jako instance třídy případně proměnné). Mezi vlastnostmi se zařazují členské proměnné (atributy, položky, attributes) a interface také jako členské funkce (metody, methods). Třídy se mohou i libovolně skládat resp. objekt třídy x je členskou proměnnou třídy y. Na následujícím příkladu si všechny tyto pojmy ukážeme a vysvětlíme. Příklady se pokusím vždy co nejvíce předvádět objektivně (jelikož deklarace tříd apod se liší v závislosti v jakém jazyku programujete), pro upřesnění se budu spíše držet syntaxe C++ (nejsou avšak korektní). Uvedený příklad budu postupem času rozšiřovat dle nových pojmů co si zavedeme. Na OOP samozřejmě také existují spoustu prog. konvencí, ačkoliv v téhle kapitole se jich držet nebudeme kvůli znázornění základních pojmů Př. Zvolme třídu Web. Jeho atributy bude návštěvnost, url a majitel webu, který je objektem třídy Osoba. Obsahuje jen jednu členskou metodu IncreaseTraffic a to na inkrementaci návštěvnosti. Třída Osoba obsahuje jméno, věk a víceméně pohlaví. class Osoba { /* Member variables */ string name; int age; bool gender; } class Web { /* Member methods */ IncreaseTraffic(); /* Member variables */ int traffic; string url; Osoba owner; } /* V závislosti na jazyk, ve kterém programujeme může definice členských metod být jinačí. Pro přehlednost vždy definici funkce budu dávat vně tříd */ IncreaseTraffic() { ++traffic; } /* Deklarace objektu pak vypadá:*/ Web pawnocz = new Web(); /* alokace objektu Webu s názvem pawnocz */ pawnocz.url = "pawno.cz"; /* k jednotlivým atributům/metodám se přistupuje pomocí tečkové notace případně šipkové (např. v PHP). Zde nastavujeme atribut */ pawnocz.owner.name = "chytrak" /* nastavování členských proměnných objektu owner (patriot Print) */ pawnocz.IncreaseTraffic(); /* voláme funkci IT(); k pawnocz Konstruktory a destruktory. Co to je? Konstruktor se deklaruje jako metoda a volá se vždy při vytvoření objektu1. Tzn když jsme deklarovali objekt pawnocz, zavolal se konstruktor. Ten ale nemáme deklarovaný ani definovaný, proto si zpravidla kompilátor vygeneruje sám2. Obecně o konstruktorech je toho hrozně moc informací, ale v základní verzi si uvedeme jen inicializační bez parametrů a s parametrama. Destruktor se naopak volá při zaniknutí objektu. Dobré zmínit je, že konstruktor nelze explicitně volat na existující objekt. 1 poctivému čtenáři může v tuhle chvíli dojít, že při vytvoření objektu pawnocz se také a dokonce jako první zavolal konstruktor Osoba2 pro zajímavost, C++ dokáže vytvořit inicializační konstruktor na vynulování proměnné. v Javě naopak vytvoří prázdný konstruktor. Více informací o C++ konstruktoru – http://en.cppreference.com/w/cpp/language/initialization Pojďme rozšířit náš příklad. Destruktor a konstruktor se deklaruje v závislosti na jazyku (např v PHP __construct, __destruct). Pro zpřehlednění si smažeme třídu Osobu a změníme majiteli datový typ. class Web { /* Constructor & destructor */ Web(); /* konstruktor MUSÍ mít stejný název jako třída a NEMÁ návratovou hodnotu */ ~Web(); /* pro destruktor platí to co u konstruktoru, akorát před názvem je '~' */ IncreaseTraffic(); int traffic; string url; string owner; } Web() { traffic = 50; } /* inicializační konstruktor bez parametru */ IncreaseTraffic() { ++traffic; } Web pawnocz = new Web(); /* při alokaci webu je nyní traffic rovna 50 */ pawnocz.url = "pawno.cz"; pawnocz.owner = "chytrak" pawnocz.IncreaseTraffic(); První větším pojmem, které se setkáme při OOP je zapouzdření (anglicky encapsulation). Jak jsem již trochu nastínil nějaké settery a gettery. Jedná se vlastně o viditelnost neboli přístup k členům třídy. Dělíme do tří skupin – public, private, protected. Public znamená, že je přístupná komukoli v programu. Private je přístupná POUZE a JEN POUZE v dané třídě (neplést si to s objekty). K protected dojdeme později, jelikož ještě neznáme pojem dědění. Pojďme si zase rozšířit náš příklad. V našem příkladu použiji C++ encapsulation, jelikož mi přijde takové hezčí na uvedení. Pro poznámku, třída v C++ je implicitně privátní, zpřístupníme informace tím, že viditelnost označíme jinak. Víc na příkladech class Web { public: /* veřejná viditelnost – implicitně (tedy defaultně) je private a nepíše se tam. */ Web(); /* konstruktor a destruktor musí být vždy PUBLIC */ ~Web(); IncreaseTraffic(); /* v Javě se nedělí na viditelnost jako v C++, ale označuje klíčovým slovem public/private/protected před metodou případně u proměnných. Viz public IncreaseTraffict(); */ string owner; private: /* privátní */ int traffic; /* v Javě private int traffic */ string url; } Web() { traffic = 50; } /* inicializační konstruktor bez parametru */ IncreaseTraffic() { ++traffic; } Web pawnocz = new Web(); pawnocz.url = "pawno.cz"; /* CHYBA, proměnná url se nachází v private sekci */ pawnocz.IncreaseTraffic(); /* VALIDNÍ KROK, metoda se nachází v public sekci */ pawnocz.owner = "chytrak"; /* VALIDNÍ KROK, proměnná owner je v public sekci */ Jak zpřístupnit privátním informacím ostatním? Tím že pro členskou proměnnou si vytvoříme getter a setter. Setter a getter zní možná sofistikovaně, ale není to nic jiného než obyčejná metoda na čtení případně zapisování. Teď ale přichází kámen úrazu – a to zbytečně vytváření setterů a getterů. Vytvoříme-li setter a getter pro privátní proměnnou, rovnou ji můžeme nechat zviditelnit celou. Proto je tady potřeba pořádně promyslet zda-li vůbec potřebujeme settery a gettery. Samozřejmě pokud máme proměnnou, kterou nechceme aby nám někdo cizí měnil obsah, postačí nám pouze getter pro čtení informací. Občas nechceme vůbec aby nám někdo četl informace, v tu chvíli nepotřebujeme ani jednu z metod. int getTraffic() { return traffic; } string getUrl(string u) { return url; } void setOwner(string o) { owner = o; } Pojďme si ještě zmínit klíčové kouzelné slovo this. Jedná se o proměnnou (většinou reference) na danou instanci nad kterou pracujeme. Používá se pro upřesnění s jakým objektem pracujeme, např pro rozlišování proměnné instance od parametru. Občas se hodí i předávat danou instanci dál v metod. Zároveň si rozšíříme příklad o konstruktoru s parametrem. class Web { public: Web(int traffic, string url, string owner); /* rozšířili jsme konstruktor o tři parametry */ ~Web(); IncreaseTraffic(); int getTraffic(); string getUrl(); setOwner(string owner); private: string url; int traffic; string owner; /* jenom drobná změna, owner jsme přesunuli mezi private */ } Web(int traffic, string url, string owner) { /*Vtip je v tom, že náš parametr se jmenuje stejně jako naše členská proměnná, tak jak to vyřešit? Můžeme přistoupit k proměnné slůvkem this->traffic = traffic; Pro zamezení tohoto konfliktu osobně třeba používám prefix "m_" --> tedy přejmenovat to na m_Traffic = traffic; */ this->traffic = traffic; /* v c++ se jedná o pointer, v javě reference. v PHP $this->traffic; */ this->owner = owner; this->url = url; } IncreaseTraffic() { ++traffic; } int getTraffic() { return traffic; } string getUrl() { return url; } void setOwner(string owner) { this->owner = owner; } Web pawnocz = new Web(50,"pawno.cz","chytrak"); /* voila, závorka není nic jiného než konstruktor. Lze vytvořit i lokální objekty Web pawnocz(50,"pawno.cz");, const Web pawno(50,"pawno.cz");...*/ print pawnocz.getUrl() + " má " + pawnocz.getTraffic() + " návštěvnost."; /* pawno.cz má 50 návštěvnost */ pawnocz.IncreaseTraffic(); pawnocz.setOwner("Lukáš Valenta"); /* už se nám nelíbilo, že je chytrak majitelem webu. */ Metody i proměnné můžou být static. Co to pro nás znamená? Co se týče metod, tak jsou podobné běžným funkcím, nemají implicitní instanci ani implicitní členské proměnné, ani this nejsou k dispozici. Jediné plus je mají přístup k třídním proměnným a volat třídní metody. Statické třídní proměnné jsou sdíleny instancemi třídy, a jsou dodržována standartními pravidly zapouzdření. Statické metody ani proměnné nás ale teď nezajímá. Zbývá nám ještě projasnit si tři základní pojmy – protected, polymorfismus a dědičnost Dědičnost slouží k vytvoření nových datových typ na základě něčeho čeho už máme. Proč jsem si nechal encapsulation protected až teď? Protected je víceméně private plus navíc to, že se věci pod touto viditelností dědí do ostatních podtříd. Pro znázornění využijeme třídu Osoba, kterou jsem si hezky nadeklaroval na začátku a rozšíříme ji o metodu pozdrav. Na tento příklad později navážeme polymorfismus. Vysvětlíme si příklad, chceme třídu Cech a Nemec a ty budou dědit Osoba, která se bude chovat jako abstraktní třída1. Každý vždy bude mít navíc členskou proměnnou a každý umí jen svůj jazyk. 1 abstraktní třída je třída, která nemá svoji implementaci a chová se jen čistě jako rozhraní pro třídy, které ho budou dědit. Na abstraktní třídy nelze vytvořit instance. Abstraktní třídy jsou užitečné, pokud víme, že všechny zděděné třídy jsou schopny provést implementaci abstraktních metod class Osoba { public: Osoba(); ~Osoba(); void pozdrav() = 0; /* = 0; znamená, že označujeme pozdrav() za abstraktní metodu v c++. V Javě a PHP je označení klíčovým slůvkem "abstract" před "class" */ protected: string name; int age; bool gender; } /* v Javě class Cech extends Osoba, v PHP tuším taky */ /* v C++ lze využít klíčové slovo public/private nebo vůbec nic. V případě public znamená, že ponechává vidtelnost zděděných věcí. Private je, že zděděné věci nemají viditelnost mimo této třídy a zakazuje polymorfismus */ class Cech : public Osoba { public: Cech(); ~Cech(); string getFavouriteBeer(); private: string favouriteBeer; } class Nemec: public Osoba { public: Nemec(); ~Nemec(); bool hasMustache(); private: bool mustache; } Polymorfismus umožňuje pracovat a používat jednotné rozhraní pro více (podobných) typů objektů. Podstatou polymorfismu je, zajistit přehlednost, jednoduchost jednotně pracovat se třídy velmi podobné, avšak trochu se lišící. Dokonce jsme si připravili rozhraní (viz výše Osoba) a poděděné třídy. Naším cílem je zajistit volání z databáze Osob1 takovým způsobem, aby každá osoba své národnosti volal svůj pozdrav2. 1 přeskočíme-li řeči o dynamických a statických vazeb, tabulce virtuálních metod neboli VMT (c++), zjišťování instance (java)2 abychom nemuseli složitě zjišťovat jakou instancí jaké třídy, ale stačí volat a nechat na běhu programu ať si zvolí metodu sám. // Kód v C++ Osoba ** arr = new Osoba*[20]; for ( int i = 0; i < 20; i ++){ if(rand % 2 == 0) arr[i] = new Cech; else arr[i] = new Nemec; } for( int i = 0; i < 20; i ++) arr[i]->pozdrav(); // Guten tag / Ahoj v závislosti na random for( int i = 0; i < 20; i ++) delete arr[i]; // nesmíme zapomenout na uvolňování :-) 2. Závěr Tak došli jsme úspěšně ke konci. V dnešní kapitolě jste si doufám odnesli nějaké základy o OOP a jeho základní pojmy (zapouzdření, polymorfismus, dědění,...). Pokud máte v něčem nejasno, neváhejte a zeptejte se. Polymorfismus jsem trochu odbil, takže se za to omlouvám, ale snad jsem Vám nastínil trochu tý černé magie okolo ní. Pokud byste si přáli o ní něco více vědět, tak editnu trochu příklad a rozšířím ji. Pokud jsem něco uvedl špatně, prosím napište mi to. Pokud jsem na něco zapomněl, také mi to napište. Každopádně se s Vámi loučím a snad jsem někoho zaujal vyzkoušet si OOP. Edited 19. Březen, 2017 by HighPrint 8 Link to comment Share on other sites More sharing options...
Hlavní moderátor vEnd 279 Odesláno: 19. Březen, 2017 Hlavní moderátor Share Odesláno: 19. Březen, 2017 Toto by klidně mohlo sloužit jako vzor pro ostatní návody. Pěkná práce. Takovéto tuty jsou celkem zásadní, každý se dříve nebo později s OOP setká, takže určitě je dobré mít základní znalosti. Link to comment Share on other sites More sharing options...
mimic 27 Odesláno: 8. Duben, 2017 Share Odesláno: 8. Duben, 2017 Určitě je to + pro lidi, kteří začínají v C++ a je to i přehledné Ale mnohem efektivnější by to bylo ukázat třeba v C# nebo Javě, ve kterým (a to hlavně v Javě) je všechno objekt a striktně se řídí OOP. Myslim si, že některý lidi to může rozhodit, protože syntax je v C++ jiná a to hlavně v pohledu interface, který se řeší úplně jinak, než v jiných jazykách. Ale to neber jako kritiku, spíše takový hint a možná, by to bylo dobré napsat i do titulku A teď nějaké mé postřehy, co jsem v rychlosti zahlédl. 1) jako přiklad uvádíš třídu Osoba, což proti tomu nic nemám, spíš mě vyděsily ty datové typy proměnných (sice to s OOP nemá nic společného, ale když už, tak ať to dává aspoň smysl) enum Gender : unsigned { MALE, FEMALE } class Osoba { private: // i když je private vychozí modifikátor, je dobré ho uvádět taky string name; unsigned age; // nevidim duvod pouzivat 4byte int, kdyz vek muzu ulozit do 1byte Genre gender; // pokud bude bool, tak false bude jako co? muz? O_o } 2) init konstruktoru bez parametru je lepší zapisovat jako Web() : traffic(50) {} 3) vytvoření instance Web se dělá 2 způsoby, né vždy je nutné alokovat třídu, pokud to není vyložené nutné, tak proč to dělat, potom je potřeba řešit uvolnění (většinou přes destruktor) a ještě tam máš chybu // tohle tvoje prece nemuže fungovat Web pawnocz = new Web(); /* alokace objektu Webu s názvem pawnocz */ // správně (nova instance "new" vraci pointer na alokovanou oblast v pameti) Web* pawnocz = new Web(); pawnocz->IncreaseTraffic(); // volani // nebo bez alokace a pristupovat přes "tecku" Web pawnocz; pawnocz.IncreaseTraffic(); // volani 4) tohle tvoje tvrzení "a to zbytečně vytváření setterů a getterů. Vytvoříme-li setter a getter pro privátní proměnnou, rovnou ji můžeme nechat zviditelnit celou." není pravda... Dost záleží na úhlu pohledu, díky tomu, že existuje getter/setter, tak je možné provést více operací než jen to volání/zápis... např. volat různé události, překreslení, nastavit další hodnoty, které uzce souvisí s nastavovanou apod. Vždy je dobré používat getter/setter i přesto, že jen nastavuji/ziskavaji hodnotu 5) co se týče destruktoru, tak je dobre se na ni nikdy nespolehat, vzdy je lepsi varianta udelat metodu, ktera vsechno uvolni a tu volat v destruktoru a idealne i na miste, kde uz s objektem nechce programator dale pracovat 6) a tohle tvrzení "Private je přístupná POUZE a JEN POUZE v dané třídě" také není pravda co se C++ týče... v C++ existují tzv. spřátelené třídy, ve kterých je možné volat i privátní fieldy mezi sebou. 7) v tom jednom příkladu nemáš konstruktor a destruktor public U toho tého "this" jsem skončil, moc dlouhý ) Link to comment Share on other sites More sharing options...
Globální moderátor HighPrint 177 Odesláno: 8. Duben, 2017 Author Globální moderátor Share Odesláno: 8. Duben, 2017 Diky moc, cenim si odpovedi a beru tvoje pripominky na vedomi. Jenom bych chtel dodat par komentaru k pripominkam. Snazil jsem se spise popsat princip oop a kvuli tomu se pak michaly ruzne syntaxe 1) jasne byl to jen priklad abych ukazal, ze trida muze bejt clenskou metodou jine tridy, nechtel jsem pouzit nic co by okolo toho nebylo nezbytne 2) dobra poznamka, v tu chvili me to nenapadlo, ale zase... snazil jsem se to brat co nejvic objektivne, takze initializer list nema treba zminovana java. A dale protoze se za tim skryva zajimavejsich veci at uz z praktickeho hlediska tak i teoretickeho 3) jo, tuto informaci bych mohl pripsat, co se tyce ty chyby tak jsem si ji vedom. Michal jsem blbe jazyky, tak se za to omlouvam, kazdopadne diky za bystre oko 4) pripisu informaci, az budu dostupnej na pc. Diky! 5) o tom jsem nikdy neslysel, mel jsem za to, ze destruktor je vzdy zaruceny. Mohl bys mi vic popsat proc se na nej nelze spolehnout? 6) pripisu jako poznamku pro c++ 7) jsem si toho vedom, muj pokus o navod volit metodu "baby-steps" a postupne rozsirovat pojmy, proto jsem nechtel zatezovat na zacatku ctenare Link to comment Share on other sites More sharing options...
Tanga 131 Odesláno: 8. Duben, 2017 Share Odesláno: 8. Duben, 2017 // správně (nova instance "new" vraci pointer na alokovanou oblast v pameti) Web* pawnocz = new Web(); pawnocz->IncreaseTraffic(); // volani // nebo bez alokace a pristupovat přes "tecku" Web pawnocz; pawnocz.IncreaseTraffic(); // volani 4) tohle tvoje tvrzení "a to zbytečně vytváření setterů a getterů. Vytvoříme-li setter a getter pro privátní proměnnou, rovnou ji můžeme nechat zviditelnit celou." není pravda... Dost záleží na úhlu pohledu, díky tomu, že existuje getter/setter, tak je možné provést více operací než jen to volání/zápis... např. volat různé události, překreslení, nastavit další hodnoty, které uzce souvisí s nastavovanou apod. Vždy je dobré používat getter/setter i přesto, že jen nastavuji/ziskavaji hodnotu 5) co se týče destruktoru, tak je dobre se na ni nikdy nespolehat, vzdy je lepsi varianta udelat metodu, ktera vsechno uvolni a tu volat v destruktoru a idealne i na miste, kde uz s objektem nechce programator dale pracovat 6) a tohle tvrzení "Private je přístupná POUZE a JEN POUZE v dané třídě" také není pravda co se C++ týče... v C++ existují tzv. spřátelené třídy, ve kterých je možné volat i privátní fieldy mezi sebou. 7) v tom jednom příkladu nemáš konstruktor a destruktor public U toho tého "this" jsem skončil, moc dlouhý ) 3.) vysvetlil si referencie v jednom riadku na ktore knihy davaju 20 stran... 4.) Suhlasim. Gettery a settery su spravne riesenie. V C++ zmenis switch pri kompilacii a vsetky volania sa zmenia na proste ziskanie hodnoty premennej. JVM to robi automaticky, C# by malo tiež. 5.) moz byt. Ale "Nikdy na ni nespolehat" je proti encapsulation. Nemal by si vediet jak su detaily implementovane a uz vobec nie clearovat objekty z inej triedy. 6.) NAvod je o OOP, nie o C++. V OOP teorii to plati. Inak v praxi mozes povedat ze nikde to nefunguje kvoli reflexii. Jo a dobry navod, asi sa mi to nechcelo citat tak som ani nepisal. Vlastne ani teraz som to cele necital. Jo a nemam co robit. Link to comment Share on other sites More sharing options...
mimic 27 Odesláno: 9. Duben, 2017 Share Odesláno: 9. Duben, 2017 (upraveno) 5) o tom jsem nikdy neslysel, mel jsem za to, ze destruktor je vzdy zaruceny. Mohl bys mi vic popsat proc se na nej nelze spolehnout? Jsem asi špatně napsal, destruktor by se měl vždy zavolat při zavolání delete, spíš jde o to, že při složitější implementaci je možné udělat virtuální destruktor a potom při vytvoření implementace nemusí být zcela jasné a může se i stát, že se nezavolá ten destruktor z implementace, ale z rozhraní. Je to sice vic specifická záležitost, ale v C++ je to možný... ale pokud by se to stalo, tak to je většinou chyba samotné implementace, né jazyku, ale v jazycích, které mají vlastní GC, bych tomu neveřil, tam se ani nedoporučuje používat destruktor 6.) NAvod je o OOP, nie o C++. V OOP teorii to plati. Inak v praxi mozes povedat ze nikde to nefunguje kvoli reflexii. Jasně, pokud se bavíme o OOP jako takovým tak máš pravdu, ale vzhledem k tomu, že je to spíš víc o C++ kde to OOP je trosku jiný a jinak se k nemu pristupuje, tak proto jsem i psal, ze je lepsi tenhle topic udelat jako OOP pro C++, aby ostatni vedeli jakou ma syntax v tomhle jazyku... idealni navod na OOP by byl v jave, ktera ho striktne dodrzuje uz od sameho pocatku, ale to uz jsem psal Tak, mám chvíli čas, tak jsem se rozhodl dodělat ten zbytek 8) v tom zdrojáku pod "this" ti chybí návratové typy u 2 metod v deklaraci třídy 9) možná by bylo dobré zmínit, proč preferuješ a co to znamená to "m_" u instančních proměnych, ono je to dost různý, posledni dobou (pár let) spíš "frčí" samotné podtržítko v případě privátních členů. Jinak opět zmíním, že to jde napsat i tímto stylem (to neber jako opravu, jen bych to zahrnul i do ukázky, protože jak jsem řekl, tak ukazovat OOP na C++ je trošku jiný než v jiných jazykách, kde je striktně daný zápis) Web(int traffic, string url, string owner) : traffic(traffic), owner(owner), url(url) // vubec nevadi, ze nazev člena s parametrem je stejny, C++ si s tim poradi i bez "this" {} 10) Nechybi ti tady neco? print pawnocz.getUrl() + " má " + pawnocz.getTraffic() + " návštěvnost."; /* pawno.cz má 50 návštěvnost */ 11) U toho slova "static" mě zajímá, jak bylo myšleno tohle.. "Jediné plus je mají přístup k třídním proměnným a volat třídní metody", protože to není pravda, cokoliv je deklarovaný jako static, tak je úplně oddělený on instance třídy, tzn. jak metod, tak proměnných Ten zbytek je relativně ok, jen bych asi zmínil věci ohledně polymorfismu, že tenhle řekneme zpusob vývoje větsinou pracuje s rozhraním a ne s abstraktnima tridama. V C++ jelikoz neni klicove slovo abstract nebo interface, tak se to zajistuje tak, ze jakmile ma trida aspon jednu metodu abstraktni (metoda = 0), tak se automaticky prevadi na abstraktni tridu. V pripade rozhrani je to tak, ze trida musi mit pouze public metody a vsechny abstraktni. Coz je neco, s cim tento tutorial nepocita a je to tez soucast OOP A potom klicove slovo static je dobre pouzivat minimalne. Je dobre na metody napr. pro utilit tridy a tak, ale co se tyce statickych clenu tridy, tak opravdu zvazit, zda je nutne to delat jako staticky. Pri nevhodnem pouziti je to vic problemu nez uzitku a o bezpecnosti kodu ani nemluvim V poslední řadě tady přikládám teda ukázku k předchozímu bodu 6. kde je mozne pristupovat k privatnim clenum (pouze C++), v jinych jazykach to mozne neni #include <iostream> // pro cout class B; // deklarace tridy pro pouziti ve tride A class A { private: int valueFromA; public: A(int value) : valueFromA(value) {} void run(B ; // operace se tridou B ve tride A }; class B { friend class A; // umozni pristupovat tride A k privatnim clenum private: int valueFromB; public: B(int value) : valueFromB(value) {} }; void A::run (B { valueFromA = b.valueFromB; // b.valueFromB je private std::cout << valueFromA; // vypise 20 } int main() { A a(10); B b(20); a.run(; // vypise 20 return 0; } Edited 9. Duben, 2017 by mimic Link to comment Share on other sites More sharing options...
Recommended Posts
Create an account or sign in to comment
You need to be a member in order to leave a comment
Create an account
Sign up for a new account in our community. It's easy!
Register a new accountSign in
Already have an account? Sign in here.
Sign In Now