Продолжающееся путешествие от C к современному C++
Задний план:
Я инженер-программист. Хотя недавно переделал. Я получил двойную Е с несовершеннолетним в CS. Работал инженером-нефтяником. Пока я не понял, что мне действительно нравится заниматься программированием. Итак, я переключился.
Я знал C++ по университетской работе. Я изучил Java-программирование для Android-приложений. Для развлечения в качестве подработки. Я выучил Python, чтобы возиться с Raspberry Pi и пробиться в индустрию обработки данных. Тем не менее, для работы я должен был сделать C. Как это может быть сложно, подумал я. Ну, очень похоже на C++, которому меня учили в школе. Тем не менее, он сильно отличается от современных языков высокого уровня, которые я выучил позже. Что без занятий! Нет перегрузки функций! Никаких простых в использовании функций для работы со строками! Запомнить! Сюрпризы закончились не скоро.
Я попытался написать свой код на C++ и связать его с устаревшим кодом C. Но мой ограниченный опыт был очевидным барьером. Через несколько месяцев моя мысленная модель языка сформировалась. Я получил руку его. Тем не менее, я ясно вижу, как разработка может быть медленной в C. Я обнаружил, что внедряю структуры данных, которые не являются частью языка, чтобы ускорить разработку. Я понял, что хотя я и способен на это, многое может занять много времени, не так эффективно, как STL, и ограничено языковыми ограничениями.
Итак, я решил выйти за рамки C и погрузиться в мир современного C++. Медленно-медленно интегрируем больше C++ в исходную базу. Я могу создавать код C с помощью компиляторов C++. Итак, я решил вести журнал. Вещи, которые я открываю по пути. Я был бы признателен, если бы другие (более опытные) программисты указали на ошибки в этой статье и дополнили ее. Вот так.
Основы:
- Инициализатор {}:
В C нельзя использовать {} для инициализации значения без =, который вызывает копию:
Итак, почему, еще отличается? {} выполняет проверку типов во время компиляции. Следующее не будет компилироваться:
Установка i на 0,1 в C вызовет предупреждение.
- Ключевое слово auto:
В C++ можно использовать auto. auto избавляет от необходимости понимать, что возвращает функция. Поначалу для программиста, предвзято относящегося к типам, это звучало не очень умно. Тем не менее, при работе с объектами в разных пространствах имен использование auto делает код чище и удобнее в сопровождении по мере изменения API. - for in :
Это одно из моих любимых. Сочетание этого с auto упрощает итерацию по итерации. Не говоря уже о аккуратности. Поскольку большинство итераций обычно происходит по всей коллекции, это становится очень удобным.
- Ссылка и в объявлении:
Ссылки, с точки зрения программиста C, представляют собой константный указатель, который передается и отслеживается за сценой. Возьмем следующий пример:
Теперь, если мы попробуем вместо этого использовать ссылки, поскольку намерение состоит в том, чтобы изменить значение целого числа, на которое указывает переданный указатель, мы можем переписать его следующим образом:
(Игнорируйте тот факт, что это будет преобразовано в число с плавающей запятой, а затем обратно в целое число)
В обоих случаях мы избегали копирования int (ВАУ, большое достижение), но мы избегали предоставления функции доступа к значению указателя, который по любой причине может быть поврежден, позволяя при этом изменять его содержимое.
- nullptr & NULL:
nullptr заменяет собой использование NULL. NULL обычно определяется в C как 0. Использование языковой константы, такой как nullptr, устраняет путаницу. Присвоение указателю нуля по-прежнему разрешено в C++, но не одобряется. - Пространства имен
Пространства имен — очень интересный инструмент, помогающий уточнить наименования объектов. В пространстве имен один раз можно сгруппировать несколько связанных объектов в пространстве имен. Следовательно, эти имена можно повторно использовать в другом месте, либо в другом пространстве имен, либо в глобальном пространстве имен.
Как только объект находится в пространстве имен, на него можно ссылаться, используя синтаксис namespace::object
Импорт имени из определенного пространства имен (т. е. использование его без прикрепленного к нему пространства имен) может быть достигается с помощью «использования». Импорт всех имен пространств имен в глобальное пространство имен можно выполнить с помощью «using namespace::» - классы-перечисления
C поддерживает типы-перечисления. Тем не менее, перечисляемые классы — это новое дополнение к языку C++, которое (по аналогии с пространством имен) содержит термины перечисления в своем собственном пространстве. В C это не скомпилируется
Использование классов инкапсулирует каждое перечисление, но доступ к термину перечисления требует использования имени класса, чтобы компилятор мог различать их.
- обработка ошибок
C++ имеет встроенные функции для обработки исключений. Язык предоставляет способы обнаружения неожиданного или ошибочного поведения, которого нельзя ожидать (аппаратный сбой, ошибка ОС и т. д.). Можно также «подбросить» исключение вверх по стеку, чтобы другой объект мог с ним справиться. Эмуляция того же поведения в C — ручная работа, нестандартизированная и синтаксически непонятная. - Приведение
Приведение в C немного неоднозначно. Приведение переменной может преобразовать ее тип. Преобразование ячейки памяти просто изменит интерпретацию системы и обработку значения в этой ячейке.
С другой стороны, C++ содержит несколько типов мощных возможностей приведения для управления преобразованием типов. Основные методы приведения: static_cast, dynamic_cast, reinterpret_cast, const_cast. Dynamic Cast идеально подходит для использования между указателями и ссылками на классы. Это добавляет дополнительную проверку, чтобы убедиться, что преобразование является допустимым. С другой стороны, статические приведения не выполняют проверки преобразования. Преобразования Reinterpret выполняют преобразование двоичного уровня из одного типа в другой. Наконец, const_cast меняет тип с константного на неконстантный или наоборот. - Союзы
Функционально союзы остаются прежними. Тем не менее, в C++ последний использованный тип называется активным членом, и он является единственным действительным членом до следующего присваивания. Другими словами, присвоение значения определенного типа члена элементу объединения, а затем доступ к элементу с использованием другого типа члена считается поведением undefined. Я бы подумал, что это неразумно делать даже в C.
Рассмотрите возможность использования Variant из стандартной библиотеки C++. - Структуры (как классы)
C++ позволяет структурам содержать функции. Это полезная функция для классов, которые содержат все открытые члены (переменные и функции). Структура может до некоторой степени действовать как класс. - Классы и объектно-ориентированные функции
C на самом деле не поддерживает классы, наследование и полиморфизм. Есть способы эмулировать подобное поведение в C, но это уже совсем другой пост. - Перегрузка функций:
В языке C разрешен один прототип функции (в старых определениях языка C функцию можно определить только по ее возвращаемому типу). Что касается C++, одно и то же имя функции может использоваться для разных прототипов функций.
Это не разрешено в C. Тем не менее, в C++
это совершенно нормально (пока компилятор может сделать вывод, какой из них вы вызываете).
Со всем, что упомянуто, кажется, что это едва царапает поверхность. C++ STL (стандартная библиотека) — очень богатый и мощный инструмент, который при правильном использовании может сделать код кратким, (в некоторой степени) читабельным, менее подверженным ошибкам и эффективным. Есть и другие особенности, о которых я не упомянул, например, лямды.
Не стесняйтесь обращаться ко мне по поводу изменений или дополнений к этому сообщению.
Использованная литература:
Путешествие по C++
В книге «Путешествие по C++, второе издание Бьярн Страуструп, создатель языка C++, описывает, что представляет собой современный язык C++. Это…learning.oreilly.com»
https://stackoverflow.com/questions/10586003/try-catch-statements-in-c