6 zpracovanych otazek v programovani c++

This commit is contained in:
2026-03-29 18:24:39 +02:00
parent 9ae161b10b
commit b32a47575d

View File

@@ -59,11 +59,110 @@ Poznámka: Příklady jsou zjednodušené a ne vždy jsou 100% syntakticky práv
- Jaký je rozdíl mezi mělkou a hlubokou kopií? - Jaký je rozdíl mezi mělkou a hlubokou kopií?
# 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
#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. ### 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? ### 3) Jaké operátory nelze v C++ přetížit?
### Jak a kdy se volá konstruktor a destruktor? Přetěžovat nelze operátory:
### 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[]`? - `::`
- `?:`
- `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
```
### Jaká je návratová hodnota destruktoru? ### Jaká je návratová hodnota destruktoru?
### Co je třeba zajistit při dynamické alokaci? Uveďte příklad. ### 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. ### Co je to výjimka a k čemu je dobrá? Uveďte příklad.