По мнению Алана Кэя, объектная модель «Алгол с классами», использованная в C++, уступает модели «всё — объект»[37], используемой в Objective-C, по общем объёму возможностей, показателям повторного использования кода, понимаемости, модифицируемости и тестируемости. В то же время использование сборщика мусора и виртуальной машины создают труднопреодолимые ограничения. Программы на Java, как правило, медленнее, требуют значительно больше памяти, к тому же виртуальная машина изолирует программу от операционной системы, делая невозможным низкоуровневое программирование.
Для снижения размера машинного кода пытаются автоматически обрабатывать исходный код до этапа раскрутки шаблонов[46][47]. Другим решением могла бы быть стандартизованная ещё в 1998 году возможность экспорта шаблонов, но она доступна далеко не во всех компиляторах, так как её трудно реализовать[48][49][мнения 4] и для импорта библиотек шаблонов C++ в языки с существенно отличной от C++ семантикой она всё равно была бы бесполезна. Сторонники C++ оспаривают масштабы раздувания кода как преувеличенные[50], игнорируя даже тот факт, что в Си параметрический полиморфизм транслируется непосредственно, то есть без дублирования тел функций вообще. При этом сторонники C++ считают, что параметрический полиморфизм в Си опасен — то есть более опасен, чем переход от Си к C++ (противники C++ утверждают обратное — см. выше). Стандартная библиотека C++ включает в себя набор средств, которые должны быть доступны для любой реализации языка, чтобы обеспечить программистам удобное пользование языковыми средствами и создать базу для разработки как прикладных приложений самого широкого спектра, так и специализированных библиотек.
Типы[править править код]
Выбор реализации метода Draw будет производиться во время выполнения исходя из реального типа объекта. Одной из первых альтернатив C++ в прикладном программировании стал язык Java. Его часто ошибочно считают прямым потомком C++; в действительности семантика Java унаследована от языка Модула-2, и основы семантики C++ в Java не прослеживаются. Учитывая это, а также генеалогию языков (Модула-2 является потомком Симулы, как и C++, но им не является Си), Java правильнее называть «троюродным племянником» C++, нежели «наследником». То же можно сказать о языке C#, хоть процент родственности с C++ у него несколько выше, чем у Java.
При этом некоторые интуитивно ожидаемые операции (подчистка динамических объектов в случае генерации исключений) в C++ не выполняются, а значительная часть перегруженных функций и операторов вызывается неявно (приведение типов, создание временных экземпляров классов и др.). В результате средства, изначально предназначенные для того, чтобы сделать программы более ясными и повысить удобство разработки и сопровождения, превращаются в ещё один источник неоправданного усложнения и снижения надёжности кода. Попыткой создать промышленную замену C/C++ стал разработанный в корпорации Google в 2009 году язык программирования Go. Авторы языка прямо указывают, что мотивом для его создания были недостатки процесса разработки, вызванные особенностями языков Си и C++[56]. Язык позиционируется как альтернатива C++, то есть, в первую очередь, средство групповой разработки высокоэффективных вычислительных систем большой сложности, в том числе распределённых, допускающее, при необходимости, низкоуровневое программирование.
Вычислительная эффективность[править править код]
Например, на платформе x86 это GCC, Clang, Visual C++, Intel C++ Compiler, Embarcadero (Borland) C++ Builder и другие. C++ оказал огромное влияние на другие языки программирования, в первую очередь на Java и C#. К С были добавлены некоторые новые возможности и расширения, предназначенные для поддержки объектно-ориентированного программирования (ООП). Так как С++ создан на основе С, нельзя программировать на С++, не зная, как программировать на С. К 1983 году в язык были добавлены новые возможности, такие как виртуальные функции, перегрузка функций и операторов, ссылки, константы, пользовательский контроль над управлением свободной памятью, улучшенная проверка типов и новый стиль комментариев (//). Получившийся язык уже перестал быть просто дополненной версией классического C и был переименован из C с классами в «C++».
- В одной экологической нише с C/C++ находится разработанный в 2010 году и поддерживаемый корпорацией Mozilla язык Rust, ориентированный на безопасное управление памятью без использования сборщика мусора.
- Здесь класс Figure является абстрактным (и, даже, интерфейсным), так как метод Draw не определён.
- Как отмечает Ян Джойнер[39], C++ ошибочно отождествляет инкапсуляцию (то есть помещение данных внутрь объектов и отделение реализации от интерфейса) и сокрытие реализации.
- В качестве основы для хранения и доступа к обобщённым алгоритмам была выбрана Стандартная библиотека шаблонов (STL), разработанная Александром Степановым и Менг Ли[en].
- Перечисленные выше факторы делают сложность менеджмента проектов на C++ одной из самых высоких в индустрии разработки ПО.
Доступ к возможностям стандартной библиотеки C++ обеспечивается с помощью включения в программу (посредством директивы #include) соответствующих стандартных заголовочных файлов. Средства стандартной библиотеки объявляются как входящие в пространство имён std. Заголовочные файлы, имена которых соответствуют шаблону «cX», где X — имя заголовочного файла стандартной библиотеки C без расширения (cstdlib, cstring, cstdio и пр.), содержат объявления, соответствующие данной части стандартной библиотеки C. Стандартные функции библиотеки C также находятся в пространстве имён std.
Избыточные и опасные возможности[править править код]
В теле определения класса можно указать как объявления функций, так и их определение. Нестатические функции-члены могут иметь квалификаторы const и volatile, а также ссылочный квалификатор (& или &&). C++ (читается си-плюс-плюс[2][3]) — компилируемый, статически типизированный язык программирования общего назначения. Ещё одним языком, рассматриваемым как конкурент C++, стал Nemerle, являющийся результатом попытки совместить модель типизации Хиндли-Милнера и макроподмножество Common Lisp с языком C#[55]. В том же русле находится созданный Microsoft язык F# — диалект ML, адаптированный для среды .NET.
Попыткой совмещения безопасности и скорости разработки, характерных для Java и C#, с возможностями C++ явился диалект Managed C++ (впоследствии — C++/CLI). Он разработан Microsoft в основном для переноса существующих проектов на C++ под платформу Microsoft.NET. Программы выполняются под управлением CLR и среда разработки c# могут использовать весь массив библиотек .NET, но при этом накладывается ряд ограничений на использование возможностей C++, что фактически сводит C++ к C#. Данный диалект не получил широкого признания и используется в основном лишь для связывания библиотек, написанных на чистом C++, с C#-приложениями.
Стандартная библиотека[править править код]
Язык также не был назван D, поскольку «является расширением C и не пытается устранять проблемы путём удаления элементов C»[7]. Таким образом, одни и те же свойства C++ — объём, сложность, эклектичность и отсутствие конкретной целевой ниши применения — рассматривается сторонниками как «главное достоинство», а критиками — как «главный недостаток». В статье Стефена Цейгера из Rational Software Corporation[29], утверждается, что в целом разработка на Аде обходится на 60% дешевле, и приводит к получению кода, имеющего в 9 раз меньше дефектов, чем на Си. Хотя эти результаты не могут быть прямо перенесены на C++, но всё же представляют интерес с учётом того, что многие недостатки C++ унаследованы от Си. В C++ (как и в C), если выполнение программы доходит до конца функции main(), то это эквивалентно return 0;.
Для автоматического управления памятью в C++ традиционно используются т. «умные указатели», ручное же управление памятью снижает эффективность самих программистов (см. раздел Результативность). Многочисленные реализации сборки мусора, таких как статический вывод регионов не применимы для C++ программ (точнее, это требует реализации поверх языка C++ интерпретатора нового языка, сильно отличающегося от C++ как большинством объективных свойств, так и общей идеологией) по причине необходимости прямого доступа к AST. C– (читается как «Си минус минус») — переносимый язык программирования низкого уровня, используемый как промежуточное представление для сверхвысокоуровневых языков. Создан во второй половине 1990-х годов исследователями функционального программирования Пейтоном-Джонсом и Рэмси Норманом (англ.) (рус.. Основная отличительная особенность в сравнении с различными вариантами байткодов в том, что сгенерированный результат на C– является человекочитаемым — текстом на языке с си-подобным синтаксисом. Кроме того, это увеличивает длительность самого процесса разработки[34].
Система типов[править править код]
В сравнении с его предшественником — языком C — наибольшее внимание уделено поддержке объектно-ориентированного и обобщённого программирования[5]. Для написания портируемого кода на C++ требуется огромное мастерство и опыт, и «небрежные» коды на C++ с высокой вероятностью могут оказаться непортируемыми[43]. По мнению Линуса Торвальдса, для обеспечения на C++ портируемости, аналогичной Си, программист должен ограничиться возможностями C++, унаследованными от Си[33]. Стандарт содержит множество элементов, определённых как «implementation-defined» (например, размер указателей на методы классов в различных компиляторах варьируется в диапазоне от 4 до 20 байт[44]), что ухудшает портируемость программ с их использованием.
Несмотря на ряд известных недостатков языка C, Страуструп пошёл на его использование в качестве основы, так как «в C есть свои проблемы, но их имел бы и разработанный с нуля язык, а проблемы C нам известны». Кроме того, это позволило быстро получить прототип компилятора (cfront), который лишь выполнял трансляцию добавленных синтаксических элементов в оригинальный язык C. В результате наследования класс-потомок получает все поля классов-предков и все их методы; можно сказать, что каждый экземпляр класса-потомка содержит подэкземпляр каждого из классов-предков. Если один класс-предок наследуется несколько раз (это возможно, если он является предком нескольких базовых классов создаваемого класса), то экземпляры класса-потомка будет включать столько же подэкземпляров данного класса-предка.