Files
PPC/Zpracované Otázky.md

12 KiB

zatím nic moc, skoro nic nemám a není to moc podrobné 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.
    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í
    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?

2) Jak se v C++ provádí přetížení operátoru? Uveďte příklad.

3) Jaké operátory nelze v C++ přetížit?

Jak a kdy se volá konstruktor a destruktor?

Jaký je rozdíl mezi objektem alokovaným v zásobníku a objektem dynamicky alokovaným na haldě?

Jaký je rozdíl mezi operátory delete a delete[]?

Jaká je návratová hodnota destruktoru?

Co je třeba zajistit při dynamické alokaci? Uveďte příklad.

Co je to výjimka a k čemu je dobrá? Uveďte příklad.

Kolik výjimek je možné v programu ošetřit?

Co je to generická funkce?

Jak lze vytvořit explicitní instanci generické funkce? K čemu je to dobré?

Jak jsou obvykle parametrizovány šablony tříd?

V čem spočívá problém vícenásobného dědění? Jak je možné tomuto problému zabránit?

Co je to zapouzdření a čemu je dobré?

Jak lze využít implicitní hodnoty argumentu funkce? Uveďte příklad.

Jaký je rozdíl mezi deklarací třídy pomocí class a struct?

Co je to konverzní konstruktor?

Jaký je rozdíl mezi statickou a dynamickou vazbou?

Jaký je význam klíčového slova auto? Lze ho použít vždy?

Co přesouvací (move) kontruktor?

Co je pravidlo tří (rule of three)?

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

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:

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
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.

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).

#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í?