Спецификаторы доступа
В C++ используются три спецификатора доступа: public, private и protected. Они определяют, кто может получить доступ к членам класса или структуры.
public — члены с таким спецификатором доступны из любого места программы, включая другие классы и структуры.
private — члены с таким спецификатором доступны только из самого класса, в котором они объявлены.
protected — члены с таким спецификатором доступны из самого класса, в котором они объявлены, а также из производных классов.
По умолчанию все члены класса объявляются с спецификатором private, а члены структуры — с public.
Спецификаторы доступа используются для обеспечения инкапсуляции, то есть отделения внутренней реализации класса от его интерфейса. Инкапсуляция позволяет скрыть детали реализации от пользователя класса, что делает код более понятным и надежным.
В C++ используются три спецификатора доступа: public, private и protected. Они определяют, кто может получить доступ к членам класса или структуры.
public — члены с таким спецификатором доступны из любого места программы, включая другие классы и структуры.
private — члены с таким спецификатором доступны только из самого класса, в котором они объявлены.
protected — члены с таким спецификатором доступны из самого класса, в котором они объявлены, а также из производных классов.
По умолчанию все члены класса объявляются с спецификатором private, а члены структуры — с public.
Спецификаторы доступа используются для обеспечения инкапсуляции, то есть отделения внутренней реализации класса от его интерфейса. Инкапсуляция позволяет скрыть детали реализации от пользователя класса, что делает код более понятным и надежным.
Функция floor
Функция floor в C++ используется для округления числа с плавающей запятой (типа float или double) вниз до ближайшего целого числа, которое меньше или равно исходному числу. Функция floor является частью стандартной библиотеки C++ и объявлена в заголовочном файле cmath.
Функция floor полезна, например, при работе с денежными суммами, когда вам нужно округлить результат вниз до ближайшего целого значения валюты, чтобы учесть минимальные единицы валюты.
Функция floor в C++ используется для округления числа с плавающей запятой (типа float или double) вниз до ближайшего целого числа, которое меньше или равно исходному числу. Функция floor является частью стандартной библиотеки C++ и объявлена в заголовочном файле cmath.
Функция floor полезна, например, при работе с денежными суммами, когда вам нужно округлить результат вниз до ближайшего целого значения валюты, чтобы учесть минимальные единицы валюты.
🧑💻 Статьи для IT: как объяснять и распространять значимые идеи
Напоминаем, что у нас есть бесплатный курс для всех, кто хочет научиться интересно писать — о программировании и в целом.
Что: семь модулей, посвященных написанию, редактированию, иллюстрированию и распространению публикаций.
Для кого: для авторов, копирайтеров и просто программистов, которые хотят научиться интересно рассказывать о своих проектах.
👉Материалы регулярно дополняются, обновляются и корректируются. А еще мы отвечаем на все учебные вопросы в комментариях курса.
Напоминаем, что у нас есть бесплатный курс для всех, кто хочет научиться интересно писать — о программировании и в целом.
Что: семь модулей, посвященных написанию, редактированию, иллюстрированию и распространению публикаций.
Для кого: для авторов, копирайтеров и просто программистов, которые хотят научиться интересно рассказывать о своих проектах.
👉Материалы регулярно дополняются, обновляются и корректируются. А еще мы отвечаем на все учебные вопросы в комментариях курса.
Флаги оптимизации
🤔 Что это за флажки?
Флажки оптимизации — это специальные параметры, которые передают компилятору инструкции о том, насколько сильно он должен оптимизировать ваш код при компиляции. Уровень оптимизации может варьироваться от минимального (O0) до максимального (O3).
🔍 Чем отличаются уровни оптимизации?
• O0 (Отсутствие оптимизации): Этот уровень подходит для отладки. Компилятор минимизирует время компиляции, не внося оптимизаций, чтобы облегчить отслеживание багов
• O1 (Базовая оптимизация): Проводит базовые оптимизации, например, устранение мертвого кода и простые inline-функций
• O2 (Средняя оптимизация): Включает более сложные оптимизации, такие как оптимизация циклов и векторизация, что приводит к более эффективному исполнению кода
• O3 (Максимальная оптимизация): Производит максимально возможное количество оптимизаций. Подходит для создания высокопроизводительного кода, но может увеличить время компиляции
🤔 Что это за флажки?
Флажки оптимизации — это специальные параметры, которые передают компилятору инструкции о том, насколько сильно он должен оптимизировать ваш код при компиляции. Уровень оптимизации может варьироваться от минимального (O0) до максимального (O3).
🔍 Чем отличаются уровни оптимизации?
• O0 (Отсутствие оптимизации): Этот уровень подходит для отладки. Компилятор минимизирует время компиляции, не внося оптимизаций, чтобы облегчить отслеживание багов
• O1 (Базовая оптимизация): Проводит базовые оптимизации, например, устранение мертвого кода и простые inline-функций
• O2 (Средняя оптимизация): Включает более сложные оптимизации, такие как оптимизация циклов и векторизация, что приводит к более эффективному исполнению кода
• O3 (Максимальная оптимизация): Производит максимально возможное количество оптимизаций. Подходит для создания высокопроизводительного кода, но может увеличить время компиляции
Вывод типа шаблона (Template Type Deduction)
⚙️ Начиная с C++11 появилась возможность переложить вывод типа на компилятор — вывод типа шаблона (Template Type Deduction)
🔥 Эта фича не только улучшает читаемость, но и делает код более устойчивым к изменениям. Если мы решим изменить тип вектора, нам не нужно изменять сигнатуру функции
⚙️ Начиная с C++11 появилась возможность переложить вывод типа на компилятор — вывод типа шаблона (Template Type Deduction)
🔥 Эта фича не только улучшает читаемость, но и делает код более устойчивым к изменениям. Если мы решим изменить тип вектора, нам не нужно изменять сигнатуру функции
Какие конструкторы и методы реализуются по умолчанию?
Начиная с C++11 каждый класс, помимо конструктора по умолчанию, имеет следующие 5 дефолтных операций:
1. Конструктор копирования (Copy Constructor):
• Принимает объект своего же типа в качестве параметра
• Создает новый объект, инициализируя его значениями из переданного объекта
2. Оператор присваивания (Copy Assignment Operator):
• Присваивает значения одного объекта другому
• Вызывается при использовании оператора присваивания (=) между двумя объектами
3. Конструктор перемещения (Move Constructor):
• Это нововведение в C++11
• Принимает rvalue-ссылку на объект своего типа в качестве параметра
4. Оператор перемещения (Move Assignment Operator):
• Также нововведение в C++11
• Принимает rvalue-ссылку на объект своего типа в качестве параметра
5. Деструктор (Destructor):
• Освобождает ресурсы, занимаемые объектом, при его уничтожении (выходе из области видимости, удалении из контейнера)
Начиная с C++11 каждый класс, помимо конструктора по умолчанию, имеет следующие 5 дефолтных операций:
1. Конструктор копирования (Copy Constructor):
• Принимает объект своего же типа в качестве параметра
• Создает новый объект, инициализируя его значениями из переданного объекта
2. Оператор присваивания (Copy Assignment Operator):
• Присваивает значения одного объекта другому
• Вызывается при использовании оператора присваивания (=) между двумя объектами
3. Конструктор перемещения (Move Constructor):
• Это нововведение в C++11
• Принимает rvalue-ссылку на объект своего типа в качестве параметра
4. Оператор перемещения (Move Assignment Operator):
• Также нововведение в C++11
• Принимает rvalue-ссылку на объект своего типа в качестве параметра
5. Деструктор (Destructor):
• Освобождает ресурсы, занимаемые объектом, при его уничтожении (выходе из области видимости, удалении из контейнера)
📚 std::exception — это базовый класс для всех стандартных исключений в C++
Почему стоит наследоваться от std::exception?
• Единообразие в обработке исключений: Когда вы наследуетесь от std::exception, ваш класс исключения приобретает интерфейс, который делает его совместимым с другими стандартными исключениями
• what() метод: std::exception предоставляет важный метод what(), который возвращает строковое представление исключения. Это позволяет вам предоставлять информативные сообщения об ошибке при обработке исключений
• Легкость в поддержке кода: Если вы используете сторонние библиотеки или фреймворки, они также могут ожидать обработку исключений, производных от std::exception
• Стандартные типы исключений: std::exception имеет несколько стандартных подклассов, таких как std::runtime_error, std::logic_error и другие. Вы можете использовать эти подклассы вместо базового std::exception, чтобы более точно определить характер ошибки
Почему стоит наследоваться от std::exception?
• Единообразие в обработке исключений: Когда вы наследуетесь от std::exception, ваш класс исключения приобретает интерфейс, который делает его совместимым с другими стандартными исключениями
• what() метод: std::exception предоставляет важный метод what(), который возвращает строковое представление исключения. Это позволяет вам предоставлять информативные сообщения об ошибке при обработке исключений
• Легкость в поддержке кода: Если вы используете сторонние библиотеки или фреймворки, они также могут ожидать обработку исключений, производных от std::exception
• Стандартные типы исключений: std::exception имеет несколько стандартных подклассов, таких как std::runtime_error, std::logic_error и другие. Вы можете использовать эти подклассы вместо базового std::exception, чтобы более точно определить характер ошибки
🔍 Что такое std::thread?
std::thread предоставляет собой интерфейс для взаимодействия с системными потоками
💡Что можно запустить?
• Любой функтор можно превратить в поток
💡Что можно передать при запуске потока?
• Можно передать любое количество параметров, но стоит учитывать, что все они будут копироваться
• Чтобы передать ссылку, её стоит обернуть в std::ref или std::cref
💡Что можно сделать с потоком?
• После создания потока мы можем с ним делать две вещи: вызвать join и ждать завершение потока или вызвать detach, тогда поток просто будет работать (пока сам не завершится)
💡Начиная с C++20 появился std::jthread
• Это тоже самое, но в деструкторе будет вызываться join
std::thread предоставляет собой интерфейс для взаимодействия с системными потоками
💡Что можно запустить?
• Любой функтор можно превратить в поток
💡Что можно передать при запуске потока?
• Можно передать любое количество параметров, но стоит учитывать, что все они будут копироваться
• Чтобы передать ссылку, её стоит обернуть в std::ref или std::cref
💡Что можно сделать с потоком?
• После создания потока мы можем с ним делать две вещи: вызвать join и ждать завершение потока или вызвать detach, тогда поток просто будет работать (пока сам не завершится)
💡Начиная с C++20 появился std::jthread
• Это тоже самое, но в деструкторе будет вызываться join
Dependency Injection
Dependency Injection (DI) — это паттерн проектирования, который помогает управлять зависимостями в приложениях. Он особенно важен в объектно-ориентированных языках программирования, таких как C++, где классы и объекты играют центральную роль.
DI предполагает, что зависимости (например, объекты других классов, которые класс использует) должны передаваться в класс извне, а не создаваться им самостоятельно. Это делает класс более независимым и более тестируемым. В C++, DI можно реализовать следующими способами: внедрение через конструктор, внедрение через метод и использование фабрик. В картинке с примером мы используем внедрение через конструктор, так как это самый распространенный способ DI в C++. В конструкторе класса вы передаете зависимости как параметры.
Использование DI в C++ способствует лучшей организации кода, более простой поддержке и тестированию. Он позволяет избегать жестких зависимостей и делает ваш код более гибким и расширяемым.
Dependency Injection (DI) — это паттерн проектирования, который помогает управлять зависимостями в приложениях. Он особенно важен в объектно-ориентированных языках программирования, таких как C++, где классы и объекты играют центральную роль.
DI предполагает, что зависимости (например, объекты других классов, которые класс использует) должны передаваться в класс извне, а не создаваться им самостоятельно. Это делает класс более независимым и более тестируемым. В C++, DI можно реализовать следующими способами: внедрение через конструктор, внедрение через метод и использование фабрик. В картинке с примером мы используем внедрение через конструктор, так как это самый распространенный способ DI в C++. В конструкторе класса вы передаете зависимости как параметры.
Использование DI в C++ способствует лучшей организации кода, более простой поддержке и тестированию. Он позволяет избегать жестких зависимостей и делает ваш код более гибким и расширяемым.
Может ли виртуальный метод быть шаблонной функцией?
Ответ: нет не может
Пояснение
• Если шаблоны будут виртуальными, то вместо перечисления функций в базовом классе надо искать все подстановки шаблона при вызовах функции
• Для этого вместо индексов надо использовать имена, и искать эти имена в хеш-таблице
• Скорость вызова значительно упадет, т.к. надо будет разрешать коллизии
Ответ: нет не может
Пояснение
• Если шаблоны будут виртуальными, то вместо перечисления функций в базовом классе надо искать все подстановки шаблона при вызовах функции
• Для этого вместо индексов надо использовать имена, и искать эти имена в хеш-таблице
• Скорость вызова значительно упадет, т.к. надо будет разрешать коллизии
co_await, co_yield и co_return
co_await, co_yield и co_return — это ключевые слова, которые используются для реализации корутин (coroutines).
co_await используется для приостановки корутины и ожидания результата асинхронной операции.
co_yield используется для приостановки корутины и передачи управления обратно вызывающему коду.
co_return используется для завершения корутины и возврата результата.
В этом примере используются все три ключевых слова:
— co_await приостанавливает корутину create_task в начале.
— co_yield можно было бы использовать для дополнительных приостановок.
— co_return завершает корутину в конце.
co_await, co_yield и co_return — это ключевые слова, которые используются для реализации корутин (coroutines).
co_await используется для приостановки корутины и ожидания результата асинхронной операции.
co_yield используется для приостановки корутины и передачи управления обратно вызывающему коду.
co_return используется для завершения корутины и возврата результата.
В этом примере используются все три ключевых слова:
— co_await приостанавливает корутину create_task в начале.
— co_yield можно было бы использовать для дополнительных приостановок.
— co_return завершает корутину в конце.
🤔 Что такое structural bindings?
• Данная фитча появилась в C++17
• Это механизм, который позволяет нам декомпозировать структуры данных, такие как tuple, pair, и даже свои пользовательские структуры, на более простые именованные переменные
• Это делает код более читаемым, компактным и легко поддерживаемым
🌐 Ссылки
• Восемь возможностей C++17, которые должен применять каждый разработчик
• Structured binding declaration
• Structured binding in C++ https://habr.com/ru/articles/343622/
• Данная фитча появилась в C++17
• Это механизм, который позволяет нам декомпозировать структуры данных, такие как tuple, pair, и даже свои пользовательские структуры, на более простые именованные переменные
• Это делает код более читаемым, компактным и легко поддерживаемым
🌐 Ссылки
• Восемь возможностей C++17, которые должен применять каждый разработчик
• Structured binding declaration
• Structured binding in C++ https://habr.com/ru/articles/343622/
Что такое TDD?
TDD (Test-Driven Development) — это методология разработки программного обеспечения, которая основана на повторении очень коротких циклов разработки: сначала пишется тест, покрывающий желаемое изменение, затем пишется код, который позволит пройти тест, и под конец проводится рефакторинг нового кода к соответствующим стандартам.
TDD означает, что программист сначала пишет модульный тест, который проверяет ожидаемое поведение некоторой части кода. Затем программист пишет код, который заставляет тест пройти. После этого программист может провести рефакторинг кода, чтобы улучшить его читаемость, производительность или другие свойства.
TDD (Test-Driven Development) — это методология разработки программного обеспечения, которая основана на повторении очень коротких циклов разработки: сначала пишется тест, покрывающий желаемое изменение, затем пишется код, который позволит пройти тест, и под конец проводится рефакторинг нового кода к соответствующим стандартам.
TDD означает, что программист сначала пишет модульный тест, который проверяет ожидаемое поведение некоторой части кода. Затем программист пишет код, который заставляет тест пройти. После этого программист может провести рефакторинг кода, чтобы улучшить его читаемость, производительность или другие свойства.
🌟 Что такое std::optional?
Это класс, появился начиная с C++17, который даёт удобный способ работы с «возможно отсутствующим» значением
🌐 Ссылки
• std::optional
• std::optional in C++
• Рефакторинг с использованием C++17 std::optional
• Использование std::optional в С++17
Это класс, появился начиная с C++17, который даёт удобный способ работы с «возможно отсутствующим» значением
🌐 Ссылки
• std::optional
• std::optional in C++
• Рефакторинг с использованием C++17 std::optional
• Использование std::optional в С++17
🌟 Что такое std::variant?
std::variant — это класс-шаблон в стандартной библиотеке C++, который предоставляет механизм для хранения и обработки значения из списка альтернативных типов. Это позволяет программистам создавать переменные, которые могут содержать значения разных типов, известных заранее
📘 Особенности
Безопасность типов: std::variant гарантирует безопасность типов на этапе компиляции. Это означает, что вся обработка значений будет проверена на соответствие типов на этапе компиляции, что помогает избежать ошибок времени выполнения, связанных с неправильным использованием типов данных
std::variant — это класс-шаблон в стандартной библиотеке C++, который предоставляет механизм для хранения и обработки значения из списка альтернативных типов. Это позволяет программистам создавать переменные, которые могут содержать значения разных типов, известных заранее
📘 Особенности
Безопасность типов: std::variant гарантирует безопасность типов на этапе компиляции. Это означает, что вся обработка значений будет проверена на соответствие типов на этапе компиляции, что помогает избежать ошибок времени выполнения, связанных с неправильным использованием типов данных
👉 Что это такое strerror?
strerror является стандартной функцией в языке программирования C++ и предоставляет простой и эффективный способ получения описания ошибки на основе ее кода. Саму же ошибку можно чаще всего взять из errno (глобальная переменная, объявление её лежит в заголовочном файле errno.h)
🔧 Зачем это нужно?
Это очень полезно при обработке ошибок в программе. strerror помогает преобразовать код ошибки, возвращаемый функциями стандартной библиотеки или операционной системы, в человекочитаемое описание, что упрощает понимание и отладку проблем
strerror является стандартной функцией в языке программирования C++ и предоставляет простой и эффективный способ получения описания ошибки на основе ее кода. Саму же ошибку можно чаще всего взять из errno (глобальная переменная, объявление её лежит в заголовочном файле errno.h)
🔧 Зачем это нужно?
Это очень полезно при обработке ошибок в программе. strerror помогает преобразовать код ошибки, возвращаемый функциями стандартной библиотеки или операционной системы, в человекочитаемое описание, что упрощает понимание и отладку проблем
🌟 Что такое std::jthread?
std::jthread — это новый класс потока исполнения (thread) в стандартной библиотеке C++ (начиная с C++20). Он представляет собой управляемый поток, который автоматически завершает свою работу при выходе из области видимости, если он был запущен
📘 В отличие от std::thread, std::jthread предоставляет несколько преимуществ
• Управление временем жизни: std::jthread автоматически завершает свою работу, когда объект std::jthread выходит из области видимости. Это позволяет избежать необходимости явного вызова join() или detach() для завершения потока, что упрощает управление ресурсами
• Безопасное исключение при завершении: Если поток, созданный с помощью std::jthread, был запущен и бросает исключение, прежде чем завершиться, то исключение будет перехвачено и обработано, прежде чем поток завершится. Это делает код более безопасным и предотвращает утечку ресурсов
std::jthread — это новый класс потока исполнения (thread) в стандартной библиотеке C++ (начиная с C++20). Он представляет собой управляемый поток, который автоматически завершает свою работу при выходе из области видимости, если он был запущен
📘 В отличие от std::thread, std::jthread предоставляет несколько преимуществ
• Управление временем жизни: std::jthread автоматически завершает свою работу, когда объект std::jthread выходит из области видимости. Это позволяет избежать необходимости явного вызова join() или detach() для завершения потока, что упрощает управление ресурсами
• Безопасное исключение при завершении: Если поток, созданный с помощью std::jthread, был запущен и бросает исключение, прежде чем завершиться, то исключение будет перехвачено и обработано, прежде чем поток завершится. Это делает код более безопасным и предотвращает утечку ресурсов
🛠️ Что такое C++ Streams?
В контексте C++, потоки (streams) представляют собой механизм для работы с вводом и выводом данных. Они обеспечивают абстракцию над различными источниками и приемниками данных, такими как консоль, файлы и строки, позволяя программистам работать с ними с помощью общего интерфейса
Основные реализации потоков в C++
• std::cin и std::cout: Это стандартные потоки ввода и вывода, которые обычно используются для взаимодействия с консолью
• std::ifstream и std::ofstream: Это классы потоков для работы с файлами
• std::stringstream: Этот класс потока позволяет работать с данными как с потоком, хранящимся в строке. Он может использоваться для выполнения операций ввода-вывода с помощью строкового представления данных
Преимущества использования потоков
• Удобство в использовании
• Возможность абстрагировать ввод-вывод от конкретных источников и приемников данных
• Поддержку различных типов данных
В контексте C++, потоки (streams) представляют собой механизм для работы с вводом и выводом данных. Они обеспечивают абстракцию над различными источниками и приемниками данных, такими как консоль, файлы и строки, позволяя программистам работать с ними с помощью общего интерфейса
Основные реализации потоков в C++
• std::cin и std::cout: Это стандартные потоки ввода и вывода, которые обычно используются для взаимодействия с консолью
• std::ifstream и std::ofstream: Это классы потоков для работы с файлами
• std::stringstream: Этот класс потока позволяет работать с данными как с потоком, хранящимся в строке. Он может использоваться для выполнения операций ввода-вывода с помощью строкового представления данных
Преимущества использования потоков
• Удобство в использовании
• Возможность абстрагировать ввод-вывод от конкретных источников и приемников данных
• Поддержку различных типов данных