Новости

22.04.2021

Книга «C++ для профи»

«C++ для профи» адресован программистам среднего и продвинутого уровней, вы продеретесь сквозь тернии к самому ядру С++. Часть 1 охватывает основы языка С++ — от типов и функций до жизненного цикла объектов и выражений. В части II представлена стандартная библиотека C ++ и библиотеки Boost. Вы узнаете о специальных вспомогательных классах, структурах данных и алгоритмах, а также о том, как управлять файловыми системами и создавать высокопроизводительные программы, которые обмениваются данными по сети.

Об этой книге


Современные программисты на C++ имеют доступ к ряду очень качественных книг, например «Эффективный современный C++» Скотта Мейерса1 и «Язык программирования C++» Бьёрна Страуструпа, 4-е издание2. Однако эти книги написаны для достаточно продвинутых программистов. Доступны также некоторые вводные тексты о C++, но они часто пропускают важные детали, потому что ориентированы на абсолютных новичков в программировании. Опытному программисту непонятно, где можно погрузиться в язык C++.

Я предпочитаю изучать сложные темы осознанно, выстраивая концепции из их основных элементов. Язык C++ имеет пугающую репутацию, потому что его фундаментальные элементы тесно связаны друг с другом, что затрудняет построение полной картины языка. Когда я изучал C++, то изо всех сил пытался сосредоточиться на языке, перескакивая от книг к видео и измученным коллегам. Поэтому и написал такую книгу, которую сам хотел бы иметь пять лет назад.

Кому будет интересна эта книга?


Эта книга предназначена для программистов среднего и продвинутого уровня, уже знакомых с основными концепциями программирования. Если у вас нет опыта в программировании систем, ничего страшного. Опытным программистам приложений издание также будет полезно.

Вы познакомитесь с основными фишками современного С++:

 

  • Базовые типы, ссылочные и пользовательские типы.
  • Полиморфизм во время компиляции и полиморфизм во время выполнения.
  • Жизненный цикл объекта, включая длительность хранения, стек вызовов, управление памятью, исключения и парадигму RAII.
  • Продвинутые выражения, операторы и функции.
  • Умные указатели, структуры данных, дата и время, числовые данные и др.
  • Контейнеры, итераторы, строки и алгоритмы.
  • Потоки и файлы, многозадачность, сетевое программирование и разработка приложений.

 

Отслеживание жизненного цикла объекта


Жизненный цикл объекта является настолько же пугающим для новичков, насколько и мощным. Давайте рассмотрим пример, который исследует каждую из длительностей хранения.

Рассмотрим класс Tracer в листинге 4.5, который печатает сообщение всякий раз, когда объект Tracer создается или разрушается. Этот класс можно использовать для исследования жизненных циклов объекта, потому что каждый Tracer четко указывает, когда его жизнь начинается и заканчивается.

Листинг 4.5. Класс Tracer и его конструктор с деструктором

Конструктор принимает один параметр 1 и сохраняет его в члене name 2. Затем он печатает сообщение, содержащее name 3. Деструктор 4 также выводит сообщение с name.

Рассмотрим программу в листинге 4.6. Четыре различных объекта Tracer имеют разную длительность хранения. Просматривая порядок вывода программы Tracer, вы можете проверить полученные знания о длительности хранения.

Листинг 4.6. Программа, использующая класс Tracer в листинге 4.5 для иллюстрации длительности хранения

Листинг 4.6 содержит Tracer со статической 1, локальной поточной 2, автоматической 4 и динамической 5 длительностью хранения. Между каждой строкой в main выводится символ A, B или C для ссылки 3.

Запуск программы приводит к результату в листинге 4.7.

Листинг 4.7. Пример вывода из листинга 4.6

Перед первой строкой main 3 статические и потоковые локальные переменные t1 и t2 были инициализированы 1 2. Это можно увидеть в листинге 4.7: обе переменные напечатали свои сообщения инициализации до A. Как и для любой автоматической переменной, область видимости t3 ограничена включающей функцией main. Соответственно t3 создается в месте инициализации сразу после A.

После B вы можете видеть сообщение, соответствующее инициализации t4 5. Обратите внимание, что соответствующее сообщение, генерируемое динамическим деструктором Tracer, отсутствует. Причина в том, что вы (намеренно) потеряли память для объекта, на который указывает t4. Поскольку команды delete t4 не было, деструктор никогда не будет вызван.

