From f860f9d1e6f1c32620308fa6376ed59e171c0d0d Mon Sep 17 00:00:00 2001 From: czertyaka Date: Wed, 12 Nov 2025 23:36:05 +0500 Subject: [PATCH 1/3] Move 12 presentation to 13 --- Makefile | 18 ++++++++++++++++-- .../basic-example/employee.hpp | 0 .../basic-example/main.cpp | 0 .../virtual-members.tex | 4 ++-- 4 files changed, 18 insertions(+), 4 deletions(-) rename Presentations/{12-Virtual-members => 13-Virtual-members}/basic-example/employee.hpp (100%) rename Presentations/{12-Virtual-members => 13-Virtual-members}/basic-example/main.cpp (100%) rename Presentations/{12-Virtual-members => 13-Virtual-members}/virtual-members.tex (98%) diff --git a/Makefile b/Makefile index 73ddc67..d7fbb78 100644 --- a/Makefile +++ b/Makefile @@ -25,6 +25,7 @@ BUILD_DIR := build pr-10 \ pr-11 \ pr-12 \ + pr-13 \ prj-auth-lib \ prj-enc-exch @@ -49,6 +50,7 @@ build: \ pr-10 \ pr-11 \ pr-12 \ + pr-13 \ prj-auth-lib \ prj-enc-exch @@ -65,7 +67,8 @@ install: build cp "$(BUILD_DIR)/pr-09.pdf" "$(PREFIX)/Презентации/09 Функции.pdf" cp "$(BUILD_DIR)/pr-10.pdf" "$(PREFIX)/Презентации/10 Приведения типов.pdf" cp "$(BUILD_DIR)/pr-11.pdf" "$(PREFIX)/Презентации/11 Структуры и классы.pdf" - cp "$(BUILD_DIR)/pr-12.pdf" "$(PREFIX)/Презентации/12 Виртуальные методы и полиморфизм.pdf" + cp "$(BUILD_DIR)/pr-12.pdf" "$(PREFIX)/Презентации/12 Исключения.pdf" + cp "$(BUILD_DIR)/pr-13.pdf" "$(PREFIX)/Презентации/13 Виртуальные методы и полиморфизм.pdf" mkdir -p "$(PREFIX)/Домашние задания" cp "$(BUILD_DIR)/hw-01.pdf" "$(PREFIX)/Домашние задания/01 Hello World.pdf" cp "$(BUILD_DIR)/hw-02.pdf" "$(PREFIX)/Домашние задания/02 Git & Github.pdf" @@ -104,6 +107,7 @@ help: @printf "pr-10\tbuild presentation pr-10.pdf\n" @printf "pr-11\tbuild presentation pr-11.pdf\n" @printf "pr-12\tbuild presentation pr-12.pdf\n" + @printf "pr-13\tbuild presentation pr-13.pdf\n" @printf "prj-auth-lib\tbuild project prj-auth-lib.pdf\n" @printf "prj-enc-exch\tbuild project prj-enc-exch.pdf\n" @@ -119,6 +123,7 @@ pr-09: pr-09.pdf pr-10: pr-10.pdf pr-11: pr-11.pdf pr-12: pr-12.pdf +pr-13: pr-13.pdf hw-01: hw-01.pdf hw-02: hw-02.pdf @@ -155,6 +160,8 @@ pr-02.pdf: \ Presentations/02-Phases-of-translation/phases_of_translation.tex \ Presentations/presentationtemplate.sty \ $(wildcard Presentations/images/*-logo.png) \ + $(wildcard Presentations/02-Phases-of-translation/library/*.cpp) \ + $(wildcard Presentations/02-Phases-of-translation/relocations/*.cpp) \ $(wildcard Presentations/02-Phases-of-translation/*.cpp) \ $(wildcard Presentations/02-Phases-of-translation/*.h) \ Packages/terminal.sty \ @@ -262,7 +269,14 @@ pr-11.pdf: \ $(call generate_pdf,$<,$@) pr-12.pdf: \ - Presentations/12-Virtual-members/virtual-members.tex \ + Presentations/12-Exceptions/exceptions.tex \ + Presentations/presentationtemplate.sty \ + $(wildcard Presentations/images/*-logo.png) \ + Packages/mylisting.sty + $(call generate_pdf,$<,$@) + +pr-13.pdf: \ + Presentations/13-Virtual-members/virtual-members.tex \ Presentations/presentationtemplate.sty \ $(wildcard Presentations/images/*-logo.png) \ Packages/mylisting.sty diff --git a/Presentations/12-Virtual-members/basic-example/employee.hpp b/Presentations/13-Virtual-members/basic-example/employee.hpp similarity index 100% rename from Presentations/12-Virtual-members/basic-example/employee.hpp rename to Presentations/13-Virtual-members/basic-example/employee.hpp diff --git a/Presentations/12-Virtual-members/basic-example/main.cpp b/Presentations/13-Virtual-members/basic-example/main.cpp similarity index 100% rename from Presentations/12-Virtual-members/basic-example/main.cpp rename to Presentations/13-Virtual-members/basic-example/main.cpp diff --git a/Presentations/12-Virtual-members/virtual-members.tex b/Presentations/13-Virtual-members/virtual-members.tex similarity index 98% rename from Presentations/12-Virtual-members/virtual-members.tex rename to Presentations/13-Virtual-members/virtual-members.tex index 5537a88..2ecffb1 100644 --- a/Presentations/12-Virtual-members/virtual-members.tex +++ b/Presentations/13-Virtual-members/virtual-members.tex @@ -28,7 +28,7 @@ \begin{column}{0.5\textwidth} \myinputlisting[minted language=cpp] - {Presentations/12-Virtual-members/basic-example/} + {Presentations/13-Virtual-members/basic-example/} {employee.hpp} \end{column} @@ -36,7 +36,7 @@ \begin{column}{0.5\textwidth} \myinputlisting[minted language=cpp] - {Presentations/12-Virtual-members/basic-example/} + {Presentations/13-Virtual-members/basic-example/} {main.cpp} \end{column} From b290dc43c47ed0fbd17c8e5ddc77c07e4b161b38 Mon Sep 17 00:00:00 2001 From: czertyaka Date: Thu, 13 Nov 2025 00:55:55 +0500 Subject: [PATCH 2/3] Start presentation --- .../structs-and-classes.tex | 2 +- Presentations/12-Exceptions/exceptions.tex | 421 ++++++++++++++++++ 2 files changed, 422 insertions(+), 1 deletion(-) create mode 100644 Presentations/12-Exceptions/exceptions.tex diff --git a/Presentations/11-Structs-and-classes/structs-and-classes.tex b/Presentations/11-Structs-and-classes/structs-and-classes.tex index 511671f..f267cfe 100644 --- a/Presentations/11-Structs-and-classes/structs-and-classes.tex +++ b/Presentations/11-Structs-and-classes/structs-and-classes.tex @@ -1,4 +1,4 @@ -% !TeX TS-program = xelatex +% !TeX TS-program = lualatex \documentclass[compress, 8pt]{beamer} diff --git a/Presentations/12-Exceptions/exceptions.tex b/Presentations/12-Exceptions/exceptions.tex new file mode 100644 index 0000000..a3efdad --- /dev/null +++ b/Presentations/12-Exceptions/exceptions.tex @@ -0,0 +1,421 @@ +\documentclass[compress, 8pt]{beamer} + +\usepackage{presentationtemplate} +\usepackage[askip=3mm, bskip=3mm]{terminal} +\usepackage[linenosfontsize=\tiny, askip=3mm, bskip=3mm]{mylisting} +\usepackage{csquotes} + +\newtcolorbox{task}{ + colback=yellow!50!white, + boxrule=0.02cm, + colframe=black, + sharp corners, + left=0mm, + right=0mm, + top=0mm, + bottom=0mm, + before upper={\textbf{Задание}:\:}, +} + +\title{Исключения} + +\begin{document} + + \frame[plain]{\titlepage} + + \begin{frame}[fragile] + + \frametitle{Синтаксис} + + Ключевые слова: + + \begin{itemize} + \item \texttt{throw} + \item \texttt{try} + \item \texttt{catch} + \end{itemize} + + \end{frame} + + \begin{frame}[fragile] + + \frametitle{Синтаксис} + + Типовой упрощенный пример использования исключений: + + \begin{myinplacelisting}[minted language=cpp] +int foo(unsigned i) { + const int arr[] = {1, 2, 3}; + if (i > 2) { + throw std::out_of_range("Too large index"); + } + return arr[i]; +} + +unsigned get_index(); + +int main() { + const auto index = get_index(); + try { + std::println("arr[{}] = {}", index, foo(index)); + } + catch (const std::exception& err) { + std::println(stderr, "Error: {}", err.what()); + } +} + \end{myinplacelisting} + + \end{frame} + + \begin{frame}[fragile] + + \frametitle{Обработка ошибок} + + В C++ существует два подхода к обработке ошибок: + + \hfill \break + + \begin{itemize} + \item Передача информации об ошибке в возвращаемом значении. + \item Механизм исключений. + \end{itemize} + + \hfill \break + + Каждый из них имеет свои преимущества и недостатки. + Исключения считаются более \enquote{идиоматическим} способом. + Рассмотрим сначала альтернативный способ. + + \end{frame} + + \begin{frame}[fragile] + + \frametitle{Ошибка в возвращаемом значении} + + \textbf{Вариант 1} \textemdash \space в возвращаемом значении код ошибки, + а результаты выполнения передается по ссылке. + + \begin{myinplacelisting}[minted language=cpp] +enum class Result { + OK, + OUT_OF_RANGE +}; + +Result foo(unsigned i, int& result) { + constexpr int arr[] = {1, 2, 3}; + if (i > 2) { + return Result::OUT_OF_RANGE; + } + result = arr[i]; + return Result::OK; +} + \end{myinplacelisting} + + \end{frame} + + \begin{frame}[fragile] + + \frametitle{Ошибка в возвращаемом значении} + + \textbf{Вариант 1} \textemdash \space в возвращаемом значении код ошибки, + а результаты выполнения передается по ссылке. + + \begin{myinplacelisting}[minted language=cpp] +unsigned get_index(); + +int main() { + int result {}; + switch (foo(get_index(), result)) { + case Result::OK: + std::println("Result: {}", result); + break; + case Result::OUT_OF_RANGE: + std::println(stderr, "Error: out of bounds"); + default: + std::println(stderr, "Error: unknown"); + break; + } +} + \end{myinplacelisting} + + \end{frame} + + \begin{frame}[fragile] + + \frametitle{Ошибка в возвращаемом значении} + + \begin{task} + Подумайте, какие преимущества и недостатки у \textbf{варианта 1}. + \end{task} + + \end{frame} + + \begin{frame}[fragile] + + \frametitle{Ошибка в возвращаемом значении} + + \textbf{Вариант 2} \textemdash \space информация об ошибке и результат + операции объединены в один тип. + + \begin{myinplacelisting}[minted language=cpp] +struct Result { + enum class Error { + NONE, + OUT_OF_RANGE + }; + Error error = Error::NONE; + int value; +}; + +Result foo(unsigned i) { + constexpr int arr[] = {1, 2, 3}; + if (i > 2) { + return {Result::Error::OUT_OF_RANGE}; + } + Result result {}; + result.value = arr[i]; + return result; +} + \end{myinplacelisting} + + \end{frame} + + \begin{frame}[fragile] + + \frametitle{Ошибка в возвращаемом значении} + + \textbf{Вариант 2} \textemdash \space информация об ошибке и результат + операции объединены в один тип. + + \begin{myinplacelisting}[minted language=cpp] +unsigned get_index(); + +int main() { + const auto result = foo(get_index()); + switch (result.error) { + case Result::Error::NONE: + std::println("Result: {}", result.value); + break; + case Result::Error::OUT_OF_RANGE: + std::println(stderr, + "Error: out of bounds"); + default: + break; + } +} + \end{myinplacelisting} + + \end{frame} + + \begin{frame}[fragile] + + \frametitle{Ошибка в возвращаемом значении} + + \begin{task} + Подумайте, какие преимущества и недостатки у \textbf{варианта 2}. + \end{task} + + \end{frame} + + \begin{frame}[fragile] + + \frametitle{Unrepresentable state} + + Передача ошибки через возвращаемое значение \textemdash \space + не универсальное решение. + Возвращаемых значений нет у \textit{конструкторов классов}. + + \begin{myinplacelisting}[minted language=cpp] +class Month { +public: + Month(const unsigned number) { + if (number >= 12) { + // how do we handle this? + } + } + // ... +}; + \end{myinplacelisting} + + \end{frame} + + \begin{frame}[fragile] + + \frametitle{Unrepresentable state} + + Одним из способов решения проблемы \textemdash \space + создание методов, указывающих на консистентность + состояния объекта. + + \begin{myinplacelisting}[minted language=cpp] +class Month { + std::uint8_t number_; +public: + Month(std::uint8_t number) : + number_(number) {} + bool Valid() const { + return number_ < 12; + } +}; + +void foo(const Month& month) { + if (month.Valid()) { + // do stuff ... + } +} + \end{myinplacelisting} + + \end{frame} + + \begin{frame}[fragile] + + \frametitle{Unrepresentable state} + + Как правило, лучше вообще не давать создавать объект с + неконсистентным состояним, делая его таким образом + \enquote{непредставимым} (\textit{unrepresentable state}). + + \begin{myinplacelisting}[minted language=cpp] +class Month { + std::uint8_t number_; +public: + Month(std::uint8_t number) : number_(number) { + if (number_ > 11) { + throw std::out_of_range( + "There's only 12 months" + ); + } + } +}; + \end{myinplacelisting} + + \end{frame} + + \begin{frame}[fragile] + + \frametitle{Выброс исключения} + + Исключения выбрасываются ключевым словом \texttt{throw}. + Исключение может быть объектом любого типа. + + \begin{myinplacelisting}[minted language=cpp] +throw 1; +throw "hello!"; +throw (1.0f * 2); +throw new int; +throw Foo{}; +throw std::runtime_error("hello!"); + \end{myinplacelisting} + + \end{frame} + + \begin{frame}[fragile] + + \frametitle{Отлов исключений} + + Для отлова исключений используется блок \texttt{try} \slash \texttt{catch}. + Семантика отлова исключений позволяет фильтровать их по \textit{типу}. + + \begin{myinplacelisting}[minted language=cpp] +void foo(int i) { + switch (i) { + case 1: throw int{}; + case 2: throw double{}; + default: throw nullptr; + } +} + +void bar(int i) { + try { + foo(i); + } + catch (const double err) { + // `throw double` will be handled here + } + // all other `throw`s are not handled at all +} + \end{myinplacelisting} + + \end{frame} + + \begin{frame}[fragile] + + \frametitle{Отлов исключений} + + В одном \texttt{try} \slash \texttt{catch} блоке можно отловить более + одного типа исключений. + Последовательность блоков \texttt{catch} важна: + при возникновении неоднозначности в выборе блока будет выбран первый. + + \begin{myinplacelisting}[minted language=cpp] +void bar(int i) { + try { + foo(i); + } + catch (const double err) { + std::println("Error: {}", err); + } + catch (const int err) { + std::println("Error: {}", err); + } +} + \end{myinplacelisting} + + \end{frame} + + \begin{frame}[fragile] + + \frametitle{Отлов исключений} + + Для отлова исключения любого типа используется конструкция + \texttt{catch(...)}. + + \begin{myinplacelisting}[minted language=cpp] +void bar(int i) { + try { + foo(i); + } + catch (const double err) { + std::println("Error: {}", err); + } + catch (...) { + // will handle all unhandled exceptions + // but we lack error object here + std::println("Error: unknown"); + } +} + \end{myinplacelisting} + + \end{frame} + + \begin{frame}[fragile] + + \frametitle{Stack unwinding} + + \end{frame} + + \begin{frame}[fragile] + + \frametitle{\texttt{noexcept} функции} + + \end{frame} + + \begin{frame}[fragile] + + \frametitle{Исключения и деструкторы} + + \end{frame} + + \begin{frame}[fragile] + + \frametitle{Исключения из стандартной библиотеки} + + \end{frame} + + \begin{frame}[fragile] + + \frametitle{Собственные типы исключений} + + \end{frame} + +\end{document} From 2c5e21e8b418eb95718e819a93ab92ee4aa7588a Mon Sep 17 00:00:00 2001 From: "o.pyhov" Date: Thu, 13 Nov 2025 10:34:06 +0500 Subject: [PATCH 3/3] Finished --- Presentations/12-Exceptions/exceptions.tex | 82 ++++++++++++++++++++-- 1 file changed, 77 insertions(+), 5 deletions(-) diff --git a/Presentations/12-Exceptions/exceptions.tex b/Presentations/12-Exceptions/exceptions.tex index a3efdad..61bf50f 100644 --- a/Presentations/12-Exceptions/exceptions.tex +++ b/Presentations/12-Exceptions/exceptions.tex @@ -392,11 +392,48 @@ \frametitle{Stack unwinding} + После выбрасывания исключению поток управления переходит + в ближайший блок \texttt{catch} вниз по стекам фрейма. + Вызываются деструкторы уже созданных объектов. + Этот процесс называется \textit{размоткой стека} (stack + unwinding). + + \begin{myinplacelisting}[minted language=cpp] +struct Foo { + std::string_view name_; + Foo(std::string_view name) : name_(name) { + std::println("New: {}", name_); + } + ~Foo() { std::println("Delete: {}", name_); } +}; + +void foo() { Foo f4 {"f4"}; throw 1; Foo f5 {"f5"}; }; + +void bar() { Foo f2 {"f2"}; foo(); Foo f3 {"f3"}; }; + +int main() { + try { Foo f0 {"f0"}; bar(); Foo f1 {"f1"}; } + catch (...) {} +} + \end{myinplacelisting} + \end{frame} \begin{frame}[fragile] - \frametitle{\texttt{noexcept} функции} + \frametitle{Stack unwinding} + + Пример вывод приложения с прошлого слайда: + + \begin{terminalwindow} +!\shellcommand{./a.out}! +New: f0 +New: f2 +New: f4 +Delete: f4 +Delete: f2 +Delete: f0 + \end{terminalwindow} \end{frame} @@ -404,17 +441,52 @@ \frametitle{Исключения и деструкторы} - \end{frame} + В процессе размотки стека вызываются деструкторы. + Из-за этого нельзя выбрасывать новые исключения в самих + деструкторах \textemdash \space C++ runtime не сможет + выбросить новое исключение во время обработки уже имеющегося. + В этом случае будет вызвана функция \texttt{std::terminate}\footnotemark{}. - \begin{frame}[fragile] + \footnotetext{\url{https://en.cppreference.com/w/cpp/error/terminate.html}} + + \begin{myinplacelisting}[minted language=cpp] +struct Foo { ~Foo() { throw 1; } }; + +int main() { + try { Foo f {}; throw 1; } + catch (...) {} +} + \end{myinplacelisting} - \frametitle{Исключения из стандартной библиотеки} + \begin{terminalwindow} +!\shellcommand{./a.out}! +terminate called after throwing an instance of 'int' +Aborted (core dumped) + \end{terminalwindow} \end{frame} \begin{frame}[fragile] - \frametitle{Собственные типы исключений} + \frametitle{Спецификатор \texttt{noexcept}} + + Функции, помеченные спецификатором \texttt{noexcept}, + приведут к вызову \texttt{std::terminate}, если их них + будет выброшено исключение. + + \begin{myinplacelisting}[minted language=cpp] +void bar() { throw 1; } + +void foo() noexcept { bar(); } + +int main() { foo(); } + \end{myinplacelisting} + + \begin{terminalwindow} +!\shellcommand{./a.out}! +terminate called after throwing an instance of 'int' +Aborted (core dumped) + \end{terminalwindow} \end{frame}