Обсуждение:C++: различия между версиями
Нет описания правки |
|||
Строка 529: | Строка 529: | ||
В буржунете даже есть такое слово "Bullshildt" [[Special:Contributions/81.195.20.101|81.195.20.101]] 18:26, 2 декабря 2010 (UTC)Vasya |
В буржунете даже есть такое слово "Bullshildt" [[Special:Contributions/81.195.20.101|81.195.20.101]] 18:26, 2 декабря 2010 (UTC)Vasya |
||
== Макросы == |
|||
''# Макросы (#define) являются мощным, но опасным средством. Они сохранены в C++ несмотря на то, что необходимость в них, благодаря шаблонам и встроенным функциям, не так уж велика[источник не указан дцать дней].'' |
|||
Можно сослаться на "Герб Саттер, Андрей Александреску. Стандарты программирования на С++" (http://ru.wikipedia.org/wiki/%D0%A1%D0%BB%D1%83%D0%B6%D0%B5%D0%B1%D0%BD%D0%B0%D1%8F:BookSources/9785845903518). |
|||
--[[Special:Contributions/193.232.174.16|193.232.174.16]] 13:05, 18 января 2011 (UTC) |
Версия от 13:05, 18 января 2011
побольше бы
Хорошо бы побольше написать...
///Demon/// — Эта реплика добавлена с IP 195.230.73.2 (о) 07:48, 21 сентября 2004 (UTC)
- Конечно, хорошо бы. Напишешь? MaxiMaxiMax 08:16, 21 Сен 2004 (UTC)
- А по-моему, хорошо бы меньше. Уж больно статья рыхлая получилась. Всё как-то раскидано по разным частям текста, много дублирования. С вашего позволения, я постараюсь её причесать.
- Для начала переписал вводную часть, так чтобы в ней осталась только важнейшая выжимка сведений о языке.
- --achp 11:39, 11 марта 2006 (UTC)
- Сократил статью ещё --Urod 02:06, 21 июня 2006 (UTC)
Не писать return 0; в main() это всё-таки дурной тон. Думаю, надо оставить только последний пример с добавлением return 0; .
И ещё нужна ссылка на STL, ибо стандарт и фундаментальная часть языка.
Как-нибудь доберусь -- распишу...
--Maxim Razin 15:33, 4 Янв 2005 (UTC)
Начал переработку статьи исходя из перевода английской статьи и личных знаний…
Про STL тоже напишу…
§l1ck Ar7ist 15:28, 14 Фев 2005 (UTC)
- В основном всё готово.
Недоделки — отсутствие списка внешних адресов. Ну и какую-нибудь картинку можно для красоты поместить. Потом можно и на «лучшее» номинироваться. :)§l1ck Ar7ist 14:32, 16 Фев 2005 (UTC)
- Вообще-то, исходя из семантики названия языка, следовало бы переименовать статью в «Си-плюс-плюс» или «Си плюс-плюс»: ведь речь не о том, что к Си прибавляется плюс, а о том, что производится инкрементация. По-моему, если название понятия состоит из равноправных
частей речи (первый плюс ничем не хуже второго), из надо через дефис. Al Silonov 8 июля 2005 12:10 (UTC)
Bjarne
Бьярне Страуструп — верная транслитерация. Ramir 02:42, 2 января 2006 (UTC)
- А статья утверждает обратное, да и сам Бьярне, похоже склоняется именно к варианту Строуструп (см. аудиозапись произношения). ~ qvvx 11:10, 4 января 2006 (UTC)
Картинка
А в этой картинке есть какой-то смысл? --Solon 23:13, 29 ноября 2005 (UTC)
Картинка в вводном абзаце не несёт никакой смысловой нагрузки вообще, зато съедает много места. Предлагаю избавиться от неё. ~ qvvx 20:50, 3 января 2006 (UTC)
А, прошу прощения, не заметил сообщение Solon. Ну, раз возражений не последовало, то я убираю картинку. ~ qvvx 21:29, 3 января 2006 (UTC)
Убрал пассаж "что дает серьёзные преимущества по сравнению с другими языками". К сожалению, не указаны ни обоснование, ни источники. Nikov 11:31, 3 ноября 2007 (UTC)
В первую очередь - остуствие CTTI является недостатком, но никак не отсутствие RTTI. Так как язык C++ - язык построения систем, а никак не язык использования каких то конкретных систем (таких как Garbage Collection и RTTI). Как раз добавление в язык CTTI позволит строить любые RTTI. Поэтому - отсутствие RTTI (и связанных с ним затрат) не является недостатком, а может даже достоинством.
Не забываем, что C++ так же используется для программирования микроконтроллеров с крайне ограниченной, поэтому любой встроенный RTTI будет только мешать.
Sergey Shandar — Эта реплика добавлена участником Sergey shandar (о • в) 03:37, 20 июня 2006 (UTC)
- Раздел "Недостатки" переименовал. Большинство этих «недостатков» сводится к тому, что С++ - не Java. Они не устранимы без превращения С++ в интерпретируемый язык и, соответственно, резкой потери эффективности. Нельзя в статье "автомобиль Форд-Эскорт" в разделе "недостатки" писать, что он не может перевозить многотонные грузы. Я хотел бы вообще выбросить раздел: С++ и Java - языки разных типов, применимые в разных областях и некорректно их сравнивать. — Эта реплика добавлена участником Urod (о • в) 02:06, 21 июня 2006 (UTC)
Согласен. Максимум что оставить - так это различия. Но убрать "сторонников C++" и "сторонников Java". --Sergey Shandar 13:40, 21 июня 2006 (UTC)
Не путаем CTTI и RTTI. Java имеет RTTI, но Java НЕ имеет полноценного CTTI, так же как и средств для метапрограммирования (программирование и вычисление во время компиляции). --Sergey Shandar 12:45, 22 июня 2006 (UTC)
Коллеги, вы вообще о чём? RTTI в C++ как раз есть, это dynamic_cast и typeof (и лично я это рассматриваю как один из самых больших недостатков языка, но тут уже возможны и иные мнения) DrCroco 13:21, 22 января 2008 (UTC)
-- А как же dynamic_cast и typeid ? Это разве не относится к RTTI ? Касательно garbage collection можно радостно использовать shared и auto указатели как альтернативу.
<yurec> — Эта реплика добавлена с IP 195.39.210.202 (о) 22:49, 3 ноября 2008 (UTC)
В C++ не полноценный RTTI, храниться только очень-очень мальнькая часть информации о типе (не вся как в Java или .NET), и то, в многих компиляторах можно выключить польностью. --Сергей Шандар 15:40, 28 апреля 2009 (UTC)
Сравнение с Java
С другой стороны, Java является некомпилируемым языком (программы компилируются не в машинный код, а в некий промежуточный код, который интерпретируется), что приводит к чрезвычайно низкой, по сравнению с С++, эффективности. Поэтому круг задач, где может использоваться Java, ограничен.
Это не совсем правда. Java может компилировать в машнный код. См. JIT
--Sergey Shandar 09:28, 21 июня 2006 (UTC)
- Дело не в том, может или не может Java компилировать в машинный код. Сделать такие компиляторы никогда не было проблемой и они существуют. Проблема в том, что Java-программы должны выполняться на виртуальной Java-машине и следовательно ограничены возможностями ее архитектуры. Никакие нововведия архитектуры процессоров не повлияют на характеристики программ, написанных на Java.
- Неспроста основатель Java и производитель hardware Sun заняла ту позицию, которая она заняла.
--HenryS 16:06, 25 июня 2006 (UTC)
Священная война
Сам факт такой "войны" обязан быть отражён в статье. Я создал два независимых раздела, которые прошу заполнить неон 10:58, 21 июня 2006 (UTC)
Давай, тогда, вынесем это ниже достоинств и недостатков. Хотя по мне - этой войны в статье не должно быть. Лучще найти компромис и объективную информацию. Все эти войны, в основнов, из за не понимания предназначения языка. Например, может быть достаточно дать пару ссылок на RSDN, где эти войны носят тотальный характер и флейм по ним идет на несколько мега страниц... Сразу скажу - я не сторонник ни одного из этих языков. Я их просто применяю там где нужно, каждый в своей области. Например, написать маршалинг интерфейсов лучше на C++, так как необходимо работать с незащищенной памятью, и стеком. А написать GUI лучше, конечно, на Java. Ссылки на войны http://www.rsdn.ru/forum/?group=flame.comp. По поиску можно найти очень много споров что лучще и что хуже.
--Sergey Shandar 13:31, 21 июня 2006 (UTC)
Согласен насчёт вынести в конец статьи. Кстати хорошо бы и написать про сам факт такой войны и дать эти ссылки - явление знаменательное. Приведите пожалуйста! То что у сторонников Явы больше аргументов, и то что "С не Ява" - тоже закономерно, потому что Яву разрабатывали после С с учётом его недостатков и пытаясь улучшить язык неон 13:47, 21 июня 2006 (UTC)
Например: http://www.rsdn.ru/Forum/Message.aspx?mid=1669546&only=1 - С++ vs C# (я это даже не читаю, не осилил :-) — Эта реплика добавлена участником Sergey shandar (о • в) 13:52, 21 июня 2006 (UTC)
Здорово! Если можете доработать - попробуйте, если лень - я попытаюсь сам :-) Собственно тут не место для теоретических споров, но существующие мнения в обе стороны хорошо бы отразить для потомства. неон 14:01, 21 июня 2006 (UTC)
Попробуйте сами. А я позже гляну :-) — Эта реплика добавлена участником Sergey shandar (о • в) 14:09, 21 июня 2006 (UTC)
Хорошо, попробую, а Вы если что - подправите неон 14:12, 21 июня 2006 (UTC)
Уже лучще :-) С некоторыми пунктами я все еще не согласен. Но, пока, закрою на них глаза --Sergey Shandar 01:12, 22 июня 2006 (UTC)
Почему не надо войны
Например, моя критика на критику :-) :
Критика языка Java сторонниками C++
- Java является некомпилируемым языком (программы компилируются не в машинный код, а в некий промежуточный код, который интерпретируется), что приводит к чрезвычайно низкой, по сравнению с С++, эффективности. Поэтому круг задач, где может использоваться Java, ограничен.
Это не правда :-)Java может компилироваться. Иногда код может быть даже быстрее на Java, все еще зависит еще от того кто писал и как :-)
Критика С++ сторонниками Java
* Сторонники языка C++ считают, что С++ компиляторы генерируют более эффективный код. Это было одним из центральных пунктов критики языка Java при его появлении. Однако сейчас сторонники языка Java считают, что всвязи с прогрессом компиляторов разница в эффективности компиляции стала не существенной, но за счёт лучшей технологии подготовки программ в конечном итоге программы на Java могут оказаться значительно более эффективны и после компилляции.
- то были неправильные сторонники C++ :-) ни Java ни C++ пока не стоят на месте.
* В языке C++ нет чётко сформулированных принципа организации библиотек классов и пакетов, при этом поощряется переопределение всех базовых понятий языка с самого низкого уровня. Это приводит к трудностям при соединении друг с другом крупных пакетов программ.
- это зависит от КУЛЬТУРЫ программирования. На ассемблере тоже можно писать применяя ООП, а на Java процедурно. Есть и принципы и в C++ по организации (например, см. Boost). Данная гибкость означает только то, что ты свободен в праве выбора, но со свободой появляется и ответственность, и про это многие забываю.
* В языке C++ нет чётко определённых стандартов на ввод-вывод, графику, геометрию, диалог, доступ к базам данных и прочим типовым приложениям.
Это можно считать и достоинство. Например, у меня микроконтроллер, управляющий сборкой данных, какой у него может быть стандарт на графику? Второе: а если я хочу создать новый стандарт на графику?
* Возможность введения пользовательского синтаксиса с помощью #define может привести к тому, что модули в крупных пакетах программ становятся сильно связаны друг с другом, что резко понижает надёжность пакетов и возможность организации разделённых модулей. С другой стороны, С++ предоставляет достаточно средств (константы, шаблоны, встроенные функции) для того, чтобы практически полностью исключить использование #define.
Согласен. Но, в многих проффесиональных библиотеках использование без повода define стараются избегать. Но есть случае когда без них просто нельзя. Например STATIC_ASSERT(условие времени компиляции)
* В С++ нет механизма встроенных проверок корректности указателей, что может привести к тяжёлым непредсказуемым последствиям порчи памяти, связанным со сбоем адресации. С другой стороны, стандартная библиотека шаблонов STL и механизмы ООП позволяют практически исключить выделение памяти вручную.
Да. С указателями в C++ можно натворить дел. Поэтому и нужно быть аккуратным. А проверка корректности указателей может повлиять на скорость работы программы или сделать вообще невозможным реализации некоторых модулей (тот же маршалинг).
--Sergey Shandar 14:10, 21 июня 2006 (UTC)
Хм... Критика не объективная
IMHO: В статье появилось много совсем не признаных или спорных недостатков. Которые, я лично, не считал за недостатки или за очень незначительные. Скорее как особенность языка. Например:
* C++ унаследовал многие проблемы языка C:
Согласен, но наследство можно использовать и как достоинство. Например, затем же C# брал синтаксис из C++, что бы программистам было легче переходить, а не из за того что это красиво.
o Операция присваивания обозначается = , а операция сравнения == . Их легко спутать, и такая конструкция будет синтаксически правильной, но приведёт к труднонаходимому багу. Особенно часто это происходит в операторах if и while, например, программист пишет if (i=0) вместо if (i==0).
То же самое что и первый пункт. Согласен что это не очень красиво, но можно привыкнуть и к тому же многие языки делают именно так. Это больше вопрос соглашений.
o Некоторые считают неправильным приоритет операций: например, в выражении (a<b&c<d) сначала будет выполнена операция &.
Ну да, ведь есть еще операция && для булевских операция. А & это битовая операция, поэтому приоритет ОЧЕНЬ ДАЖЕ правильный!
o Операции присваивания (=), инкрементации (++), декрементации (--) и другие выдают значение. В сочетании с обилием операций это позволяет, но не обязывает программиста, создавать сложные для понимания выражения.
Это фича, а не недостаток. Причем иногда очень полезная при написании выражений которые нужно оптимизировать. Хотя сам без повода стараюсь не использовать результат операции ++ или --. Но иногда это полезно.
o Некоторые преобразования типов неинтуитивны. В частности, операция над беззнаковым и знаковым числами выдаёт беззнаковый результат. Например, unsigned u=0; double d=u-1; приведёт к тому, что d будет большим положительным числом, а не -1, как можно ожидать.
Да, есть немного. Используйте явные преобразования по возможности.
o Подключение интерфейса внешнего модуля через препроцессорную вставку заголовочного файла (#include) серьезно замедляет компиляцию, при подключении большого количества модулей. Для устранения этого недостатка, многие компиляторы реализуют механизм прекомпиляции заголовочных файлов Precompiled Headers.
Это реальный недостаток.
o Недостаток информации о типах данных во время компиляции (CTTI).
Аналогично. Так как отсутствие CTTI серьезно затрудняет работу с типами данных в шаблонах.
o Макросы (#define) являются мощным, но опасным, средством. В языке C++, в отличие от C, необходимость в опасных макросах появляется крайне редко, благодаря шаблонам и встроенным функциям. Однако в стандартных библиотеках много потенциально опасных макросов.
Наличие у танка дополнительного мощного оружия можно считать недостатком, если экипаж не знает как им пользоватся? Еще раз - это фича которая требует определенных знаний и культуры!
o Нет проверки выхода за границы массива.
Это очень даже хорошо!!!
o Язык C++ гораздо сложнее для изучения
Это да. Но зато как мощный инструмент после того как научился им пользоватся :-) Как сравнивать ручную коробку передач и автомат.
o Язык C++ сложнее для компиляции. И?
o Код на C++ после компиляции обычно занимает гораздо больше места. Так, в системе Cygwin программа после компиляции со стандартными флагами занимает 465 килобайт. Аналогичная программа на C после компиляции занимает меньше 9 килобайт.
1. А кто заставляет использовать std::cout? 2. Полностью зависит от компилятора!
* В Стандартной библиотеке шаблонов нет массивов размерности больше 1. Такие массивы приходится представлять как вектора векторов, вектора векторов векторов и т. д. Это неудобно и часто неэффективно.
Boost.multiarray есть. А стандартная библиотека обеспечивает только базовую функциональность.
* Любое поле класса или полностью доступно, или полностью недоступно извне класса. Невозможно сделать поле доступным только для чтения. ???
* Некоторые считают недостатком языка C++ отсутствие системы сборки мусора. Только некоторые так считают. Это не повод добавлять это в статью в раздел недостатки.
Ребята. Давайте называть НЕДОСТАТКАМИ то что нельзя исправить или обойти в той сфере применения для которой предназначен язык C++. А то можно придумать ОЧЕНЬ МНОГО, например: в стандартной библиотеке нет способа общения с базой данных MySQL...
Есть особенности языка, которые накладывают на него определенную область применимости. Например, в C# есть GC, и это для многих систем может быть серьезным "НЕДОСТАТКОМ", хотя на самом деле это особенность языка, которая определяет область применимости!
--Sergey Shandar 13:57, 25 июня 2006 (UTC)
o Некоторые считают неправильным приоритет операций: например, в выражении (a<b&c<d) сначала будет выполнена операция &.
Ну да, ведь есть еще операция && для булевских операция. А & это битовая операция, поэтому приоритет ОЧЕНЬ ДАЖЕ правильный!
Критика правомерна. Но пример был выбран действительно неудачно. В русском издании "Дизайн и эволюция С++" (ISBN 5-469-01217-4) указан более интересный и более часто встречающийся на практике пример: if(x & 0x77 == 0){} (параграф 2.6, страница 52) 91.90.36.250 15:26, 17 мая 2007 (UTC)
Сравнения языков и .т.п
Думаю, что не к месту оно здесь. Пусть это будет отдельные статьи - если очень хочется. А в статье о языке достаточно и необходимо указать область применимости и достоинства и недостатки В ЭТИХ ОБЛАСТЯХ. Все!
--150.101.25.90 05:19, 17 июля 2006 (UTC)
Поэтому и удалил из статьи сравнение C++ с Java. Это как сравнивать носорога с бульдогом. Можно, но не нужно. Совершенно разные подходы и области применимости.
--Sergey Shandar 05:21, 17 июля 2006 (UTC)
Очень к месту, особенно для энциклопедической статьи, зафиксировать все мнения за и против. Ява разрабатывалась позже с учетом недостатков языка С++, пока этот спор в памяти людской, надо его отразить. Тут не футбол и не политика :-), речь идет о технических решениях и о причинах по каким одни решения являются предпочтительнее других. Это нельзя умалчивать неон 07:41, 17 июля 2006 (UTC)
Дело в том, что у этих языков разные области применения. Да, в области высокоуровневого программирования Java дает серьезные преимущества. Но никак не на низком/среднем уровне. Статья перегжруженна. Лучще сделать отдельную статью. Так как, такие сравниния C++ и Java в статье о C++ дают ЛОЖНОЕ представление о языках. Почему бы тогда не сравнить с Python или c Nemerle. Почему Java? Java имеет отношения к C++ только частичной похожестью синтаксиса, семантика совершенно другая. Можно посмотреть, например, статью на английском языке. Нет там такого. Есть критика, и ссылки на критику. А не полный список сравнения C++ с Java и т.п.
--Sergey Shandar 04:04, 20 июля 2006 (UTC)
Сравнение языков программирования должно основываться на задачах решаемых этим языком. И успешных и не успешных проектах реализованных на этих языках. Например Линукс это Си, Microsoft Office это С++, OpenOffice это Java. А вдаваться в подробности синтаксиса, в рамках этой статьи, глупо. Лучше дать ссылку на описание синтаксиса. Ссылку на компиляторы свободные и не. Сказать что 98% приложений для платформы Windows написаны на Си++. И тогда споры, из абстрактных материй перейдут к количественным, и эта величина 98, опустится до 96 или до 95. Но смысл этого языка будет уже понятен даже школьнику.
--Дмитрий Лужецкий 21:49, 20 декабря 2007 (UTC)
Недостатки
То что сейчас в статье недостатки - это не недостатки, это критика. Это разные вещи.
--Sergey Shandar 03:59, 20 июля 2006 (UTC)
Размеры статьи
По моему, что то статья совсем испортилась, особенно после добавления этих огромных примеров и сравнений :-( Вообще, это кто нибудь читает? Я имею ввиду обсуждение. Или просто в статью добавляют все что угодно, как в помойную яму? Ау!
--Sergey Shandar 15:53, 1 августа 2006 (UTC)
Примеры можно подсократить - эти примеры ничего не дают. Достоиннства такие что хоть плачь. Их же можно объявить недостатками или залепухами неон 16:03, 1 августа 2006 (UTC)
Рад что ты откликнулся :-) (на ты/Вы?)
- Примеры большие убрать, если очень жалко (мне нет) - то в отдельную статью.
- Достоинства/недостатки. Здесь могу не согласитья (хотя бы с той же масштабируемостью), но это опять уйдет в войны. Предлагаю тогда оставить ТОЛЬКО раздел "Критику", без сравнения с Java и без недостатков/достоинств.
--Sergey Shandar 16:18, 1 августа 2006 (UTC)
Пример "Крестики нолики" убрал. --Sergey Shandar 16:22, 1 августа 2006 (UTC)
Давайте уберем отсюда учебник по ООП. Ну зачем в статье по языку С++ огромный раздел про инкапсуляцию? Имхо, достаточно сказать, что инкапсуляция поддерживается в С++ через модификаторы доступа public/protected/private/friend и дать ссылку на соответствующую статью. Ну и так далее. А то статью совсем читать невозможно. Enerjazzer 04:13, 8 сентября 2008 (UTC)
C# как новый язык
"...фирма Майкрософт предложила язык C# как новый язык, развивающий принципы C++..." Ну это вообще дезинформация! — Эта реплика добавлена с IP 195.218.214.217 (о) 12:20, 3 ноября 2006 (UTC)
Критика ООП
Не совсем по теме, но всё-таки. Проблемы старого подхода несколько неадекватны. Начнём с того, что функции Elem и ChangeElem бредовы. Тупое следование принципам ООП до добра не доводит, особенно если пишешь на не-ООП языке. Вызовы FreeArray и AllocArray ничем не хуже вызовов new и delete, защиту от двойного вызова можно сделать, ну а вообще программист должен знать, что где аллочится, а не уповать на компилятор, что тот в нужном месте что-то удалит или создаст. Другие функции для работы с Array - это то, что надо. Я никогда не понимал, почему у адептов С++ какая-то мания по ограничению доступа себя самого к внутренностям объектов? И потом ещё специальные методы для преодоления таких ограничений (типа friend). Соответственно, мешая менять val и len программист сам себе убивает эффективность программы - отсюда и неэффективные функции Elem и ChangeElem вместо ясных обращений к arr.val[i] (которые эффективны донельзя). Присваивание объектов работает в C и C++ одинаково - копированием памяти (если не перегружен оператор присваивания, что в C эквиванетно вызову функции копирования). Непонятно, как С++ эту проблему решает. В C давно известно, что использовать лучше указатель на структуру, чем её саму, то же самое делается в Delphi (там вообще объекты - изначально указатели) и в C++ (тут уже вручную, объектность С++ ни при чём). В общем, какие-то надуманные аргументы...А вообще, можно было бы более конструктивную критику устроить, если бы был код(ы) на C++, в котором(ых) эти проблемы бы наглядно решались (а то какое-то голословное утверждение, и больше ничего). LRN 14:45, 14 марта 2007 (UTC)
Начнём с того, что функции Elem и ChangeElem бредовы. - конечно, бредовы. О том и речь: если попытаться решить проблему (доступ к 1-мерному массиву с проверкой выхода за границу) на старом С - получатся бредовые функции.
- Интересно, зачем осуществлять доступ к элементам массива, которые не существуют (под существованием подразумевается нахождение в пределах границ массива), а если доступ осуществляется только к существующим элементам, то зачем проверка выхода за границу? Если делать проверку - то да, наверное действительно бред получается. И ещё...как аналогичный доступ будет осуществляться в C++? Там есть какой-то магический механизм, делающий функции Elem и ChangeElem класса Array быстрее?
- Кстати, надо оговориться, что лично я под "C" понимаю C++ без использования встроенного в C++ механизма классов (и всего, что с ними связано) и некоторых других чисто C++'сных вещей. Это скорее "грязный C", а не "чистый C". В частности, я допускаю применение передачи по ссылке (о ней см. ниже). — Эта реплика добавлена участником L.R.N (о • в) 11:00, 30 марта 2007 (UTC)
Тупое следование принципам ООП до добра не доводит, особенно если пишешь на не-ООП языке. - действительно, не доводит. Но указанный код на старом С не следует никаким принципам ООП.
- Имелось ввиду, что следуя принципам ООП он загоняет проверку границ внутрь класса Array, в то время как в C проверка границ обычно осуществляется перед обработкой массива. Для конструкции типа for (int i = 0; i < arr->len; i++) {} очень трудно выйти за границы массива. — Эта реплика добавлена участником L.R.N (о • в) 11:00, 30 марта 2007 (UTC)
Вызовы FreeArray и AllocArray ничем не хуже вызовов new и delete - хуже, в тексте подробно объяснено чем.
защиту от двойного вызова можно сделать - действительно можно, но только за счёт дальнейшего усложнения класса. В С++ такого усложнения не требуется. Другие защиты сделать вообще невозможно.
- Говоря об уложнениях - советую посмотреть код, который выполняется при вызове функции new. Кстати, у меня назрел вопрос: как в C++ выделить некоторый участок памяти (допустим - буфер в виде массива unsigned char'ов)? Как это делается с помощью new?
- С другой стороны, зачем она нужна, эта защита? Неправильно написанную программу она не исправит, а отдебагить повторный вызов FreeArray - задача относительно простая (программа будет падать во время вызова, искать ничего не надо). А в C++ останется двойной вызов delete (или чем там будет удаляться класс), ибо защита. — Эта реплика добавлена участником L.R.N (о • в) 11:00, 30 марта 2007 (UTC)
а вообще программист должен знать, что где аллочится - знать он действительно должен. И именно в С++ он знает: все функции, которые делают аллокации, описаны в разделах protected и private данного класса (если класс описан хорошо). В старом С он знать, что где аллочится, в принципе не может (кроме маленьких программ). В типичной современной программе - десятки или сотни файлов, сотни тысяч строк кода, а её авторы - десяток или пара десятков программистов, писавших её на протяжении нескольких лет, причём часть уже перешло в другие фирмы. Там обязательно будут места, где что-то аллочится вне описания класса. Причём таких мест будут десятки в лучшем случае, сотни в типичном, как бы программисты ни старались поддерживать дисциплину. Именно потому что программист должен знать, что где аллочится, ООП и нужен (хотя и не только поэтому).
- Незнание кода, над которым ведётся работа. Программист должен знать, как работает тот модуль, в пределах которого он пишет; и в пределах этого модуля правильно распоряжаться памятью. Если что-то выходит за пределы модуля - оно выходит по определённым правилам, которые заранее оговорены. Поэтому существуют и процветают C'шные библиотеки (как пример модульного кода). Естественно подразумевается, что остальные модули работают как надо, всё-таки и в C++ будет очень плохо искать неправильно описанный класс где-то в другом куске программы, писавшемся 10 лет назад. — Эта реплика добавлена участником L.R.N (о • в) 11:00, 30 марта 2007 (UTC)
а не уповать на компилятор, что тот в нужном месте что-то удалит или создаст - автоматическое удаление и создание гораздо лучше, чем делать то же вручную, совершая ошибки.
- Проще найти ошибку в собственном коде, чем найти, почему вызывает ошибку в твоём коде другой код, созданный компилятором (причём сам факт существования этого второго кода нужно знать, т.е. нужно точно знать, что и где будет сгенерировано, и как оно работает). — Эта реплика добавлена участником L.R.N (о • в) 11:00, 30 марта 2007 (UTC)
Я никогда не понимал, почему у адептов С++ какая-то мания по ограничению доступа себя самого к внутренностям объектов? - доступ не ограничивается: всегда можно описать новую функцию-член или функцию-френд. Но все такие функции будут собраны в одном месте, а не разбросаны по сотням тысячам строк кода. Это решает и проблему дублирования опасных функций: когда все опасные функции собраны в одном месте, они дублироваться не будут.
- В каком месте? В описании класса? Ну, можно все прототипы описать в одном месте - будет то же самое. Нет, конечно можно писать "от души", следуя по пятам за работой мысли, в результате чего код представлят из себя огромную кучу непонятно как связанных функций. А можно сначала прикинуть структуру программы, классов, и писать в соответствии с этим. И прямой доступ к данным будет лишь одним из инструментов (и будет применяться там, где он необходим). В основном это вопрос вменяемости программиста, хотя конечно проще ограничить программиста средствами языка. — Эта реплика добавлена участником L.R.N (о • в) 11:00, 30 марта 2007 (UTC)
И потом ещё специальные методы для преодоления таких ограничений (типа friend). - см. выше. Доступ к защищённым членам не ограничивается - но все такие доступы должны быть указаны в одном месте. Для того и нужен механизм френдов, чтобы не ограничивать доступ к внутренностям объектов. Без френдов он был бы ограничен.
Присваивание объектов работает в C и C++ одинаково - копированием памяти (если не перегружен оператор присваивания, что в C эквиванетно вызову функции копирования). - неправильно. Присваивание в современном С++ работает вызовом копи-конструктора. В классе class A {std::vector<float> b; int c;} не нужно описывать оператор присваивания или явно описывать копи-конструктор.
- Не понял...т.е. описывать копи-конструктор не нужно, но он будет работать. Что, опять компилятор сгенерирует? И как этот копи-конструктор будет работать? Уж не память ли будет копировать? Или вызовет копи-конструктор vector'а, который таки был написан? Тогда крыть нечем, кроме как написанием вручную функции копирования для класса А и вызова её вместо присваивания. Единственное, что портит прекрасную картину автоматически-рекурсивно-иерархического вызова копи-конструкторов - возможная необходимость дебагить эти вызовы. — Эта реплика добавлена участником L.R.N (о • в) 11:00, 30 марта 2007 (UTC)
Непонятно, как С++ эту проблему решает. - какую проблему?
В C давно известно, что использовать лучше указатель на структуру, чем её саму - известно. При этом возникает куча проблем: можно передать неправильный указатель; нужно вручную писать амперсанд и звёздочку; можно забыть то или другое или написать неправильное количество звёздочек (конструкции с двумя и более звёздочек в старом С встречаются постоянно).
- См. ниже. — Эта реплика добавлена участником L.R.N (о • в) 11:00, 30 марта 2007 (UTC)
то же самое делается в Delphi (там вообще объекты - изначально указатели) - рад за Delphi.
- Я тоже. — Эта реплика добавлена участником L.R.N (о • в) 11:00, 30 марта 2007 (UTC)
и в C++ (тут уже вручную, объектность С++ ни при чём) - это в С вручную: пишутся амперсанды при каждом вызове и звёздочки или -> при упоминании параметра. В С++ амперсанд пишется один раз: в списке параметров. И правильно пишется: иногда (редко) надо передать объект не по ссылке. А ООП тут действительно ни при чём.
- В C не пишутся амперсанды, в C пишутся звёздочи при объявлении переменной-указателя на объект. То же самое делается в C++. Потому что new возвращает указатель (без new объекты будут создаваться там, где они объявлены в коде). Так что все объекты хранятся в виде указателей на объекты (за редким исключением), а обращение к параметрам - с помощью -> (кстати, что в нём плохого?). А если после этого вызывать функцию с амперсандом, то как ей передавать объект, который известен только по указателю на него? Дереференсить указатель на объект и послать объект, чтобы компилятор сам сформировал указатель на объект и перадал в функцию? Как-то странно получается. Не, вообще аперсанд удобен - но как раз не для объектов, а для других данных, которые хранятся не в виде укзателей на области памяти, а просто так. — Эта реплика добавлена участником L.R.N (о • в) 11:00, 30 марта 2007 (UTC)
В общем, какие-то надуманные аргументы...А вообще, можно было бы более конструктивную критику устроить, если бы был код(ы) на C++, в котором(ых) эти проблемы бы наглядно решались (а то какое-то голословное утверждение, и больше ничего). - см. выше. Да вы сами написали аргументы против старого С: и что программист должен знать, что где аллочится (это хорошо известный и убийственный аргумент против С), и что в С часто появляются бредовые функции. --Urod 15:52, 28 марта 2007 (UTC)
- Нет, конечно есть области, где без ООП не обойтись, всё-таки наследование в C очень плохо реализуется, да и весь "высший пилотаж ООП" - тоже. Но, простите, обычную модульность и инкапсуляцию (понимая под инкапсуляцией группировку данных и функций в одной сущности) можно и так сделать...Зачем огород городить? Вспоминается бородатый прикол про эволюцию программиста и программу Hello World. — Эта реплика добавлена участником L.R.N (о • в) 11:00, 30 марта 2007 (UTC)
Подводя итоги.
- Программист должен знать ту часть кода, в пределах которой он в данный момент работает. Если она слишком большая, чтобы её понять - значит надо разбить её на N связанных частей кода и делать их по одной.
- Связь между частями кода придумывается (оговаривается) заранее. Если речь идёт об уже существующем модуле, то надо читать документацию (читать её придётся всё равно, так что лучше раньше, чем позже), ибо сходу непонятно, какие "методы" есть у "класса" (принадлежность функции к "классу" в C не очевидна). Если этого не делать, то естественно начинаются "походы в глубину" и излишнее копание во внутренностях "объектов".
- Проще найти собственную ошибку в C'шном коде, чем искать собственную ошибку, косвенно вызванную в коде, автоматически сгенерированном в С++.
P.S. Неправильно назван раздел. Я критикую С++, а не ООП. ООП не виновато, что его применяют где попало и как попало.
LRN 11:00, 30 марта 2007 (UTC)
Препроцессор
Достоинства языка C++
...
C++ имеет мощный препроцессор, унаследованный от C. Но, как и любой другой мощный инструмент, требует осторожного использования.
...
Недостатки языка C++
...
Препроцессор С++ (унаследованный от С) очень примитивен.
Помоему из этих двух утверждений надо выбрать что-то одно(а второе убрать). Либо примитивен, либо мощен. По-моему, cpp действительно примитивен (сравнить например с m4) Страуструп отзывался о препроцессоре отрицательно. К тому же препроцессор связан с языком очень слабо( например, препроцессор обрабатывает MACRO(std::pair<int,int>) как макрос с двумя параметрами --- первый это pair<int , а второй это int>, хотя это не желательно для многих макросов).
Вообщем если никто не будет возражать, препроцессор будет вычеркнут из достоинств языка. — Эта реплика добавлена с IP 91.90.36.250 (о) 16:19, 17 мая 2007 (UTC)
- Наличие препроцессора - достоинство. Убогость этого препроцессора - недостаток. Enerjazzer 02:36, 3 июля 2009 (UTC)
Критика и компилятор gcc
Считаю, что нет необходимости публиковать длинные сообщения об ошибке gcc. Во-первых, это больше критика gcc, во-вторых, приведённая ошибка не добавляет энциклопедичности, в третьих, она занимает оцень большое место по ширине, что добавляет прокрукту по горизонтали даже при разрешении 1280 --Pavel Zubkov 20:39, 10 января 2008 (UTC)
Си++ не включает в себя Си
Несмотря на то, что большая часть кода Си будет справедлива и для Си++, Си++ не является надмножеством Си и не включает его в себя.
Си++ действительно не является надмножеством стандарта C99, однако же C89 является его подмножеством, так действующий на данный момент стандарт ANSI/ISO языка Си++ (принятый в 1998 г.) построен на основе стандарта C89.
Существует и такой верный для Си код, который неверен для Си++.
Опять же, это касается стандарта C99.
Например, следующий фрагмент кода корректен с точки зрения Си, но некорректен с точки зрения Си++:
typedef struct mystr { int a; int b; } mystr;Дело в том, что в Си идентификаторы структур (тэги структур), то есть идентификаторы, используемые при описании структуры в качестве имени структуры, являются сущностями отдельного вида, имеющими обособленное пространство имён, тогда как в Си++ идентификатор структуры представляет собой попросту её тип. Таким образом, в языке Си вышеприведённый фрагмент вводит структуру
mystr
и новый типmystr
, тогда как в Си++ этот же фрагмент будет воспринят как попытка дважды описать тип с именемmystr
.
Нет, в этом фрагменте кода всего лишь определена переменная структурного типа mystr
с именем mystr
. Этот код верен для обоих языков и ошибки здесь нет. Отличие состоит в том, что в Си, в отличие от Си++, имя структуры не определяет в полной мере его типа.
typedef struct mystr {
int a;
int b;
};
mystr mystr; //ОК для Си++, ошибка в Си
В Си++ mystr
в полной мере определяет имя типа и его можно использовать для объявления переменных. В Си же mystr определяет лишь тэг(идентификатор) структуры. Поэтому в Си при объявлении определени переменной тэг необходимо предварять ключевым словом struct
.
struct mystr mystr;// Теперь приемлимо и для Си
Более того, код, верный для обоих языков, может давать разные результаты в зависимости от того, компилятором какого языка он оттранслирован. Например, следующая программа печатает «С», если компилируется компилятором Си, и «С++» — если компилятором Си++. Так происходит из-за того, что символьные константы в Си (например 'a') имеют тип int, а в Си++ — тип char.
#include <stdio.h> int main() { printf("%s\n", (sizeof('a') == sizeof(char)) ? "C++" : "C"); return 0; }
Можно было просто указать, что „символьные константы в Си (например 'a') имеют тип int, а в Си++ — тип char“
217.146.246.8 14:11, 3 мая 2008 (UTC)Vanuan
А как насчёт следующего?
int main ()
{
int new = 5;
return 0;
}
Это тривиальное различие основанное на расширении C++'ом множества ключевых слов C. Но не единственное. Мне как-то захотелось реализовать в C++ списки с принудительной связью. Арифметика указателей и преобразования типов, которые работали в C, в C++ работать перестали. Без static_cast обойтись мне не удалось. Это, быть может, не стоит относить к различиям синтаксиса, но именно это делает C несовместимым с C++. Или C++ несовместимым с C, но это уже не столь важно. зы. извиняйте мою лень, но если вам хочеться больше примеров, то возьмите какую-нибудь C-программу (тот же list.h из ядра linux) и попробуйте прогнать её через компилятор C++. 91.190.87.137 08:42, 13 апреля 2009 (UTC)
Статья должна быть информативнее
А как же к примеру компиляция программ на C++ для разных режимов ? Где разница и в чём к примеру для создания win32 based приложения и DOS mode приложения, какая роль MFC и вообще есть ли хоть что-либо об этом ? 79.111.9.190 14:10, 19 ноября 2008 (UTC)MisterC++
- Какое отношение прикладная библиотека MFC имеет к самому языку? Она, вроде, в стандарт языка не встроена, так что ей тут не место, развечто в обзем списке известных библиотек, если такой вообще нужен, конечно. Enerjazzer 02:38, 3 июля 2009 (UTC)
inline
«inline является не директивой, а рекомендацией компилятору — компилятор не обязан реализовывать подстановку тела для inline-функций, но может, исходя из заданных критериев оптимизации, выполнять подстановку тела для функций, которые не объявлены как inline.»
По-моему последнего "НЕ" не должно быть Wiki vlad 08:15, 3 октября 2009 (UTC)wiki_vlad
- Компилятор может и без объявления inline делать это, поэтому всё правильно.--Angstorm 20:01, 3 октября 2009 (UTC)
объясните мне тогда зачем этот инлайн нужен вообще? Если и без него компиллятор может подставлять тело функии, и с ним может не подставлять? Wiki vlad 13:02, 5 октября 2009 (UTC)
- Явное или неявное определение функции как inline изменяет действие правила одного определения на эту функцию.--achp 13:25, 5 октября 2009 (UTC)
А что такое "действие правила одного определения"?--Wiki vlad 12:07, 7 октября 2009 (UTC)
- Видимо он опечатался и имел ввиду "оного".--Angstorm 22:05, 7 октября 2009 (UTC)
- Видимо, вам обоим надо ознакомиться с предметом обсуждения, то есть, с языком Си++. Правилу одного определения посвящён раздел 3.2 действующего стандарта.--achp 05:52, 8 октября 2009 (UTC)
- Всё равно не понятно. Зачем Инлайн нужен если компилятор сам решает в обоих случаях подставлять или вызывать. «inline является не директивой, а рекомендацией компилятору — компилятор не обязан реализовывать подстановку тела для inline-функций, но может, исходя из заданных критериев оптимизации, выполнять подстановку тела для функций, которые не объявлены как inline» Особенно меня удвляет вторая часть предложения. Даже не инлайн функции компилятор может инлайнить? Всё завсит не от программиста а от компилятора? В учебнике по с++ например [1] ничего подобного не утверждается. Все очень просто: инлайн — подставляется, не инлайн — вызывается. Может быть это учебник по старому стандарту? А где последний стандарт можно почитать? Wiki vlad 06:36, 8 октября 2009 (UTC)
- Ссылки на действующий стандарт нет, но есть ссылка на черновик готовящейся новой версии стандарта. Там раздел, посвящённый правилу одного определения, имеет всё тот же номер, 3.2 (к inline имеет отношение абзац 3).--achp 08:31, 8 октября 2009 (UTC)
- Что касается оптимизации, то её логика лежит за пределами определения языка. Стандарт определяет только семантику языка. Спецификатор inline был изначально предназначен для того, чтобы воздействовать на оптимизатор, однако это воздействие только рекомендательное. Во-первых, оптимизатору встраивание функции может оказаться просто «не по зубам». Например, рекурсивную функцию встроить невозможно в принципе. Во-вторых, современные оптимизаторы настолько умные и изощрённые, что могут принимать решение сами, не полагаясь на рекомендацию пользователя. Зато тот эффект, который спецификатор оказывает на семантику программы, является обязательным.--achp 08:31, 8 октября 2009 (UTC)
- Всё равно не понятно. Зачем Инлайн нужен если компилятор сам решает в обоих случаях подставлять или вызывать. «inline является не директивой, а рекомендацией компилятору — компилятор не обязан реализовывать подстановку тела для inline-функций, но может, исходя из заданных критериев оптимизации, выполнять подстановку тела для функций, которые не объявлены как inline» Особенно меня удвляет вторая часть предложения. Даже не инлайн функции компилятор может инлайнить? Всё завсит не от программиста а от компилятора? В учебнике по с++ например [1] ничего подобного не утверждается. Все очень просто: инлайн — подставляется, не инлайн — вызывается. Может быть это учебник по старому стандарту? А где последний стандарт можно почитать? Wiki vlad 06:36, 8 октября 2009 (UTC)
Примеры
Господа, а кто-нибудь вообще читал примеры? Либо я чего-то не понимаю, либо в 5 примере ошибка, сейчас там так:
transformer odds(int n) { return transformer(counter(n), odd); }
transformer squares(int n) { return transformer(counter(n), square); }
но разве должно быть не так:
transformer odds(int n) { return transformer(counter(n), odd(n)); }
transformer squares(int n) { return transformer(counter(n), square(n)); }
80.64.109.156 11:16, 11 февраля 2010 (UTC)Александр
- На самом деле, из приведённого примера нельзя сказать, что там должно передаваться, поскольку тип transformer является шаблоном, определённым где-то в заголовочных файлах, интерфейс нам не показан, и потому нам неизвестно, какие параметры и с какими типами там следует передавать. А если пытаться анализировать смысл этого кода, то, по идее, там нужны именно функции (указатели на них), а не их один конкретный результат, иначе код теряет смысл. PS: А вообще, этот недавно добавленный пример, вероятно, следует либо переделать, упростив, либо вообще убрать, поскольку он не самодостаточен. Я уже не говорю про внешнюю ссылку, которая туда затесалась. -- AVBtalk 13:09, 11 февраля 2010 (UTC)
- Наличие в примере функций int odd(int i) и int square(int i) все таки дает мне основание полагать, что их нужно использовать, посему, соглашусь с Вами, и предложу внести изменения так:
transformer odds(int n) { return transformer(counter(n), &odd(n)); }
transformer squares(int n) { return transformer(counter(n), &square(n)); }
Спасибо за ответ. 80.64.109.156 13:47, 11 февраля 2010 (UTC)Александр
- Во-первых, применение операция взятия адреса к именам функций излишне. Во-вторых, ваш вариант некорректен, поскольку пытается взять адрес от результата функции, а не самой функции. Вы здесь, видимо, решили повысить читабельность за счёт "изгаляний" над синтаксисом. Это бессмысленно и даже вредно, это попытка заменить (отсутствующий) КОММЕНТАРИЙ с пояснением конструкциями-идиомами из других языков. Это всё равно, как заменять конструкции вроде "a=b[++i]" на более "простые" конструкции вроде "i=i+1; a=b[i]" - такие попытки всего лишь показывают, что язык вам всё ещё недостаточно привычен. -- AVBtalk 14:05, 11 февраля 2010 (UTC)
- Я не пытался повышать читабельность. Мои познания в с++ на начальном уровне, поэтому я и решил почитать данную статью. И этот пример меня запутал. Я просто хочу понять как будет правильно. Напишите, пожалуйста, верный вариант примера (в предположении, что кусок кода все же самодостаточный).
80.64.109.156 14:44, 11 февраля 2010 (UTC)Александр
- верный вариант примера - тот пример, который есть, как я предполагаю, верен. Проблема только в его несамодостаточности (данный конкретный пример нельзя рассматривать в отрыве от заголовков boost, которые нам не показаны). И я сейчас не готов убрать этот пример или предложить ему замену, поскольку для этого мне нужно пересмотреть всю статью, чтобы оценить, нужен ли этот раздел и нужен ли в нём такой пример. То, что у вас с этим примером возникли проблемы, может свидетельствовать за то, что в таком виде он в статье не нужен. (Учтите, речь ведь не об учебнике, а о кратком обзоре, в котором должны даваться ссылки на внешние источники с более подробной, в том числе и учебной информацией). -- AVBtalk 20:22, 15 февраля 2010 (UTC)
- Энциклопедия - это не учебник. Согласен добавить пояснения. Александр Чуранов
- Пример добавил я. Отвечу на все вопросы. Он компилируется и работает в том виде, в котором изначально был добавлен, так что править точно ничего не нужно. Цель добавления примера - продемонстрировать, что на С++ возможно и такое написание, радикально отличающееся от предыдущих "упрощёнок". Это необходимо, чтобы у читателя было более полноценное представление о языке. Александр Чуранов
Динамический полиморфизм
Во фрагменте кода, посвящённом динамическому полиморфизму, убрал абсолютно лишние спецификаторы функций virtual в производных классах. Они только захламляют код и совершенно не нужны. Надеюсь, всем ясно, что объявлять функцию как virtual имеет смысл только в базовом классе. ;) Stalker 09:57, 4 ноября 2010 (UTC)
Так всё-таки C или Си?
Поскольку даже дети лейтенанта Шмидта заключили между собой конвенцию, предлагаю и авторам сей статьи (статей) установить соглашение: либо везде писать англоязычное название языка C, либо русскоязычное Си. В известных мне переводных книгах Бьярна Страуструпа по C++ переводчики выбрали именно англоязычный вариант C. Имхо предпочитаю также англоязычный вариант из уважения к оригиналу. Аргументы в пользу русскоязычного варианта вроде возможной путаницы из-за сходства с предлогом "С" считаю несерьёзными: человек, изучающий C/C++, прекрасно разберётся, где предлог, а где название языка. Иначе ему вообще нет смысла браться за слишком сложный для него предмет. ;) Stalker 10:24, 4 ноября 2010 (UTC)
- Статья в википедии пишется для широкого круга читателей (большинство из которых вообще не программисты), а не для изучающих C/C++. Mathaddict 06:52, 28 ноября 2010 (UTC)
Ошибка в правильном произношении C++.
Ошибка в правильном произношении C++.
Добрый день. Хочу поправить. С++ читается(прозиносится) как "Си плас плас" а не "Си плюс плюс".
С уважением Иван. 93.72.161.159 13:35, 1 декабря 2010 (UTC)
- Поправлять не надо - на русском говорят "плюс плюс". Добавляйте, с примечанием, что так произносится в английском языке. -- X7q 13:53, 1 декабря 2010 (UTC)
Уберите Шилдта из списка рекомендованной литературы
В буржунете даже есть такое слово "Bullshildt" 81.195.20.101 18:26, 2 декабря 2010 (UTC)Vasya
Макросы
# Макросы (#define) являются мощным, но опасным средством. Они сохранены в C++ несмотря на то, что необходимость в них, благодаря шаблонам и встроенным функциям, не так уж велика[источник не указан дцать дней].
Можно сослаться на "Герб Саттер, Андрей Александреску. Стандарты программирования на С++" (http://ru.wikipedia.org/wiki/%D0%A1%D0%BB%D1%83%D0%B6%D0%B5%D0%B1%D0%BD%D0%B0%D1%8F:BookSources/9785845903518). --193.232.174.16 13:05, 18 января 2011 (UTC)