it-roy-ru.com

Чем С отличается от С ++?

Многие люди говорят, что C++ - это совершенно другой язык, чем C, но сам Бьярне сказал, что C++ - это язык, который расширен от C, поэтому именно здесь ++ происходит от. Так почему же все продолжают говорить, что C и C++ - это совершенно разные языки? Чем C отличается от C++, кроме расширенных функций в C++?

21
Joshua Partogi

В 1980-х годах, когда разработка C++ только начиналась, C++ был почти правильным надмножеством C. Так все и началось.
Однако со временем и C, и C++ развились и разошлись, хотя совместимость между языками всегда считалась важной.

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

Это является движущим фактором для людей, говорящих такие вещи, как "нет такого языка, как C/C++" или "C и C++ - это два разных языка". Хотя можно писать программы, приемлемые как для компилятора C, так и для C++, обычно считается, что код не является ни примером хорошего кода C, ни примером хорошего кода C++.

18
Bart van Ingen Schenau

Сам Страуструп отвечает на это в его FAQ :

C++ является прямым потомком C, который сохраняет почти все C как подмножество. C++ обеспечивает более строгую проверку типов, чем C, и напрямую поддерживает более широкий диапазон стилей программирования, чем C. C++ является "лучшим C" в том смысле, что он поддерживает стили программирования, выполненные с использованием C, с лучшей проверкой типов и большей поддержкой нотации (без потерь эффективности). В том же смысле ANSI C лучше, чем K & R C. Кроме того, C++ поддерживает абстракцию данных, объектно-ориентированное программирование и общее программирование.

Это поддержка объектно-ориентированного программирования и общего программирования, которые делают C++ "совершенно отличным" от C. Вы можете почти написать чистый C и затем скомпилировать его с Компилятор C++ (если вы позаботитесь о более строгой проверке типов). Но тогда вы все еще пишете C - вы не пишете C++.

Если вы пишете на C++, вы используете его объектно-ориентированные и шаблонные функции, и это совсем не то, что вы видели бы в C.

20
Dean Harding

Проще говоря, то, что считается идиоматическим в C, определенно не является идиоматическим в C++.

C и C++ на практике очень разные языки из-за того, как люди их используют. C стремится к минимализму, где C++ является очень сложным языком с много функциями.

Есть также некоторые практические различия: C легко вызывается практически из любого языка и часто определяет ABI платформы, тогда как C++ довольно сложно использовать из других библиотек. Большинство языков имеют FFI или интерфейс на C, даже языки, реализованные на C++ (например, Java).

13
David Cournapeau

Помимо очевидного факта, что C++ поддерживает объектно-ориентированное программирование, я думаю, у вас есть ответ здесь: http://en.wikipedia.org/wiki/Compatibility_of_C_and_C++

Эта статья содержит примеры кода, показывающие то, что хорошо в C, но не в C++. Например:

int *j = malloc(sizeof(int) * 5); /* Implicit conversion from void* to int* */

Перенос программы на C на C++ часто прост и состоит в основном из исправления ошибок компиляции (добавления приведений, новых ключевых слов и т.д.).

4
Martin Wickman

C++ добавляет не только новые функции, но и новые концепции и новые идиомы к C. Несмотря на то, что C++ и C тесно связаны, факт остается фактом: чтобы эффективно писать на языке, вы должны мыслить в стиле этого языка. Даже самый лучший код C не может использовать в своих интересах различные сильные стороны и идиомы C++, и поэтому, скорее всего, это не так плохо код C++.

2
Jon Purdy

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

2
DeadMG

Разница в том, что в C вы мыслите процедурно, а в C++ вы думаете объектно-ориентированным образом. Языки очень похожи, но подход очень другой.

1
Ant

В то время как C++ может быть супернабором C в синтаксических терминах - то есть любая конструкция программы C может быть скомпилирована компилятором C++.

Тем не менее, вы почти никогда не пишете программы на C++ так, как вы делали бы это с программой на C. Список может быть бесконечным или кто-то должен просто сделать больше исследований, чтобы представить его как исчерпывающие отчеты. Тем не менее, я ставлю несколько указателей, которые делают ключевые различия.

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