Перед возвратом main выводится С. Поскольку t3 — это автоматическая переменная, область видимости которой ограничена main, на этом этапе она уничтожается, поскольку main делает возврат.

Наконец, статические и локальные поточные переменные t1 и t2 уничтожаются непосредственно перед выходом из программы, в результате чего получаются последние два сообщения в листинге 4.7.

Исключения


Исключения — это типы, сообщающие об ошибке. При возникновении ошибки генерируется исключение. После того как исключение было сгенерировано, оно переходит в состояние полета. Когда исключение находится в состоянии полета, программа останавливает нормальное выполнение и ищет обработчик исключений, который может управлять исключением в полете. Объекты, которые выпадают из области видимости во время этого процесса, уничтожаются.

В ситуациях, когда не существует хорошего способа локальной обработки ошибки, например в конструкторе, обычно используются исключения. Исключения играют решающую роль в управлении жизненными циклами объектов в таких обстоятельствах.

Другой вариант оповещения об ошибках — это возврат кода ошибки как части прототипа функции. Эти два подхода дополняют друг друга. В ситуациях, когда возникает ошибка, с которой можно справиться локально или которая должна произойти во время нормального хода выполнения программы, обычно возвращается код ошибки.

Ключевое слово throw

Чтобы вызвать исключение, используйте ключевое слово throw, за которым следует бросаемый объект.

Большинство объектов являются бросаемыми. Однако рекомендуется использовать одно из исключений, доступных в stdlib, например std::runtime_error в заголовке <stdеxcept>. Конструктор runtime_error принимает const char* с нулевым символом в конце, описывающий природу состояния ошибки. Это сообщение можно получить с помощью метода what, который не принимает параметров.

Класс Groucho в листинге 4.8 создает исключение всякий раз при вызове метода forget с аргументом, равным 0xFACE.

Листинг 4.8. Класс Groucho

Чтобы вызвать исключение, в листинге 4.8 используется ключевое слово throw 1, за которым следует объект std::runtime_error 2.

Использование блоков try-catch

Блоки try-catch используются для установки обработчиков исключений в блоке кода. Внутри блока try размещается код, который может вызвать исключение. Внутри блока catch указывается обработчик для каждого типа исключений, которые можно обработать.

Листинг 4.9 показывает использование блока try-catch для обработки исключений, генерируемых объектом Groucho.

В методе main создается объект Groucho, а затем устанавливается блок try-catch 1. В части try вызывается метод forget класса groucho с несколькими различными параметрами: 0xC0DE 2, 0xFACE 3 и 0xC0FFEE 4. Внутри части catch обрабатываются любые исключения std::runtime_error 5, выводя сообщение в консоли 6.

Листинг 4.9. Использование try-catch для обработки исключений класса Groucho

При запуске программы в листинге 4.9 вы получите следующий вывод:

При вызове forget с параметром 0xC0DE 2 groucho выводит Forgot0xc0de и завершает выполнение. При вызове forget с параметром 0xFACE 3 groucho выдает исключение. Это исключение остановило нормальное выполнение программы, поэтому forget никогда больше не вызывается 4. Вместо этого исключение в полете перехватывается 5, а его сообщение выводится в консоль 6.

Классы исключений stdlib

Можно организовать классы в родительско-дочерние отношения, используя наследование. Наследование оказывает большое влияние на то, как код обрабатывает исключения. Существует простая и удобная иерархия существующих типов исключений, доступных для использования в stdlib. Стоит попытаться использовать эти типы для простых программ. Зачем изобретать велосипед?

Стандартные классы исключений

stdlib предоставляет стандартные классы исключений в заголовке <stdеxcept>. Они должны стать вашим первым причалом при программировании исключений. Суперклассом для всех стандартных классов исключений является класс std::exception. Все подклассы в std::exception могут быть разделены на три группы: логические ошибки (logic_error), ошибки выполнения (runtime_error) и ошибки языковой поддержки. Ошибки языковой поддержки обычно не относятся к вам как к программисту, но вы наверняка столкнетесь с логическими ошибками и ошибками выполнения. Рисунок 4.1 обобщает их отношения.

С полным содержанием статьи можно ознакомиться на сайте "Хабрахабр":

https://habr.com/ru/company/piter/blog/552786/


Комментарии: 0

Пока нет комментариев


Оставить комментарий






CAPTCHAОбновить изображение

Наберите текст, изображённый на картинке

Все поля обязательны к заполнению.

Перед публикацией комментарии проходят модерацию.