vypracovani temat z 3. prednasky
This commit is contained in:
85
3. týden.md
Normal file
85
3. týden.md
Normal file
@@ -0,0 +1,85 @@
|
||||
s- výjimky
|
||||
- reference
|
||||
- konstantní metody/atributy
|
||||
- přetížené operátory
|
||||
- indexování + volání funkce (oboje jsou operátory)
|
||||
- lambda funkce
|
||||
|
||||
- cvičení
|
||||
- conteinery: vector, list, mapa
|
||||
-
|
||||
# Výjimky
|
||||
- Pozn: "Častokrát je možná lepší, když ten program spadne, než když se chová špatně."
|
||||
- Řešení neočekávaných chyb
|
||||
- Může se to stát náhodně (např. poškozený/přeplněná paměť)
|
||||
- používá se **try** a **catch**
|
||||
```
|
||||
try {
|
||||
# kod kde nastane vyjimka / problem
|
||||
}
|
||||
catch (typ vyjimky) {
|
||||
# kod, ktery se s vyjimkou popasuje
|
||||
}
|
||||
```
|
||||
|
||||
knihovna: `#include <exception>`
|
||||
Pak existuje ještě třetí operátor a to operátor `throw`, který vyvolává výjimku.
|
||||
např `throw "Deleni nulou.\n` -> vyvolá výjimku **Deleni nulou\n**
|
||||
``
|
||||
## Ošetření více výjimek
|
||||
```
|
||||
catch (typ vyjimky) {
|
||||
# kod, ktery se s vyjimkou popasuje
|
||||
}
|
||||
catch (...) {
|
||||
# univerzalni reseni vyjimek pro vsechno ostatní
|
||||
}
|
||||
```
|
||||
## Typy výjimek
|
||||
- `<exceptions>`
|
||||
- `std::exception` - bázová třída
|
||||
- `virtual what()` - vrací řetězec výjimky
|
||||
- `terminate()` - ukončí program, když se něco pokazí?
|
||||
- `<stdexcept>`
|
||||
- `std::out_of_range`
|
||||
- nestihl
|
||||
- nestihl
|
||||
- `<new>`
|
||||
- nestihl
|
||||
- nestihl
|
||||
|
||||
# Reference
|
||||
- ukazatelé byly označeny komunitou C++ jako nebezpečné např. kvůli nejasné syntaxi
|
||||
- Reference je obdoba konstantního ukazatele
|
||||
- nelze vytvořit prázdnou referenci, je svázána s hodnotou a ne adresou (?)
|
||||
- Pokud možno **pls používat reference**
|
||||
|
||||
- Reference
|
||||
# Přetížené operátory
|
||||
- stejně jako funkce lze přetížit operátory (protože to jsou vlastně takové funkce)
|
||||
|
||||
- operátory definované pro dané datové typ nelze přetížit
|
||||
- týká se to hlavně operátorů pro instance tříd
|
||||
- např nelze přetížit: `.` `.*` `::` `?:` `sizeof`
|
||||
|
||||
## Přetížení binárních operátorů
|
||||
např: `+, -, *, ..., +=, -=, ...`
|
||||
používá se `@`
|
||||
např: `x @ y`
|
||||
|
||||
## Přetížení unárních operátorů
|
||||
|
||||
## Přetížení postfixových operátorů
|
||||
# Lambda funkce
|
||||
|
||||
- existuje něco jako funktor :C
|
||||
- místo funktoru mám lambda funkce
|
||||
- každou lambda funkci můžu přepsat do funktoru
|
||||
|
||||
# Conteinery
|
||||
|
||||
## Vector
|
||||
|
||||
## List
|
||||
|
||||
## Map
|
||||
74
Funktory a Lambda funkce.md
Normal file
74
Funktory a Lambda funkce.md
Normal file
@@ -0,0 +1,74 @@
|
||||
# Funktory
|
||||
Jsem línej to víc rozepsat... pozn. pro sebe dodělat funktory potom. Teď mám přibližné vysvětlení v Přetěžování operátorů.
|
||||
Prostě to je objekt, co se chová jako funkce, ale je uložený jako objekt (jako proměnná) v kódu a může mít vnitřní funkce a proměnné. Užitečné to je třeba když chci funkci, co si umí pamatovat data z každého zavolání (třeba sčítá všechny čísla, co do ní jsou poslány jako argumenty).
|
||||
# Lambda funkce
|
||||
- lambda funkce jsou primárně způsob, jak zjednodušit zápis funktoru.
|
||||
- [lambda gfg](https://www.geeksforgeeks.org/cpp/lambda-expression-in-c/)
|
||||
- [lambda capture gfg](https://www.geeksforgeeks.org/cpp/lambda-capture-clause-in-cpp/)
|
||||
|
||||
Lambdy jsou divný... ale užitečný. Jde o to, že někdy chci mít možnost napsat hodně rychlou funkci, bez toho, abych ji někde musel definovat. Vytvořím tedy vlastně funkci do proměnné, a využiji ji přímo na místě a pak ji třeba hned zahodím.
|
||||
|
||||
Syntax:
|
||||
```cpp
|
||||
[](int a, int b) {return a + b;}
|
||||
```
|
||||
což je `[capture](parametry) -> návratový_typ { tělo }` ale hodně je optional... (třeba capture)
|
||||

|
||||
|
||||
Příklad: Řekněme, že si někde potřebuju nutně definovat sčítání (protože mám hloupý cpp a zapomnělo to, nebo idk :( )
|
||||
```cpp
|
||||
auto add = [](int a, int b) {return a + b;};
|
||||
|
||||
int x = add(3,4);
|
||||
```
|
||||
|
||||
Mám zde funkci, co je vlastně "uložená v proměnné". Ve skutečnosti je to ale jenom **funktor** tedy alternativa pro:
|
||||
```cpp
|
||||
class __Lambda123
|
||||
{
|
||||
public:
|
||||
int operator()(int x, int y)
|
||||
const {
|
||||
return x + y;
|
||||
}
|
||||
};
|
||||
|
||||
__Lambda123 add;
|
||||
```
|
||||
|
||||
**Lambda funkce se musí ukládat do proměnných typu `auto`!!
|
||||
|
||||
Co je *capture*?
|
||||
Lambda funkce umožňuje přijmout hodnoty/proměnné z lokálního bloku a dále s nimi pracovat jako s vlastními proměnnými.
|
||||
Mám 2 typy *capture* a to *capture by reference* a *capture by value*. Jedno mi umožňuje vzít referenci k proměnným/objektům a v lambdě je měnit. Druhé mi umožňuje hodnoty do lambdy prostě zkopírovat.
|
||||
|
||||
Př: (ukradeno z geeks for geeks)
|
||||
```cpp
|
||||
int main() {
|
||||
vector<int> vec1 = {10, 20, 30, 40, 50}; //vektory jsou jako pole
|
||||
vector<int> vec2 = {1, 2, 3, 4, 5};
|
||||
|
||||
auto lambda = [&vec1, vec2]() //& je ref. a druhé je pouze hodnota
|
||||
{
|
||||
for (int& num : vec1) {num *= 10;}
|
||||
for (int num : vec2) {cout << num * 10 << " ";}
|
||||
cout << endl;
|
||||
};
|
||||
|
||||
lambda();
|
||||
|
||||
cout << "Vector 1: ";
|
||||
for (int num : vec1) cout << num << " ";
|
||||
|
||||
cout << "\nVector 2: ";
|
||||
for (int num : vec2) cout << num << " ";
|
||||
|
||||
return 0;
|
||||
}
|
||||
```
|
||||
|
||||
Další možnosti:
|
||||
```cpp
|
||||
auto lambda1 = [&](int x){}; //VŠECHNY externí proměnné jako refernec
|
||||
auto lambda2 = [=](int x){}; //VŠECHNY externí proměnné jako hodnotu
|
||||
```
|
||||
183
Přetěžování operátorů.md
Normal file
183
Přetěžování operátorů.md
Normal file
@@ -0,0 +1,183 @@
|
||||
- *operator overloading*
|
||||
- prakticky definování operací s operátory (např. +, -, /, etc.) pro objekty
|
||||
- [oficiální dokumentace](https://isocpp.org/wiki/faq/operator-overloading/1000)
|
||||
- [geeks for geeks](https://www.geeksforgeeks.org/cpp/operator-overloading-cpp/)
|
||||
- [krátké YT video](https://www.youtube.com/watch?v=9tHu4mWtrnM&pp=ygUYY3BwIG9wZXJhdG9yIG92ZXJsb2FkaW5n) které jsem trochu vykradl
|
||||
|
||||
Když si vytvoříme třídu, chceme někdy mít jednoduchou práci při pracování s více jejími objekty. Pokud mám třeba třídu `ComplexNumber`" a chci sečíst 2 její objekty, musel bych normálně vytvořit vlastní funkci, která mi to umožní. Přetěžování operátorů mi ale zjednoduší práci. **Místo sepsání funkce pro součet si nadefinuji, že pokud sečtu 2 objekty pomocí operátoru `+`, tak se sečtou.**
|
||||
|
||||
Příklad:
|
||||
```cpp
|
||||
class Number
|
||||
{
|
||||
public:
|
||||
int n;
|
||||
|
||||
Number(int set_n) {n = set_n;}
|
||||
};
|
||||
|
||||
int main()
|
||||
{
|
||||
Number a(5);
|
||||
Number b(10);
|
||||
|
||||
Number c = a + b; //TOTO BY SE NÁM HODILO, ALE VYHODÍ TO ERROR
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
```
|
||||
V kódu se snažím sečíst dva různé objekty, ale nejde to, protože součet dvou objektů typu `Number` není definován (stejně jako není definován součet 2 objektů typu chyba, nebo čehokoli jiného).
|
||||
**Dostanu error ve stylu:** `Invalid operands to binary expression ('Number' a...)`
|
||||
|
||||
**Já to ale můžu spravit tím, že si operaci pro součet sám definuju...**
|
||||
```cpp
|
||||
#include <iostream>
|
||||
|
||||
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()
|
||||
{
|
||||
Number a(5);
|
||||
Number b(10);
|
||||
|
||||
Number c = a + b; //TED FUNGUJE
|
||||
|
||||
std::cout << c.n << std::endl;
|
||||
return 0;
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
Takže co se děje...
|
||||
Tady je příklad binárního operátoru `+`. V podstatě to je ekvivalent zavolání funkce z objektu `a`, která by se mohla jmenovat `vrat_muj_soucet_s_necim_jak_objekt` (hrozné jméně, já vím). **V podstatě `+` je nyní funkce objektu nalevo a to co je napravo od `+` je argument této funkce.**
|
||||
|
||||
Je dobrý ale vědět, že operátory se nemusí přetěžovat jenom přes funkci objektu/třídy. Přetěžovat se dá i pomocí **nečlenské funkce** (normální funkce, která není součástí žádné třídy).
|
||||
|
||||
Příklad:
|
||||
```cpp
|
||||
Number operator+(const Vec& a, const Vec& b)
|
||||
{
|
||||
return Vec{a.x + b.x};
|
||||
}
|
||||
```
|
||||
Toto funguje, i když to není v třídě `Number`. Pomocí nečlenské funkce lze mít součty 2 různých objektů, kde nalevo není objekt třídy, např: `5 + a`.
|
||||
|
||||
# Typy operátorů a jejich přetěžování
|
||||
Existuje více typů operátorů valná většina z nich se dá přetěžovat. Přetěžovat ale nelze operátory:
|
||||
- `.`
|
||||
- `::`
|
||||
- `?:`
|
||||
- `sizeof`
|
||||
- `typeid`
|
||||
## Binární operátory
|
||||
- operáty s více stranami
|
||||
- `např +, -, /, %` etc.
|
||||
|
||||
Ve třídě:
|
||||
```cpp
|
||||
class Vec
|
||||
{
|
||||
public:
|
||||
int x;
|
||||
|
||||
Vec operator+(const Vec& other)
|
||||
const {
|
||||
return Vec{x + other.x};
|
||||
}
|
||||
};
|
||||
```
|
||||
`a + b` je prakticky `a.operator+(b)`
|
||||
|
||||
Mimo funkci:
|
||||
``` cpp
|
||||
Vec operator+(const Vec& a, const Vec& b)
|
||||
{
|
||||
return Vec{a.x + b.x};
|
||||
}
|
||||
```
|
||||
`a + b` je prakticky `operator+(a, b)`
|
||||
|
||||
## Unární operátory (prefixové)
|
||||
- mají pouze jeden člen
|
||||
- operátory prefixové se píšou před členem
|
||||
- př: `-a, ++a`
|
||||
|
||||
Ve třídě:
|
||||
```cpp
|
||||
class Vec
|
||||
{
|
||||
public:
|
||||
int x;
|
||||
|
||||
Vec operator-()
|
||||
const {
|
||||
return Vec{-x};
|
||||
}
|
||||
};
|
||||
```
|
||||
|
||||
`-a` je prakticky funkce `a.operator-()`
|
||||
`const` v tomto případě znamená, že se nezmění objekt `this`. Ono to v tomto případě ani nedává smysl, jelikož chceme vrátit `-a`, ale nechceme změnit `a` na `-a`... Tho, ten syntax je matoucí.
|
||||
**Přesněji** `const` před `{}` znamená, že metoda **nesmí měnit objekt** na kterém byla zavolaná.
|
||||
Nesmím pak měnit proměnné objektu a volat jeho funkce, co nejsou stejně `const`. **Umožní mi to ale volat funkci i na const objektu**.
|
||||
|
||||
## Unární operátory (postfixové)
|
||||
- pouze jeden člen
|
||||
- píší se za členem
|
||||
- mají dummy parametr -> to je trik jak odlišit `++a` od `a++`
|
||||
- např: `a++`
|
||||
|
||||
```cpp
|
||||
Vec operator++(int)
|
||||
{
|
||||
Vec old = *this;
|
||||
x++; //kde x je promenna Vec
|
||||
return old;
|
||||
}
|
||||
```
|
||||
`a++` je prakticky `a.operator++(0)`
|
||||
`this` je ukazatel a já nechci kopírovat ukazatel, ale to na co ukazuje, proto:
|
||||
`Vec old = *this;`
|
||||
|
||||
**Proč se to sakra píše jako:** `operator++(int)` **s int?** (`a.operator++(0)` -> dělá kompilátor). Protože by jinak nešlo rozlišit `++a` a `a++`. Proto je konvence, že `a++` je `operator++(int)` a `++a` je `operator++()`.
|
||||
|
||||
## Ostatní
|
||||
Operátor přístupu:
|
||||
```cpp
|
||||
int& operator[](size_t i)
|
||||
{
|
||||
return data[i];
|
||||
}
|
||||
```
|
||||
`a[i]` -> `a.operator[](i)`
|
||||
`int&` protože jsem šetrný a vracím referenci na prvek -> něco co ukazuje na jeho hodnotu a ne jeho
|
||||
|
||||
**Funktor**:
|
||||
```cpp
|
||||
class Functor
|
||||
{
|
||||
public:
|
||||
int operator()(int x) {
|
||||
return x * 2;
|
||||
}
|
||||
};
|
||||
```
|
||||
`a(i)` -> `f.operator()(i)`
|
||||
|
||||
Funktory jsou důležité! Funktory jsou objekty, které se chovají jako funkce a hádám (teď to nedokážu říct), že o nich uslyšíme ještě dost.
|
||||
Jejich hlavní smysl je **být něco mezi objektem a funkcí**. Funkce nemá žádnou paměť, což znamená, že vždy dává stejný výsledek při stejném vstupu (i mean ne nutně, jako když použiju náhodná čísla, tak ne... buuuhuuu, ale chápeme se...).
|
||||
Funktor mi umožňuje udělat objekt, který "předstírá, že je funkce". Pamatuje si svoje operace a může ukládat do vnitřních proměnných při každém zavolání/upravě, etc...
|
||||
|
||||
Dále jde přetěžovat třeby `->`. Operátorů je opravdu hodně...
|
||||
51
Reference.md
Normal file
51
Reference.md
Normal file
@@ -0,0 +1,51 @@
|
||||
Reference je v podstatě jako **konstantní ukazatel** s jistými omezeními:
|
||||
|
||||
- musí být inicializována při vytvoření
|
||||
- nemůže být null
|
||||
- nedá se měnit, kam ukazuje (stejně jako konst. uk.) a neumí aritmetiku
|
||||
|
||||
**Používá se jako normální proměnná se jménem (bez \*)**
|
||||
|
||||
Zásadní mentální rozdíl taky můžeme hledat v tom, co to vlastně je. Ukazatel je proměnná s adresou v paměti, zatímco reference je alias pro objekt/proměnnou.
|
||||
|
||||
```
|
||||
int x = 5; # nějaká proměnná x
|
||||
|
||||
int& r = x; #inicializace reference, musí mít hodnotu.
|
||||
#int& r; #není možné
|
||||
|
||||
int* p; # ukazatel to umí - pro srovnání
|
||||
p = &x;
|
||||
```
|
||||
|
||||
Referenci nelze přesměrovat na jinou adresu/proměnnou
|
||||
```
|
||||
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í
|
||||
```
|
||||
|
||||
- Reference nemá vlastní adresu, není to proměnná a nebo objekt. Pokud se pokusím získat adresu reference, dostanu adresu objektu, na který ukazuje.
|
||||
|
||||
K čemu to je dobré?
|
||||
- stále můžu používat referenci na předání funkci. **To je hlavní důvod existence referencí - bezpečnější a čitelnější předávání parametrů místo ukazatelů.**
|
||||
```
|
||||
void increment(int& r)
|
||||
{
|
||||
r++; #melo by zvysit jakoukoli promennou, co je predana jako parametr
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
int x = 42;
|
||||
increment(x); #zde predam proste puvodni promennou
|
||||
}
|
||||
```
|
||||
|
||||
- **Je to omezenější než ukazatel a proto je tu menší šance, že se uživatel střelí do nohy. Když to stačí, mělo by se to používat místo ukazatele. Doporučuje se to.**
|
||||
98
Výjimky.md
Normal file
98
Výjimky.md
Normal file
@@ -0,0 +1,98 @@
|
||||
Výjimka je způsob jak aktivně kontrolovat správný chod programu a popasovat se s nečekanými chybami. V podstatě mě zajímají 3 hlavní operátory a to:
|
||||
- **try** -> blok, ve kterém se snažím zachytit chybu
|
||||
- **catch** -> blok, který řeší co se stane, když nastane chyba
|
||||
- **throw** -> operátor, který umí chybu vyhodit
|
||||
|
||||
Dále se u základní C++ setkáme s třemi knihovnami, které s chybami souvisí a to?
|
||||
- `<exception>` - základní funkcionalita chyb
|
||||
- `<stdexcept>` - seznam typů chyb, které můžeme využít na "házení" při problémech
|
||||
- `<new>` - umí vyhazovat chyby typické u práci s pamětí (třeba nedostatek místa)
|
||||
|
||||
Funkcionalitu musíme přidat pomocí `#include <exceptions>`
|
||||
|
||||
Hlavní smysl chyb je zachytit nečekané věci v programu. Neměli bychom řešit problémy s kterými počítáme. Zatímco můžeme řešit třeba dělení nulou, které nestane při očekáváném vstupu od uživale (a nějaký typ chyby na to existuje), tak protože to čekáme a připravujeme se na to, tak bychom to měli řešit spíše jinak. Chyba má smysl hlavně v případech, které nelze odtušit a to například:
|
||||
- otevření souboru, který je prázdný
|
||||
- nedostatek paměti
|
||||
- přetečení
|
||||
Chyby jsou praktické, ale zatěžují program. Proto je třeba s nimi být opatrný a nepoužívat je na všechno zbytečně (a také samozřejmě kvůli přehlednosti).
|
||||
|
||||
Pro embedded systémy existuje alternativní způsob jak řešit chyby, který není tak náročný a to `std::optional` a `std::expected` v C++23.
|
||||
|
||||
# Základ
|
||||
|
||||
Strukturálně program s chytáním chyb vypadá:
|
||||
```cpp
|
||||
try
|
||||
{
|
||||
# zde je blok kde hledám chybu
|
||||
}
|
||||
catch
|
||||
{
|
||||
# zde je blok kde řeším chybu
|
||||
}
|
||||
```
|
||||
|
||||
## Try
|
||||
`try` funguje jednoduše, všechno co je uvnitř je zpracovaný výjimka a můžu řešit, co s ní pak udělám pomocí `catch`. S tím pak můžu řešit důmyslnou logiku výjimek, kdy na různých vrstvách programu řeším různé problémy dle toho, kdy se mi to hodí.
|
||||
Například na nízké vrstvě můžu vyhodit nějakou chybu ze špatné operace. na střední vrstvě se rozhodnu, jestli je řešitelná (můžu ji třeba napravit) a nebo jestli ne. Pokud ne, tak ji pošlu do vysoké vrstvy, která ji chytí a vypíše uživateli a ukončí proces, kde vznikla.
|
||||
|
||||
Všechny chyby, které nejsou chyceny pomocí `try` spustí `std::terminate`, což způsobí pád programu.
|
||||
|
||||
Tohle je vhodné si spojit ještě s konceptem **stack unwinding**. To je jak chyba cestuje -> stále nahoru v cestě programu (stack -> cesta volání - spíš paměť, kde je cesta uložena). Všechno putuje nahoru a když to skončí úplně nahoře v main, tak je průser.
|
||||
|
||||
## Throw
|
||||
`throw` vyhazuje chybu. Může to být text, např: `throw "Tady je chyba\n";` , ale obecně je spíš vhodné vyhodit nějaké oficiální objekt představující nějaký typ chyby z `<stdexcept>`.
|
||||
|
||||
např: ` throw std::invalid_argument( "received negative value" );`
|
||||
- zde je možné poslat společně s typem chyby argument se zprávou...
|
||||
|
||||
|
||||
## Catch
|
||||
V bloku `catch`, který následuje za `try` se řeší, jak se zachovat v případě nějaké chyby
|
||||
```cpp
|
||||
try
|
||||
{
|
||||
#něco
|
||||
}
|
||||
|
||||
#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
|
||||
catch(std::exception) {} #chytí všechny chyby
|
||||
catch(...) {}#chytí úplně všechno
|
||||
```
|
||||
|
||||
`Catch` funguje jako funkce. Má argumenty, které nejsou hodnoty, ale typy hodnot, které jdou "zavolat". Proto nemůžu chytat text, ale můžu chytat např. `const char* e` -> a `e` je to co se předá.
|
||||
|
||||
v případe `catch(const std::bad_alloc& e) {}` se používá [[Reference]] protože objekt může být teoreticky velký a my ho nechceme kopírovat.
|
||||
## What()
|
||||
`.what()` je funkce chybových objektů. Ta vypisuje jejich textovou hodnotu.
|
||||
Například pro `throw std::invalid_argument( "received negative value" );`
|
||||
vypíše `"received negative value"`.
|
||||
|
||||
Volal bych třeba
|
||||
```cpp
|
||||
catch(const std::bad_alloc& e)
|
||||
{
|
||||
std::cout << e.what()
|
||||
}
|
||||
```
|
||||
|
||||
## set_terminate a terminate()
|
||||
Když nastane situace, kdy se dojde k nějakému fatálnímu programu, na který program není připraven, zavolá se `std::terminate()`. Ten zavolá `abort()` a ukončí program.
|
||||
To může nastat, když výjimka není zachycena, ale případů je víc:
|
||||
- během stack unwindingu (tedy při opouštění funkcí po `throw`) dojde k další výjimce
|
||||
- vyhodí se výjimku z destruktoru během unwindingu
|
||||
- porušení pravidla `noexcept` (funkce označená jako `noexcept` vyhodí výjimku)
|
||||
|
||||
`terminate` je poslední funkce, která se zavolá před ukončením programu a nevrací dále dál tok programu.
|
||||
My pokud chceme můžeme nastavit vlastní funkci `terminate`, pro větší kontrolu nad programem pomocí `std::set_terminate(my_func);`
|
||||
|
||||
**Pozn**: destruktory nesmí házet výjimky proto, protože při výjimce nastane situace, kdy se ukončuje funkce a destruktory se volají. Pokud by destruktor vyhodil výjimku, mohla by nastat situace, kdy jsou 2 výjimky najednou, což je problém.
|
||||
# Typy chyb
|
||||
|
||||
- runtime chyby -> range, overflow, etc.
|
||||
- logické chyby -> domain, out_of_range...
|
||||
- bad_cast
|
||||
- bad_function_call
|
||||
- bad_alloc -> většinou nedostatek paměti od new...
|
||||
Reference in New Issue
Block a user