405 lines
20 KiB
Markdown
405 lines
20 KiB
Markdown
|
|
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
|
|
class Trida
|
|
{
|
|
public:
|
|
int cislo;
|
|
// tady jsou funkce a promenne
|
|
};
|
|
|
|
int main(void)
|
|
{
|
|
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í
|
|
```cpp
|
|
class Trida
|
|
{
|
|
public:
|
|
int a;
|
|
private:
|
|
int b;
|
|
protected:
|
|
int c;
|
|
};
|
|
|
|
int main(void)
|
|
{
|
|
|
|
}
|
|
```
|
|
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í?
|
|
# 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
|
|
#include <iostream>
|
|
|
|
int main(void)
|
|
{
|
|
int x;
|
|
if(std::cin >> x)
|
|
{
|
|
std::cout << "ok";
|
|
}
|
|
else
|
|
{
|
|
std::cout << "chyba";
|
|
}
|
|
}
|
|
```
|
|
|
|
Tenhle příklad načte hodnotu pomocí `std::cin >> x`, kde `x` je proměnná a `std::cin` je standardní input stream.
|
|
|
|
`std::cin >> x` vrací hodnotu `true` pokud je vše v pořádku a `false` pokud ne. Pokud se načte něco jiného jak číslo, tak třeba vrací false.
|
|
|
|
Kokrétněji `std::cin` má několik stavových bitů a to **fail** -> který je nastavený, když se něco pokazí (například špatný převod na typ -> string na int, etc.), **eof** -> který je nastavený, když je konec input streamu, **bad** -> který je nastavený, když se opravdu něco pokazí.
|
|
|
|
Když přečtu poslední znak, automaticky se nastaví eof bit a ten můžu zkontrolova pomocí `std::cin.eof() == true`. Složitější je, když se něco pokazí. To může být např. při špatném převodu nebo, když čtu po konci streamu a **je třeba to opravit**.
|
|
Nejprve je třeba nastavit `std::cin.clear()`, což vynuluje bity, takže můžu pokračovat ve čtení. To ale nestačí. Nezpracovaný text zůstane uložený v bufferu a přečte se znova příště. To jde vyřešit pomocí funkce `std::cin.ignore(int, char)`, kde int je počet znaků, co to vymaže a char je znak, kterým to končí, například `std::cin.ignore(1000, '\n')` vymaže 1000 znaků do konce řádky.
|
|
|
|
Btw `if(std::cin >> x)` vlastně vrací `if(!std::cin.fail())`
|
|
|
|
|
|
### 2) Jak se v C++ provádí přetížení operátoru? Uveďte příklad.
|
|
Přetěžování operátorů je implementace fungování znaků operátorů jako `+`, `-`, `>`, etc. pro objekty tříd, co napíšu.
|
|
Jsou dva způsoby jak to udělat. Buď na to napíšu funkci uvnitř třídy, pro kterou to chci implementovat, nebo na to napíšu samostatnou funkci mimo.
|
|
|
|
Používám na to speciální název funkce `operator`, ke které napíšu, jaký operátor řeším
|
|
Příklad uvnitř třídy:
|
|
```cpp
|
|
class Number
|
|
{
|
|
public:
|
|
int n;
|
|
Number(int set_n) {n = set_n;}
|
|
|
|
Number operator+(const Number &numA) //reference na objekt napravo od +
|
|
{
|
|
return Number(this->n + numA.n)
|
|
}
|
|
};
|
|
|
|
int main(void)
|
|
{
|
|
Number a(10);
|
|
Number b(20);
|
|
|
|
Number c = a + b;
|
|
}
|
|
```
|
|
|
|
Nebo mimo třídu to může vypadat například takto:
|
|
```cpp
|
|
Number operator+(const Vec& a, const Vec& b)
|
|
{
|
|
return Vec{a.x + b.x};
|
|
}
|
|
```
|
|
|
|
Btw, reference se používají, protože nekopírovat hodnoty, ale jenom na ně ukazovat, je šetrnější.
|
|
|
|
**Na tohle téma jsem udělal samostatný dokument na githubu (Přetěžování operátorů)**
|
|
### 3) Jaké operátory nelze v C++ přetížit?
|
|
Přetěžovat nelze operátory:
|
|
- `.`
|
|
- `::`
|
|
- `?:`
|
|
- `sizeof`
|
|
- `typeid`
|
|
|
|
Většinou to je proto, protože jsou v syntaxi tak důležité, že by to mohlo udělat nejasnosti v tom, jak by to měl vůbec kompilátor překládat. (Má tečku řešit jako člen, nebo jako něco úplně jiného... etc.) **Ty operátory totiž už většinou mají funkční účel předtím, než jsou přetížené a to u operátorů, co jdou přetížit neplatí.**
|
|
|
|
Na tohle téma jsem zpracoval mimochodem dokument na githubu.
|
|
### 4) Jak a kdy se volá konstruktor a destruktor?
|
|
Konstruktor se zavolá při vytvoření objektu. Můžu do něj dát jako argument hodnoty, které chci třeba využít při inicializaci.
|
|
|
|
Mám dva typa alokace objektů, které se dělají jinak. Jedna je statická a druhá je dynamická.
|
|
Staticky alokuju objektu takto: `Trida objekt(...);` a dynamicky pomocí **new**: `Trida* objekt = new Trida;`. Je v tom zásadní rozdíl v životnosti objektu. -> viz další otázka:
|
|
|
|
Destruktor se u statického objektu zavolá sám, když se dojde ke konci scopu (bloku kódu, funkce, etc...). Nemusím ho volat a ani bych neměl.
|
|
|
|
U dynamického objektu ho musím zavolat manuálně pomocí `delete objekt;` nebo v případě pole objektů pomocí `delete[] pole_objektu;`
|
|
|
|
Pozn: klasický dynamický objekt se řeší pomocí ukazatele na objekt a dereference
|
|
### 5) Jaký je rozdíl mezi objektem alokovaným v zásobníku a objektem dynamicky alokovaným na haldě?
|
|
|
|
- Statické objekty se automaticky zníčí, když opustí scope -> blok, funkci, etc.
|
|
- Dynamické objekty zůstávají v paměti, než jsou zničeny pomocí delete
|
|
|
|
Používají se často alternativy, například smart pointer -> drží pointer v objektu a když se zníčí, zníčí i dynamický objekt.
|
|
### 6) Jaký je rozdíl mezi operátory `delete` a `delete[]`?
|
|
- `delete` se používá pro uvolňování dynamického objektu
|
|
- `delete[]` se používá pro uvolňování pole objektů
|
|
|
|
```cpp
|
|
Trida* objekty = new Trida[7];
|
|
delete[] objekty; //uvolni cele pole objektu
|
|
```
|
|
### 7) Jaká je návratová hodnota destruktoru?
|
|
Destruktor nemá návratovou hodnotu. Jako u funkce void se z něj dá vrátit pomocí `return;`
|
|
### 8) Co je třeba zajistit při dynamické alokaci? Uveďte příklad.
|
|
Při dynamické alokaci si hlavně musím dávat pozor na to, že mám nad pamětí nonstop kontrolu (například nikde neztratím ukazatel na ní) a že ji správně dealokuju (nedojde k úniku paměti).
|
|
|
|
V moderním C++ to ale tolik řešit nemusím. Většinou použiju tzv. **smart pointer**. který automaticky dealokuje objekt, když skončí scope.
|
|
|
|
```cpp
|
|
#include <memory> //tohle je na smart ukazatele
|
|
#include <vector>
|
|
|
|
struct Node {int value;};
|
|
|
|
void main(void){
|
|
auto p = std::make_unique<Node>(); // alokace
|
|
} //po konci main automatické uvolnění
|
|
```
|
|
### 9) Co je to výjimka a k čemu je dobrá? Uveďte příklad.
|
|
Výjimky umožňuje kontrolovat chod programu a popasovat se s nečekanými chybami. Primárně jsou míněny pro řešení problémů, které programátor nemůže tak dobře ovlivnit, jako například práci se zdroji (třeba soubor) nebo množství dynamické paměti.
|
|
|
|
Výjimky existují všeho různého druhu, zde je příklad kódu:
|
|
```cpp
|
|
try
|
|
{
|
|
#nějaký kod
|
|
}
|
|
|
|
//catch("Text") {} //nedává smysl, nechytá se hodnota, ale typ
|
|
catch(const std::bad_alloc& e) {} //vyjímka špatné alokace
|
|
catch(int) {} //chytí všechny integery - které manuálně vyhodím
|
|
catch(std::exception) {} //chytí všechny chyby (věci typu chyba)
|
|
catch(...) {} //chytí úplně všechno - i to co manuálně vyhodím
|
|
```
|
|
|
|
**Mám na tohle téma samostatný dokument, kde toto téma zpracovávám.**
|
|
### 10) Kolik výjimek je možné v programu ošetřit?
|
|
Tbh, nechápu tuhle otázku
|
|
|
|
- Typů výjimek je hodně a kdyžtak si můžu vlastní dopsat.
|
|
- výjimek může program za běhu ošetřit neomezeně
|
|
- **Najednou (v jeden moment) je možné ošetřit pouze jednu výjimku. Pokud se jich objeví více (například z destruktorů), tak se pogram ukončí přes std::terminate**
|
|
|
|
### 11) Co je to generická funkce?
|
|
Generická funkce je funkce, která umí přijímat či vracet libovolný datový typ. je to šikovná alternativa k přetěžování funkcí.
|
|
|
|
K tomu používám `template <typename T>`, kde `T` reprezentuje libovoloný datový typ (to je moje pojmenování, ale jmenovat se to může jak chce, T se používá často...).
|
|
|
|
Příklad i s funkcí:
|
|
```cpp
|
|
template <typename T>
|
|
T secti(T a, T b)
|
|
{
|
|
return a + b;
|
|
}
|
|
```
|
|
Zde sčítám nějaké 2 obecné datové typy.
|
|
### 12) Jak lze vytvořit explicitní instanci generické funkce? K čemu je to dobré? - DOCELA MIZERNĚ
|
|
[stackoverflow](https://stackoverflow.com/questions/2351148/explicit-template-instantiation-when-is-it-used#2351622)
|
|
|
|
Explicitní instance je způsob, jak předem donutit kompilátor vytvořit šablonu - instanci generické funkce, než je použita.
|
|
```cpp
|
|
template int secti<int>(int, int);
|
|
```
|
|
|
|
Ono to údajně umožní zrychlit kompilaci protože tomu řeknu, ať to vytvoří tu int verzi předem.
|
|
Normálně bych do `.h` souboru napsal:
|
|
```
|
|
template <typename T>
|
|
T secti(T a, T b);
|
|
```
|
|
|
|
ale můžu místo toho do `cpp` souboru napsat:
|
|
```cpp
|
|
template <typename T>
|
|
T secti(T a, T b) {
|
|
return a + b;
|
|
}
|
|
|
|
template int secti<int>(int, int); // explicitní instance
|
|
```
|
|
|
|
kde se vytvoří verze s intem samostatně předem a pak místo toho, aby to kompilátor řešil 10x zrovna, když to potřebuje, tak to prostě zkopíruje.
|
|
|
|
Also to umožní fungování je některým typům?
|
|
|
|
Takže:
|
|
- umožní použití jen několik typů, které si určím
|
|
- zrychlý to kompilaci
|
|
### 13) Jak jsou obvykle parametrizovány šablony tříd?
|
|
### 14) V čem spočívá problém vícenásobného dědění? Jak je možné tomuto problému zabránit?
|
|
### 15) Co je to zapouzdření a čemu je dobré?
|
|
### 16) Jak lze využít implicitní hodnoty argumentu funkce? Uveďte příklad.
|
|
### 17) Jaký je rozdíl mezi deklarací třídy pomocí class a struct?
|
|
### 18) Co je to konverzní konstruktor?
|
|
### 19) Jaký je rozdíl mezi statickou a dynamickou vazbou?
|
|
### 20) Jaký je význam klíčového slova auto? Lze ho použít vždy?
|
|
### 21) Co přesouvací (move) kontruktor?
|
|
### 22) Co je pravidlo tří (rule of three)?
|
|
### 23) Jaký je tvar definice lambda funkce v C++? Uveďte příklad a popište, co funkce dělá.
|
|
# STL kontejnery
|
|
### 1) Co je to kontejner?
|
|
Kontejnery jsou datové struktury určené k ukládání kolekce dat (hodnot) a k manipulaci s nimi. Například to je `vector`, který funguje jako dynamické pole.
|
|
|
|
Máme různé typy kontejnerů - sekvenční asociativní (a pak údajně neseřazený asociativní a adaptery pro jiné ovládání existujících kontejnerů, ale to raději neřešme). Viz. další otázka.
|
|
|
|
Hlavní smysl kontejnerů je ulehčit práci při programovaní. Je to často již implementované řešení, které se v kódu jednoduše používá, nebo je to rada, jak si takové řešení udělat. Je to vrstva abstrakce.
|
|
### 2) Jaký je rozdíl mezi sekvenčními a asociativními kontejnery? Uveďte příklad.
|
|
**Sekvenční kontejnery** pracují s daty nezávisle na jejich hodnotě. To je míněno tak, že třeba data ukládají dle pořadí, ve kterém do kontejneru přišli a data mají unikátní index. Je to například `std::vector` a `std::list`
|
|
|
|
**Asociativní kontejnery** řeší data většinou dle nějakého klíče, který je k nim přiřazen. Například `std::map`. Data jsou pak seřazena tak, aby bylo například efektivní vyhledávání a místo indexu mají právě na vyhledání klíč.
|
|
- `std::map` - data seřazeny dle porovnávací funkce
|
|
- `std::unordered_map` - data neseřazeny a hledány dle jejich hashe
|
|
### 3) Jaké jsou klíčové vlastnosti kontejneru std::vector?
|
|
**Vector** je prakticky **dynamické** **pole** s podobnými vlastnostmi jako jeho implementace v C++, akorát to celé někdo implementoval v třídě s funkcemi za nás.
|
|
- Data jsou seřazeny za sebou dle jejich velikosti v paměti. (tedy 5 prvek int o velikosty 4 byty je na 17-20 bytu)
|
|
- Vyhledávání konkrétního prvku je O(1) -> dopočítám hned z velikosti a pozice
|
|
- přidání/odstranění na konec - O(1)
|
|
- Odstranění a přidání je kamkoli - O(n) -> vyžaduje přesun všech prvků v poli
|
|
- pole má hodnotu velikosti (kolik zabírá bytů prvky) a kapacity (kolik bytů si dynamicky rezervuje). Kapacita musí být větší než velikost, jinak je třeba přealokovat
|
|
- adresy prvků nejsou stabilní kvůli realokaci
|
|
|
|
`std::vector<int> kontejner1`;
|
|
### 4) Jaké jsou klíčové vlastnosti kontejneru std::map?
|
|
Ukládá si pro každý prvek 2 hodnoty a to **klíč a hodnotu**. Všechny prvky jsou seřazené podle klíče a jeho porovnávací funkce, který zajišťuje operace o O(log n). Seřazení může třeba být binární strom.
|
|
|
|
Kontejner umožňuje vymyslet a vložit vlastní porovnávací funkci v šabloně.
|
|
### 5) Jaké jsou klíčové vlastnosti kontejneru std::list?
|
|
List je kontejner, který vlastně není moc odlišný od toho, co by člověk čekl (pokud si to pamatuje).
|
|
Data jsou uložena každá ve vlastní buňce v paměti. Každá buňka umožňuje přístup k dalšímu a předchozímu prvku (pamatuji se jejich ukazatele).
|
|
|
|
- proto je každá buňka bezpečně samostatně uložena v paměti nezávisle na ostatních buňkách
|
|
- Je jednoduché přidávat/odebírat na známé pozice prvky - O(1) -> stačí změnit ukazatele v buňkách předchozí a další buňky (říká se tomu často uzel).
|
|
- Hledání prvku na n-té pozice je obtížné, je třeba projít všechny prvky, které k němu vedou - O(n)
|
|
|
|
- vhodné pro potřebu čistého rychléhi přidávání a mazaání prvků, ale nevhodné pro rychlý náhodný přístup
|
|
|
|
`std::list<int> L;`
|
|
### 6) Jakého datového typu může být klíč kontejneru std::map?
|
|
Klíč `std::map` může být kteréhokoli typu, který je možná porovnávat pomocí řazení (má operátor `>` a `<`). Nebo je možné dodat vlastní porovnávací funkci (komparátor).
|
|
### 7) Co je třeba zajistit v případě, že klíčem v kontejneru std::map je strukturovaný datový typ (např. naše vlastní třída)?
|
|
- buď je třeba zajistit, aby objekty třídy byly porovnatelné pomocí `>` a `<` například pomocí přetěžování operátorů
|
|
- nebo je možné sepsat vlastní comparator (vlastní porovnávací funkci)
|
|
### 8) Jaký je význam datového typu std::pair?
|
|
`std::pair` je datový typ, který umí ukládat 2 prvky libovolného typu
|
|
|
|
```cpp
|
|
pair<int, string> p = {1, "ahoj"};
|
|
p.first = 7;
|
|
p.second = "krkavců";
|
|
```
|
|
|
|
vhodné je se i podívat na operaci vzájemného porovnávání párů
|
|
### 9) Co je to iterátor? Uveďte příklad.
|
|
Iterátor je třída, která je spojená s určitým kontejnerem. Úkol prvků této třídy je jednoduchý a to umožnění jednoduché procházení prvky kontejneru.
|
|
|
|
Iterátor by tedy měl být dereferencovatelný -> dereferencí `*it` získáme hodnotu nynějšího prvku, jako by to byl ukazatel. Dále přičtením `++it` získáme další prvek kontejneru. Iterátoru přiřadíme hodnotu pomocí funkcá `.begin()` -> hodnota prvního iterátoru, a zjišťujeme konec kontejneru pomocí `.end()`.
|
|
|
|
Příklad:
|
|
```cpp
|
|
std::vector<int> pole = {1, 2, 3};
|
|
std::vector<int>::iterator it = pole.begin();
|
|
|
|
for(std::vector<int>::iterator it = pole.begin(); it != pole.end(); ++i)
|
|
{
|
|
std::cout << *it << std::endl;
|
|
}
|
|
```
|
|
### 10) Jaký je rozdíl mezi konstantním a nekonstantním iterátorem?
|
|
- Pomocí **nekontantního** iterátoru můžu měnit hodnotu prvku, na který ukazuje.
|
|
- Hodnotu prvku na který ukazuje **konstantní** iterátor měnit nemůžu.
|
|
- Potřebuji změnit typ iterátoru a také používám speciální funkci
|
|
|
|
```cpp
|
|
std::vector<int> pole = {1, 2, 3};
|
|
std::vector<int>::iterator it = pole.begin();
|
|
std::vector<int>::const_iterator cit = pole.cbegin(); //vlastni funkce
|
|
|
|
*it = 10; //můžu
|
|
*cit = 20; //nesmim, je to const...
|
|
```
|
|
|
|
### 11) Co všechno je třeba zajistit pro vytvoření vlastního iterátoru?
|
|
- iterátor musí mít dereferenci -> lze získat hodnotu jeho prvku
|
|
- lze přičítat takto `++it`
|
|
- lze odčítat takto `--it'
|
|
- lze porovnávat `==` a `!=` -> hlavně pro `.begin()` a `.end()`
|
|
|
|
zbytek podle kontejneru a kontextu (a podle toho, jak je vlastně vůbec myšlena tato otázka)
|
|
- je třeba mít `end` a `begin`, konstruktor u kontejneru etc...
|
|
### 12) Co je range-for cyklus? Uveďte příklad.
|
|
Je to specifický zápis `for` loop, který umžňuje iterovat všemi prvkami kontejneru.
|
|
|
|
```cpp
|
|
std::vector<int> pole = {1, 2, 3};
|
|
|
|
for (auto &i : pole)
|
|
{
|
|
i++;
|
|
}
|
|
```
|
|
|
|
V tomto kódu se projedou všehny hodnoty vektoru a přičte se k ním jedna.
|
|
`for (auto &i : pole)` -> napravo je název pole, nalevo je hodnotu prvku, používá se auto s referencí, aby se fyzicky nekopíroval každý prvek a bylo to nezávislé na typu.
|
|
|
|
prvek `i` pak reprezentuje aktuálně prvek iterace, tedy nabere hodnotu každého prvku pole
|
|
|
|
**Obdobně lze udělat loop i pro iteraci listem**.
|
|
### 13) Uveďte příklad použití algoritmu sort (deklarujte vektor libovolného datového typu, vložte do něj data a vektor seřaďte).
|
|
|
|
```cpp
|
|
#include <iostream>
|
|
#include <vector>
|
|
#include <algorithm>
|
|
|
|
int main() {
|
|
std::vector<int> v = {5, 2, 9, 1, 7};
|
|
std::sort(v.begin(), v.end());
|
|
for (const auto& x : v)
|
|
{
|
|
std::cout << x << " ";
|
|
}
|
|
return 0;
|
|
}
|
|
```
|
|
|
|
Sort porovná prvky podle jejich operárů `<` a `>`, funguje univerzálně u všech typů, pokud mají porovnávání definované.
|
|
|
|
U stringů to třeba porovnává lexikograficky.
|
|
Jinak je třeba definovat `>` `<` pomocí přetěžování operátorů a nebo dodat vlastní porovnávací funkci. -> `std::sort(v.begin(), v.end(), comparator)` -> kde comparator je porovnávací funkce
|
|
# Praktické programování (Qt a související)
|
|
- Co je to event-driven programování?
|
|
- Jaký je rozdíl mezi událostí a signálem?
|
|
- Uveďtě příklady událostí v Qt a jejich využití.
|
|
- Popište systém signálů a slotů, uveďte příklad propojení.
|
|
- Jakým způsobem lze vytvořit v Qt okno a v něm vykreslit grafickou komponentu?
|
|
- Jak lze měnit grafickou podobu jednotlivých Qt komponent?
|
|
- 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í? |