dodelana sekce s OOP

This commit is contained in:
2026-04-05 23:38:49 +02:00
parent e54496826d
commit 2f9701bc43

View File

@@ -1,9 +1,9 @@
Poznámka: Příklady jsou zjednodušené a ne vždy jsou 100% syntakticky právně (nechci vždy psát int main(void)... etc.) Poznámka: Příklady jsou zjednodušené a ne vždy jsou 100% syntakticky právně (nechci vždy psát int main(void)... etc.)
# Principy objektového programování # Principy objektového programování
1) Jaký je rozdíl mezi třídou a objektem? ### Jaký je rozdíl mezi třídou a objektem?
**Třída je šablona pro vytváření objektů**. Typicky napíšu třídu a pak z ní inicializuju její objekty, které až poté v kódu využívám. **Třída je šablona pro vytváření objektů**. Typicky napíšu třídu a pak z ní inicializuju její objekty, které až poté v kódu využívám.
```cpp ```cpp
class Trida class Trida
{ {
public: public:
@@ -16,11 +16,11 @@ Poznámka: Příklady jsou zjednodušené a ne vždy jsou 100% syntakticky práv
Trida objekt; Trida objekt;
objekt.cislo = 10; objekt.cislo = 10;
} }
``` ```
2) Jak je určena viditelnost členských proměnných a metod? ### Jak je určena viditelnost členských proměnných a metod?
- public -> přístup možný odkudkoli z programu - public -> přístup možný odkudkoli z programu
- protected -> přístup je možný ze třidy nebo z podtříd (dědičnost) - protected -> přístup je možný ze třidy nebo z podtříd (dědičnost)
- private -> pouze funkce uvnitř objektu (třídy) můžou přistupovat ke členu s touto viditelností - private -> pouze funkce uvnitř objektu (třídy) můžou přistupovat ke členu s touto viditelností
```cpp ```cpp
class Trida class Trida
{ {
@@ -37,26 +37,239 @@ Poznámka: Příklady jsou zjednodušené a ne vždy jsou 100% syntakticky práv
} }
``` ```
3) Jaký je rozdíl mezi členskými metodami (a proměnnými) třídy a objektu? ### Jaký je rozdíl mezi členskými metodami (a proměnnými) třídy a objektu?
Třída může obsahovat i metody typu `static` to jsou **členské metody**. Pokud ze třidy inicializuju objekt, tyto metody se do objektu nepředají. Nejlepší způsob jak je zavolat je přes jejich třídu `Mojetrida::metoda();` Třída může obsahovat i metody typu `static` to jsou **členské metody**. Pokud ze třidy inicializuju objekt, tyto metody se do objektu nepředají. Nejlepší způsob jak je zavolat je přes jejich třídu `Mojetrida::metoda();`
4) Jaký je rozdíl mezi klíčovými slovy protected a private? ### Jaký je rozdíl mezi klíčovými slovy protected a private?
- **private** -> přístupné **POUZE** uvnitř třídy, zděděná třída (a její objekty) nemá přístup k k proměnné původní třídy s protected - **private** -> přístupné **POUZE** uvnitř třídy, zděděná třída (a její objekty) nemá přístup k k proměnné původní třídy s protected
- **protected** -> vlastně je to jako private (tedy z kódu nemůžu měnit tuto proměnnou/metodu ve třidě), ale s tím rozdílem, že pokud vytvořím podtřídu (pomocí dědění) a z ní vytvořím objekt, tak jeho metody můžou přistupovat k protected členům objektů původní třídy - **protected** -> vlastně je to jako private (tedy z kódu nemůžu měnit tuto proměnnou/metodu ve třidě), ale s tím rozdílem, že pokud vytvořím podtřídu (pomocí dědění) a z ní vytvořím objekt, tak jeho metody můžou přistupovat k protected členům objektů původní třídy
- Co je polymorfismus a jak je ho dosaženo? ### Co je polymorfismus a jak je ho dosaženo?
- Co je to bázová třída a čím se vyznačuje? **Polymorfismus** je koncept, kdy jeden interface (třeba metoda) lze univerzálně použít pro více datových typů.
- Uveďte příklad deklarace plně virtuální metody?
- Co je to implicitní konstuktor? Toho se dosáhne pomocí více různých implementací.
- Co je to kopírovací konstruktor? Například můžu mít virtuální metodu `Draw()` v bázové třídě `Shape` a tuto metodu zdědí její potomci `Triangle` a `Square`. Implementace `Draw()` je v obou třídách jiná, ale u obou stačí zavolat `Draw()` a objekt se vykreslí.
- Jaké jsou možnosti dědění? Uveďte příklady.
- Co je to virtuální dědění a k čemu je dobré? Dále můžu dosáhnout polymorfismu pomocí přetěžování funkcí, kdy vytvořím víc funkcí se se stejným jménem, ale jiným typem.
- Které vlastnosti rodiče potomek nedědí?
- Co je to přetížení? Uveďte příklad (několik řádek kódu, ze kterých bude zřejmé, o co jde). Obvykle tím ale je spíš míněno to, že zděděné třídy od bázové třídy mají stejné chování (a ten iterface). Takže Když zdědím od `Vozidlo` -> `Tank`,`Formule`,`Tatrovka`, tak přece to jsou jiné třídy a mají jiný obsah, ale zdědí stejný typ ovládání. Např se všechny budou ovládat pomocí `.otoc_volant()`, `.zmackni_plyn()`, `.zmackni_brzdu()`, etc. (a nechci slyšet nic o tom, že tank může mít tradičně ovládací páky)
- Jaký je rozdíl mezi přepsáním (override) a přetížením (overload)? ### Co je to bázová třída a čím se vyznačuje?
- Co je vazba typu kompozice? Uveďte příklad (několik řádek kódu, ze kterých bude zřejmé, o co jde). Bázová třída třída je třída, z které se dědí. (ano notář sepíše vůli a potomci dostanou každý svojí část).
- Co je vazba typu asociace? Uveďte přiklad (několik řádek kódu, ze kterých bude zřejmé, o co jde). Bázová třída má nějaké vlastní datové typy a vlastní metody. Pokud jsou tyto metody a typy `public` nebo `protected`, tak je zdědí dědící třída.
- Co reprezentuje klíčové slovo this? Bázová třída může nebo nemusí obsahovat třeba virtuální metody nebo může nebo nemusí být plně virtuální.
- Jaký je rozdíl mezi referencí a ukazatelem? **Prostě je to třída z které někdo dědí, to je všechno.**
- Jaký je rozdíl mezi mělkou a hlubokou kopií? ### Uveďte příklad deklarace plně virtuální metody?
[geeks for geeks](https://www.geeksforgeeks.org/cpp/pure-virtual-functions-and-abstract-classes/)
**Plně virtuální metoda**, nebo někdy také **abstraktní metoda**, je metoda, co nemá vlastní implementaci v bázové třídě. To znamená, že je pouze naznačená její existence, ale není v ní žádný kód. Očekává se, že se kód dopíše ve zděděné třídě.
Pokud třída obsahuje takovou metodu, nelze z ní vytvářet instance (objekty).
Plně virtuální metoda je se píše ve tvaru `virtual typ jmeno() = 0;` Př:
```cpp
//sorry moc si nepamatuju, co kde cepujou...
class Hospoda {
public:
virtual void nacepuj() = 0; // plne virtualni metoda
};
class Nadrazka : public Hospoda {
public:
void draw() override {cout << "Staropramen\n";}
};
class Nadrazka : public Hospoda {
public:
void draw() override {cout << "Plzeň\n";}
};
class Nadrazka : public Hospoda {
public:
void draw() override {cout << "Kozel\n";}
};
```
### Co je to implicitní konstuktor?
Máme dva termíny co se obecně pletou a to **defaultní** konstruktor a **implicitní konstruktor**. Defaultní konstruktor je konstruktor, co nemá žádné argumenty a nás vlastně v této otázce nezajímá.
**Implicitní konstruktor** je konstruktor, který si kompilátor sám doplní, když ho nedodá uživatel. Obvykle pouze vytvoří proměnné, které ale pak nejsou inicializovany, takže mají náhodné hodnoty.
**Implicitní kopírovací konstruktor** je kopírovací konstruktor, který vytvoří kompilátor, když ho nedodá uživatel. Většinou jedna ku jedné vytvoří kopie hodnot prvků, což je problematické třeba u ukazatelů. Může se pak stát, že 2 prvky po zkopírování budou mít stejné pole (stejnou adresu na ukazately) a můžou si ho sami přepisovat. Dále se pak může stát, že když se zníčí jeden objekt, uvolní pole, které první objekt používá... to se řeší vlastním kopírovacím konstruktorem viz. další otázka
btw, to je tzv. mělká kopie
### Co je to kopírovací konstruktor?
Abychom řešili problém s mělkým kopírováním **implicitního kopírovacího konstruktoru** (viz. předchozí otázka), tam můžeme vytvořit vlastní kopírovací konstruktor, který udělá tzv. hlubokou kopii. Tedy umí vytvořit třeba nové ukazatele pro nový kopírovaný prvek. **Ten si musíme napsat manuálně takto:**
```cpp
Class A
{
public:
int* a;
A(int number) {a = new int(number);} //normální konstruktor
A(const &A other) {a = new int(*other.data)} //kopírovací konstruktor
//vracím objekt s novým ukazatelem u a
}
```
### Jaké jsou možnosti dědění? Uveďte příklady.
Celé je to o tom, jak se změní viditelnost členů.
Máme **3 typy dědění**:
- **public**
- **private**
- **protected**
**Public dědění:**
```cpp
class B : public A {};
```
Zde třída A dostane všechny části zděditelné části třídy B úplně stejně, jako je měla třída A.
Tedy jde hlavně o to, jak se změní public a protected atributy. Tady:
public -> public
protected -> protected
**Protected dědění:**
```cpp
class B : protected A {};
```
Zde se všechny zděditelné prvky změní na protected Tedy
public -> protected
protected -> protected
**Private dědění:**
```cpp
class B : private A {};
```
Zde se všechny zděditelné prvky změní na private. Tedy:
public -> protected
protected -> private
### Co je to virtuální dědění a k čemu je dobré?
Je to způsob řešení problému tzv. diamantového dědění (či obdobné situace, viz. obrázek). V podstatě jde o to, že **dědění umožňuje přebírat vlastnosti víc tříd najednou** (ne pouze jedné), což pak může vyústit v situace, kde se snažím vytvořit potomek z dvou a více tříd, kde **mají některé společného předchůdce** (někde v jejich rodokmeni.)
![](https://upload.wikimedia.org/wikipedia/commons/thumb/8/8e/Diamond_inheritance.svg/500px-Diamond_inheritance.svg.png)
To by normálně skončilo tak, že by byla nevyřešená situace, která by mohla vyhodit chybu v případě, kdy bych se ze třídy `D` pokoušel přistoupit ke zděděnému členu z bázové třídy `A`. Kompilátor si není jistý zda si vybrat cestu přes `B` nebo přes `C`.
Řeším to přes virtuální dědění:
```cpp
//priklad z wikipedia.org na toto téma
class Animal {
public:
virtual ~Animal() = default;
virtual void eat() {}
};
class Mammal: virtual public Animal { //virutalni dědění
public:
virtual void breathe() {}
};
class WingedAnimal: virtual public Animal { //virtuální dědění
public:
virtual void flap() {}
};
//zdědí obě vlastnosti bez duplikace
class Bat: public Mammal, public WingedAnimal {};
```
### Které vlastnosti rodiče potomek nedědí?
- **konstruktory a destruktory**
- **privátní členy**
- **funkce přetěžování operátorů**
- statické členy (jdou zavolat, ale neexistuje kopie, kinda nieche)
### Co je to přetížení? Uveďte příklad (několik řádek kódu, ze kterých bude zřejmé, o co jde).
Přetížení je, když má více funkcí stejné jméno, ale jiné chování. Využívá se to, když potřebujeme napsat jednu funkci pro více různých argumentů.
Přetěžovat jdou:
- funkce
- operátory
Přetěžování funkcí je hlavně stejné jméno, ale jiná funkce dle jejich argumentů
```cpp
bool is_not_zero(int x)
{
return(x != 0)
}
bool is_not_zero(char x)
{
return(x != 0)
}
bool is_not_zero(bool x)
{
return(x != 0)
}
bool is_not_zero(Std::string x)
{
return(x != '0')
}
```
Přetěžování argumentů je vysvětleno v jiné otázce v sekci Programování v C++ (a mimojiné jsem to vysvětlil v dokumentu v repu, co jsem na to téma vytvořil)
### Jaký je rozdíl mezi přepsáním (override) a přetížením (overload)?
Pomocí obou technik lze docílit, aby jedna funkce měla různé implementace.
**Přetížení**:
Při přetěžování vytvořím víc funkcí se stejným jménem a kompilátor se rozhodne jakou spustí dle dodaných argumentů
**Přepisování**:
Je koncept implementace polymorfismu, kdy v zájmu udržení stejného rozhraní (názvů metod u různých tříd), přepíšu u jednotlivých tříd, které metodu zdědily metody, tak je se mi u konkrétní třídy hodí
### Co je vazba typu kompozice? Uveďte příklad (několik řádek kódu, ze kterých bude zřejmé, o co jde).
Kompozice je, když objekt vlastní jiný objekt. Když zanikne celek, zanikne i část:
```cpp
class FEL {};
class FIT {};
class FS {};
class CVUT
{
public
FEL fel; //objekt cvut vlastni svoje fakulty
FIT fit; //patri k nemu a kdyz neni CVUT nejsou ani fakulty
FS fs;
//funkce co s temito objekty interaguji...
}
```
### Co je vazba typu asociace? Uveďte přiklad (několik řádek kódu, ze kterých bude zřejmé, o co jde).
Asociace je slabší vztah než kompozice. Objekt pouze odkazuje na jiný objekt (třeba přes pointer), ale nevlastní ho. Když původní objekt přestane existovat, asociovaný objekt může existovat dál.
```cpp
class Ucitel
{
public:
void uc() {}
};
class Student
{
private:
Ucitel* ucitel; // asociace
public:
//nejaky konstruktor priradi ucitle..
void studuj() {ucitel->uc();}
};
```
### Co reprezentuje klíčové slovo this?
`this` reprezentuje ukazatel na aktuální objekt/třídu (v metodách uvnitř třídy). Používání `this` není povinné, ale je to užitečné například pokud se **lokální proměnná a prvek třídy jmenují stejně**, nebo pokud chci třeba vracet ukazatel na objekt, čo objekt samotný: `*this`
`this` taky ulehčuje předání všech členů třídy/objektu lambda funkci
### Jaký je rozdíl mezi referencí a ukazatelem?
Reference je podobná ukazateli, ale je omezenější ve funkčnosti pro bezpečnost práce.
V podstatě je podobná konstantnímu ukazateli. Není možné změnit, na co reference ukazuje a dokonce nemůže existovat prázdná reference, nebo reference ukazující na `nullptr`. Referenci není třeba dereferencovat, chová se jako původní proměnná.
```cpp
int a = 1;
int b = 2;
int* p = &a; #ukazatel ukazuje na a
p = &b; # ukazatel ukazuje na b
int& r = a; #reference ukazuje na a
r = b; #reference nabírá hodnoty b, teď a = b
# a = b; je ekvivalentní
```
viz dokument, co jsem na to udělal ve stejném repu
### Jaký je rozdíl mezi mělkou a hlubokou kopií?
Mělká 1:1 zkopíruje obsah dvou objektů, structů, etc.
To může být problém třeba když mám nějakou dynamicky alokovanou paměť na ukazately. Protože se ukazatel zkopírují taky (jelikož ukazatel je číslo reprezentují číselnou adresu v paměti), tak to skončí tak, že **kopie objektu ukazuje na stejnou paměť jako původní objekt**. Takže si můžou paměť přepisovat, nebo může dojít k dvojitému uvolnění, nebo přístupu po uvolnění.
Hluboká kopie **zajišťuje zcela novou část paměti pro kopii. Ukazatele mají nyní vlastní unikátní adresy, ale zkopíruji do nich hodnotu v původní paměti.**
například na to můžu vytvořit kopírovací konstruktor...
# Programování v C++ # Programování v C++
### 1) Napište příklad načteni hodnoty typu int ze standarního vstupu pomocí proudového operátoru. Jak lze ošetřit správnost vstupu? ### 1) Napište příklad načteni hodnoty typu int ze standarního vstupu pomocí proudového operátoru. Jak lze ošetřit správnost vstupu?
```cpp ```cpp
@@ -403,3 +616,7 @@ Jinak je třeba definovat `>` `<` pomocí přetěžování operátorů a nebo do
- Co si představujete pod pojmem MVC? - Co si představujete pod pojmem MVC?
- Jaký je rozdíl mezi UDP a TCP transportní vrstvou? - Jaký je rozdíl mezi UDP a TCP transportní vrstvou?
- Co je to REST rozhraní? - Co je to REST rozhraní?
# Otázky proč
- proč píšu kopírovací konstruktor a nepřetěžuju operátor =?
-