|
|
|
|
@@ -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.)
|
|
|
|
|
# Principy objektového programování
|
|
|
|
|
1) 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.
|
|
|
|
|
```cpp
|
|
|
|
|
### 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.
|
|
|
|
|
```cpp
|
|
|
|
|
class Trida
|
|
|
|
|
{
|
|
|
|
|
public:
|
|
|
|
|
@@ -16,11 +16,11 @@ Poznámka: Příklady jsou zjednodušené a ne vždy jsou 100% syntakticky práv
|
|
|
|
|
Trida objekt;
|
|
|
|
|
objekt.cislo = 10;
|
|
|
|
|
}
|
|
|
|
|
```
|
|
|
|
|
2) Jak je určena viditelnost členských proměnných a metod?
|
|
|
|
|
- public -> přístup možný odkudkoli z programu
|
|
|
|
|
- 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í
|
|
|
|
|
```
|
|
|
|
|
### Jak je určena viditelnost členských proměnných a metod?
|
|
|
|
|
- public -> přístup možný odkudkoli z programu
|
|
|
|
|
- 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í
|
|
|
|
|
```cpp
|
|
|
|
|
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?
|
|
|
|
|
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?
|
|
|
|
|
- **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
|
|
|
|
|
- Co je polymorfismus a jak je ho dosaženo?
|
|
|
|
|
- Co je to bázová třída a čím se vyznačuje?
|
|
|
|
|
- Uveďte příklad deklarace plně virtuální metody?
|
|
|
|
|
- Co je to implicitní konstuktor?
|
|
|
|
|
- Co je to kopírovací konstruktor?
|
|
|
|
|
- Jaké jsou možnosti dědění? Uveďte příklady.
|
|
|
|
|
- Co je to virtuální dědění a k čemu je dobré?
|
|
|
|
|
- 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).
|
|
|
|
|
- Jaký je rozdíl mezi přepsáním (override) a přetížením (overload)?
|
|
|
|
|
- Co je vazba typu kompozice? Uveďte příklad (několik řádek kódu, ze kterých bude zřejmé, o co jde).
|
|
|
|
|
- Co je vazba typu asociace? Uveďte přiklad (několik řádek kódu, ze kterých bude zřejmé, o co jde).
|
|
|
|
|
- Co reprezentuje klíčové slovo this?
|
|
|
|
|
- Jaký je rozdíl mezi referencí a ukazatelem?
|
|
|
|
|
- Jaký je rozdíl mezi mělkou a hlubokou kopií?
|
|
|
|
|
### 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();`
|
|
|
|
|
### 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
|
|
|
|
|
- **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?
|
|
|
|
|
**Polymorfismus** je koncept, kdy jeden interface (třeba metoda) lze univerzálně použít pro více datových typů.
|
|
|
|
|
|
|
|
|
|
Toho se dosáhne pomocí více různých implementací.
|
|
|
|
|
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í.
|
|
|
|
|
|
|
|
|
|
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.
|
|
|
|
|
|
|
|
|
|
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)
|
|
|
|
|
### Co je to bázová třída a čím se vyznačuje?
|
|
|
|
|
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).
|
|
|
|
|
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.
|
|
|
|
|
Bázová třída může nebo nemusí obsahovat třeba virtuální metody nebo může nebo nemusí být plně virtuální.
|
|
|
|
|
**Prostě je to třída z které někdo dědí, to je všechno.**
|
|
|
|
|
### 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.)
|
|
|
|
|
|
|
|
|
|

|
|
|
|
|
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++
|
|
|
|
|
### 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
|
|
|
|
|
@@ -402,4 +615,8 @@ Jinak je třeba definovat `>` `<` pomocí přetěžování operátorů a nebo do
|
|
|
|
|
- Co se časovač (QTimer), k čemu je dobrý a jak se používá?
|
|
|
|
|
- Co si představujete pod pojmem MVC?
|
|
|
|
|
- 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 =?
|
|
|
|
|
-
|