Как это должно быть сделано в C++ над C

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

  2. Приватизация - Классы и даже структуры имеют то, что есть частные члены. Это делает возможным инкапсуляцию класса. Эквивалентом в C является типизация объекта как void * для приложения, чтобы приложение не имело доступа к внутренним переменным. Тем не менее, в C++ вы можете иметь элементы как с общими, так и с закрытыми классами.

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

  4. новый и удалить против malloc и бесплатно. Операторы new () и delete () не только выделяют и освобождают память, но и позволяют коду выполняться как часть destru-er, вызываемого в цепочке. Если вы используете C++ - на самом деле ПЛОХО использовать malloc и бесплатно.

  5. Типы ввода-вывода и перегрузка операторов Перегрузка операторов делает код читаемым или интуитивно понятным, если все сделано хорошо. То же самое для операторов << и >> io. C способ сделать это будет использовать указатели на функции - но это грязно и только для опытных программистов.

  6. Используя "строку". Char * из C работает везде. Так что C и C++ почти одинаковы. Однако, если вы находитесь в C++ - всегда намного лучше (и безопаснее) использовать классы String, которые избавляют вас от опасностей массивов при работе, которые есть почти во всех вещах.

Особенности, которые я до сих пор не был бы фанатом в C++ 1. Шаблоны - Хотя я не использую тяжелые шаблоны во многих кодах - это может оказаться очень мощным для библиотек. Этого почти нет в Си. Но в обычный день - особенно если вы делаете математически пропущенные.

  1. Умные указатели - да, они очень умные! И, как и большинство умных вещей, они начинаются хорошо, а потом становятся грязными! Я не совсем люблю использовать

Вещи, которые мне нравятся в C и не хватает в C++

  1. Полиморфные алгоритмы с использованием указателей на функции. В C, когда вы запускаете сложные алгоритмы - иногда вы можете использовать набор указателей на функции. Это делает истинный полиморфизм мощным способом. Когда вы находитесь в C++, вы [~ # ~] можете [~ # ~] использовать указатели на функции - но это плохо. Вы должны использовать только методы, иначе будьте готовы запутаться. Единственная форма полиморфизма в классах C++ - это перегрузка функций и операторов, но это довольно ограничивает.

  2. Простые темы. При создании потоков были pthreads - это довольно просто и управляемо. Это происходит, когда вам нужно создать потоки, которые должны быть "приватными" для классов (чтобы они имели доступ к закрытым членам). Существует тип повышения фреймворков - но в базовом C++ ничего нет.

Dipan.

0
Dipan Mehta

Некоторые языковые функции, даже если они являются дополнениями, могут полностью изменить способ использования языка. В качестве одного примера рассмотрим этот случай:

_lock_mutex(&mutex);

// call some functions
...

unlock_mutex(&mutex);
_

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

Деструкторы больше не находятся в сфере удобства, чтобы помочь программистам не забыть освободить/освободить ресурсы в этот момент. RAII становится практическим требованием, потому что по-человечески невозможно предвидеть каждую отдельную строку кода, которая может привести к нетривиальным примерам (не говоря уже о том, что эти строки могут не выдаваться сейчас, но могут позже с изменениями). Возьмите другой пример:

_void f(const Foo* f1)
{
    Foo f2;
    memcpy(&f2, f1, sizeof f2);
    ...
}
_

Такой код, хотя в целом безвреден в C, подобен хаосу, царящему в адском огне, потому что memcpy объединяет биты и байты этих объектов и обходит такие вещи, как конструкторы копирования. Такие функции, как memset, realloc, memcpy и ​​т.д., В то время как ежедневные инструменты разработчиков на С привыкли смотреть на вещи довольно однородно, битами и байтами в памяти, являются не гармонирует с более сложной и богатой системой типов C++. C++ поощряет гораздо более абстрактное представление пользовательских типов.

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

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

Я предпочитаю C++ гораздо чаще, чем нет, но на самом деле мне приходится довольно часто использовать API-интерфейсы C для самой широкой двоичной совместимости (и для FFI), хотя я часто реализую их в C++, несмотря на использование C для заголовков. Но иногда, когда вы переходите на действительно низкоуровневый уровень, например, к распределителю памяти или очень низкоуровневой структуре данных (и я уверен, что среди тех, кто занимается встроенным программированием, есть и другие примеры), иногда бывает полезно Можно предположить, что типы и данные, с которыми вы работаете, не имеют определенных функций, таких как vtables, costructors и destructors, так что мы можем рассматривать их как биты и байты для перемешивания, копирования, освобождения, перераспределения. Для особо низкоуровневых задач иногда бывает полезно работать с гораздо более простой системой типов, предоставляемой C, и, конечно, она имеет тенденцию к более быстрому построению и так далее.

разъяснение

Один интересный комментарий, на который я хотел бы ответить более подробно (я считаю, что комментарии здесь настолько строги по ограничению символов):

memcpy(&f2, f1, sizeof f2); также является "хаосом правящего адского огня" в C, если у Foo есть какие-либо указатели-владельцы, или даже хуже, поскольку у вас также нет инструментов, чтобы справиться с этим.

Это справедливо, но все, на чем я сконцентрировался, в основном сосредоточено на системе типов C++, а также на RAII. Одна из причин, по которой такое рентгеновское байт-копирование функций memcpy или qsort, представляет меньшую практическую опасность в C, заключается в том, что уничтожение _f1_ и _f2_ выше являются явными (если они даже нуждаются в нетривиальном уничтожении), тогда как, когда деструкторы перемещаются в картину, они становятся неявными и автоматизированными (часто с большой ценностью для разработчиков). Это даже не говоря о скрытом состоянии, таком как vptrs и т.д., Которые такие функции могли бы разрушить прямо сейчас. Если _f1_ владеет указателями, а _f2_ копирует их в каком-то временном контексте, то это не представляет проблемы, если мы не попытаемся явно освободить те, у кого есть указатели, во второй раз. С C++ это то, что компилятор автоматически захочет сделать.

И это становится больше , если обычно в C, " If У Foo есть собственные указатели ", потому что ясность, необходимая для управления ресурсами, часто делает это чем-то более сложным для игнорирования, тогда как в C++ мы можем сделать UDT более не тривиально конструируемым/разрушаемым, просто заставляя его хранить любую переменную-член, которая не ' • Тривиально конструируемые/разрушаемые (опять же, как правило, это очень полезно, но не в том случае, если мы склонны использовать такие функции, как memcpy или realloc).

Моя главная мысль не в том, чтобы пытаться спорить о какой-либо пользе от этой явности (я бы сказал, что если таковые имеются, они почти всегда отягощены минусами повышенной вероятности человеческой ошибки, которая с ними связана), а просто сказать, что такие функции, как memcpy и ​​memmove и ​​qsort и ​​memset и ​​realloc и ​​т. д., не имеют места в языке с такими UDT, как богатые особенности и возможности как C++. Несмотря на то, что они существуют независимо, я думаю, что было бы не слишком оспаривать, чтобы сказать, что подавляющее, огромное большинство разработчиков C++ было бы разумно избегать таких функций, как чума, тогда как в C это очень повседневные функции, и я Я утверждаю, что они создают меньше проблем в C по той простой причине, что его система типов намного более проста и, возможно, "тупее". Рентгенография типов C и обработка их как битов и байтов подвержена ошибкам. Делать это в C++ возможно просто ошибочно, потому что такие функции борются с очень фундаментальными особенностями языка и тем, что поощряется системой типов.

Это на самом деле самое привлекательное для меня C, тем не менее, особенно с учетом того, как оно связано с совместимостью языков. Было бы намного сложнее заставить что-то вроде FFI в C # понимать полноценную систему типов и языковые особенности C++ вплоть до конструкторов, деструкторов, исключений, виртуальных функций, перегрузки функций/методов, перегрузки операторов, всех различных типов наследование и т. д. С C это относительно тупой язык, который стал довольно стандартным для API, так что многие различные языки могут импортировать напрямую через FFI или косвенно через некоторые функции экспорта C API в желаемой форме (например: Java Native Interface). И именно здесь у меня больше не остается выбора, кроме как использовать C, поскольку в нашем случае эта функциональная совместимость является практическим требованием (хотя часто я просто пишу интерфейсы C с C++ реализации позади них).

Но вы знаете, я прагматик (или, по крайней мере, я стараюсь быть). Если бы C был этим самым отвратительным и отвратительным, склонным к ошибкам языком, то некоторые из моих коллег-энтузиастов C++ утверждали, что это так (и я бы считал себя энтузиастом C++, за исключением того, что каким-то образом это не привело к ненависти к C с моей стороны). напротив, это оказало на меня противоположное влияние, заставив меня ценить оба языка лучше в их собственных отношениях и различиях), тогда я ожидал бы, что это проявится в реальном мире в форме некоторых из самых плохих и утечек и ненадежные продукты и библиотеки пишутся на C. И я не нахожу этого. Мне нравится Linux, мне нравится Apache, Lua, zlib, я нахожу OpenGL приемлемым для своего давнего наследия против таких меняющихся требований к аппаратному обеспечению, Gimp, libpng, Cairo и т.д. По крайней мере, любые препятствия, которые ставит язык, не создают тупиковых ситуаций, поскольку написание крутых библиотек и продуктов в компетентных руках, и это действительно все, что меня интересует. Так что я никогда не был настолько заинтересован в самых страстных языковых войнах, за исключением того, чтобы прагматично апеллировать и сказать: "Эй, есть там классные вещи! Давайте узнаем, как они это сделали, и, может быть, есть классные уроки, не настолько специфичные для идиоматической природы языка, которые мы можем перенести на любой язык (языки), которые мы используем ". :-D

0
Dragon Energy