Предположим, я ограничен в использовании C ++ средой в проекте. Хорошо ли предотвращать использование некоторых языковых функций, которые есть в C ++, но нет в Java (например, множественное наследование, перегрузка операторов)?
Я думаю, что причины:
- Поскольку Java новее, чем C ++, если Java не предоставляет возможности, которые есть в C ++, это означает, что эта функция не является хорошей, поэтому мы должны избегать ее использования.
- Код C ++ со специальными функциями C ++ (например, функции-друзья, множественное наследование) может поддерживаться или проверяться только программистами C ++, но если мы просто напишем C ++, как Java (без специфической для языка C ++ функции), код может поддерживаться или проверяться обоими C ++ и Java программисты.
- Вас могут попросить преобразовать код в Java когда-нибудь
- Код без специфических особенностей C ++ обычно более удобен в обслуживании
- Каждая особенность языка C ++ (например, множественное наследование) должна иметь альтернативы для реализации в Java. Если это не так, значит, шаблон проектирования или архитектура кода проблематичны.
Это правда?
java
c++
code-quality
ggrr
источник
источник
volatile
, доступ к элементам закрытого класса пакета, рефлексию / самоанализ, блоки finally, проверенные исключения и т. Д.? В целом вопрос вроде не имеет особого смысла ... C ++ и Java внешне похожи, но в конечном итоге очень разные языки.SomeObject a = previousObject;
делает очень разные вещи в Java и C ++. В Java это копирует ссылку, в то время как в C ++ это копирует объект. В Java изменения вa
также влияют на предыдущий объект. В C ++ у вас есть два отдельных объекта.Ответы:
Нет. Это ужасно и ужасно неправильно.
источник
operator<<( ostream &, T const & )
обычно реализуется черезfriend
. Вот в чем проблема с общими заявлениями о том, что является хорошей языковой функцией, а что плохой: они являются хорошим советом, кроме случаев, когда они не ...То, что на первый взгляд синтаксис выглядит схожим, не означает, что эти два языка совместимы.
1, 4 и 5 - это действительно один и тот же вопрос:
Теперь я не фанат C ++, но говорить: «Код без специфических функций C ++ обычно более удобен для сопровождения» - просто смешно. Вы действительно верите, что в Java все было правильно, и все полезные функции были приняты, игнорируя все плохие? Вы действительно верите, что есть что-то, что обычно является «плохой» или «хорошей» функцией? Если есть, почему у нас нет одного языка, который был бы просто хорош? И нет, Java, конечно , не тот язык. Означает ли это, что Java и C ++ бесполезны? Конечно, нет.
Что если ваши лидеры решат, что вы собираетесь портировать на C #, а не на Java? C # поддерживает не только переопределение операторов, но также и значение по умолчанию - если вам нужно, чтобы люди использовали, например,
obj.Equals(obj2)
вместо тогоobj == obj2
, чтобы люди постоянно совершали ошибки. Даже если вы придерживаетесь только общих черт двух языков, существуют разные ожидания , другая культура. Если вы делаете что-то подобноеif (myField == null)
в C ++, люди сразу увидят, что вы новичок. Если вы используетеif (null == myField)
в C #, люди увидят, что вы еще не являетесь родным C # - причин, по которым разработчики C научились использовать «перевернутый» вариант, больше не существует в C #.Используя вашу логику, мы должны были придерживаться машинного кода или сборки или COBOL, потому что зачем переходить на что-то вроде Pascal, когда оно просто добавляет новые функции, которые ваши программисты должны будут изучить? Зачем нам когда-либо использовать что-то вроде SQL, когда у него даже нет циклов ? Зачем нам когда-либо использовать что - то еще, кроме SQL, если в SQL нет циклов, а в X есть?
Код C ++ определенно не может поддерживаться программистами Java. Я не могу понять, откуда у вас эта идея - что именно остается, когда вы ограничиваете C ++ только функциями, которые работают точно так же, как в Java? Вы даже не будете получать вызовы методов - даже вызовы функций . Опять же, то, что оба языка используют фигурные скобки, не означает, что языки в любом случае взаимозаменяемы.
Преобразование Java-подобного кода C ++ будет чрезвычайно подвержено ошибкам независимо от того, что вы делаете. Просто слишком много различий. Если вам нужно переписать ваше приложение на другом языке, подумайте о разумных способах модульности всего, чтобы можно было заменить детали, не разбивая их целиком. Но, в конце концов, YAGNI - что бы вы ни делали, создание кода, готового к конвертации в Java, будет стоить немалых затрат. Это время, скорее всего, лучше потратить на добавление или улучшение ваших функций.
Мы используем разные языки, потому что они дают нам другой набор инструментов для решения проблем. Если вам нужны исполняемые файлы, которые работают «везде», используйте Java. Если вам нужен код, который компилируется «везде», C ++ работает нормально. Если вам нужен код, который легко понять и проанализировать, используйте LISP или что-то еще. Но я могу сказать вам одну вещь - написание кода на одном языке, как если бы вы писали его на другом языке, всегда является ошибкой, и вы будете страдать. Не говоря уже о том, что когда вы на самом деле нанимаете парня из C ++, он запускает вторую секунду, когда видит «совместимый с Java» код. И ... парень из Java собирается сделать то же самое. Знаете, даже "зная" и C ++, и Java, я бы работал как в аду :)
Я действительно должен был работать над (простым) кодом C, написанным разработчиком Pascal, который, казалось, думал так же, как и вы. Он использовал
#define
s, чтобы переопределить C, чтобы он выглядел и чувствовал себя как Паскаль, в комплекте с такими вещами, как «BEGIN переводится в {». Результат был довольно предсказуемым - код, который не могут понять ни C, ни разработчики Pascal, и полон ошибок, которые были результатом утечки «абстракции» Pascal поверх C. И Pascal и C практически идентичны с сегодняшней точки зрения. Даже переход на C <-> C ++ намного больше разницы, и это все еще арахис в нечто вроде C ++ <-> Java.источник
myFunc()
против(myFunc)
), и на это есть очень веская причина. Языки на основе LISP по-прежнему очень популярны, особенно среди математиков и физиков. Главное в том, что языки LISPy очень незнакомы современным программистам в стиле C, но вряд ли это причина игнорировать это. Scheme, Clojure и, в некоторой степени, языки на основе ML (OCaml, F # ...) действительно очень LISPy.if (myField == null)
asif (myField = null)
, которая прекрасно скомпилирует C / C ++, но, вероятно, не сделает то, что вы хотели. С другой стороны,if (null = myField)
выдаст ошибку, так как вы не можете присвоить константу.Я отвечу на ваши вопросы по порядку.
Да, любая функция, отсутствующая в Java, является анафемой на жестком диске. Он должен быть записан из вашей базы кода. Те, кто не подчиняются, будут подвергнуты преследованиям, а их души использовались, чтобы успокоить богов.
Если вы сомневаетесь, напишите код для наименее компетентного члена вашей команды. Код читается гораздо чаще, чем написано, а код, который настолько умён, насколько вы можете написать, слишком умён для чтения. Обзоры кодов, которые ваш персонал на стойке регистрации не поймет, должны быть отклонены. Чтобы помочь, научите их программировать в Visual Basic 2.0 на выходных, а затем эмулируйте их стиль кодирования на любом языке, который вы используете.
Правда! Но зачем останавливаться на Java? Вас могут попросить преобразовать код в базовый, ассемблер и / или Perl один день. Поскольку на каждом языке есть интерпретаторы perl, просто напишите свою программу в виде длинной строки perl и добавьте в нее аргументы на выбранном языке.
Теперь, когда вам нужно сменить язык, просто перепишите код, заключающий строку perl.
Это правда, что код, который использует меньше функций, легче поддерживать. И поскольку все языки эквивалентны машине Тьюринга, а машина Тьюринга обладает наименьшим количеством функций из всех языков программирования, приведенный выше интерпретатор perl фактически запускает машину Тьюринга (ленту и все), которая решает вашу проблему.
Особые возможности языка C ++ на самом деле полезны. Поскольку они не Ява, они анафема, и те, кто использует это, могут быть заклейменными еретиками. Если бы в C ++ не было этих языковых функций, вы бы не смогли найти тех, которыми нужно пожертвовать. Особенности языка C ++ решают проблемы!
Посмотрите, C ++ и Java имеют различный набор возможностей. Программирование на пересечении C ++ и Java приводит к коду, который отбрасывает большинство преимуществ обоих языков.
Java была разработана частично как реакция на некоторые злоупотребления функциями C ++. Это не означает, что реакция была оправданной, особенно спустя годы, когда функции стали более зрелыми.
Вы можете делать ужасные вещи с перегрузкой оператора; но ни один язык не может помешать написанию ужасного кода на этом языке, если только он не помешает написанию всего кода на этом языке.
И вы также можете делать очень элегантные вещи с перегрузкой оператора. Простые вещи, такие как комплексное число или матричный класс, который работает как комплексное число или матрица.
Предупреждение об использовании функций C ++, недоступных в Java, следует рассматривать с осторожностью. То, что ваш нынешний набор разработчиков с их текущим уровнем квалификации не понимает функцию, не означает, что ее никогда не следует использовать; в то же время, просто потому, что вы можете использовать функцию, не значит, что вы должны. Однако в магазине с большим количеством Java вероятность того, что сопротивление будет сильнее, чем должна быть против функций, не относящихся к Java.
Преобразование кода между языками лучше всего проводить с переписыванием, независимо от того, насколько они структурно похожи. Любая попытка сделать это без такой переписки с треском провалится.
Многие особенности C ++ - это чудеса обслуживания. Стирание типа (например
std::function
) позволяет вам отделить иерархии, что уменьшает зависимости. Интеллектуальные указатели и детерминированные времена жизни, а также RAII уменьшают неожиданности времени выполнения и убирают шаблоны ресурсов с пути. Тяжелые статические проверки типов означают, что код не компилируется, а не работает. Дополнительные модули уменьшают дублирование кода. ADL позволяет независимое независимое расширение интерфейсов между иерархиями типов. Лямбда позволяет вам написать код рядом с тем, где он используется. Пересылка и перемещение уменьшают количество копий и делают программирование в функциональном стиле (без побочных эффектов) эффективным. Перегрузка оператора снижает шум в линии и делает код более похожим на математическую модель, которую он моделирует.Остерегайтесь ямы Тьюринга. Вы можете реализовать все на любом языке (включая необработанную машину Тьюринга с лентой), но это не значит, что вы должны это делать . Эмуляция функций C ++ с использованием конструкций Java-esque в C ++ - ужасная идея; это приведет к не поддерживаемому коду, который никто не сможет прочитать или понять.
Вы можете черпать вдохновение из конструкций Java и переносить их на C ++. Я большой поклонник использования возможностей языка Python и их реализации в C ++, потому что мне нравится синтаксис. Но это не значит, что я пишу свои методы класса как статические методы, принимающие явное «я», а затем пишу оболочку, которая перенаправляет вызов нестатического метода.
Современный C ++ не так уж похож на язык, который эмулирует и отвергает Java. Не зацикливайтесь на особенностях одного языка; нет "одного истинного языка". Узнайте о новых языках и их особенностях, и впитайте их отличительные особенности.
источник
Я просто отвечу на твои причины:
источник
delete
.delete
. Насколько я помню, по крайней мере в одном из этих случаев динамическое распределение (new
) также не требовалось.make_shared
.В Java есть функции, которых нет в C ++, такие как встроенный, быстрый и надежный сборщик мусора, иерархия объектов с одним корневым объектом и мощный самоанализ.
Другие функции Java предназначены для совместной работы с эксклюзивными функциями Java, и многие из упущений Java функций C ++ возможны, потому что новые функции восполняют недостаток. Например, Java не имеет выделенных в стек объектов с детерминированными деструкторами, но имеет наконец блоки (и try-with-resources начиная с Java 7) и сборщик мусора, чтобы восполнить этот недостаток.
C ++ не имеет окончательно блоков или сборки мусора. Если вы не используете деструкторы, потому что они не существуют в Java (я не считаю финализаторы), вы находитесь на уровне C управления ресурсами (т.е. все вручную), за исключением того, что вы не можете даже сгруппировать свою очистку в блок очистки, к которому вы переходите, потому что в Java тоже нет перехода. Вы действительно думаете, что это улучшает ремонтопригодность?
Java имеет всеобъемлющую иерархию объектов, в которой каждый класс в конечном счете является производным от Object, и несколько примитивных типов могут быть автоматически упакованы в такие классы. Это позволяет писать контейнеры объектов один раз, чтобы хранить указатели на объект. Java 5 представила дженерики, которые избавляют от приведений, которые требуются в таких контейнерах, но по-прежнему компилируются практически в один и тот же код.
C ++ не имеет такой иерархии. Чтобы облегчить написание контейнеров, которые работают для нескольких типов, вы используете шаблоны, которые представляют собой чертежи, которые создаются компилятором по мере необходимости для разных типов. Запретите ли вы использование шаблонов (и макросов) и пойдете по пути C: либо снова и снова пишите один и тот же код контейнера для разных типов, либо используйте указатели void? (Подождите, у Java нет пустых указателей!) Вы уверены, что это повысит удобство обслуживания?
Приличный язык имеет множество функций, которые предназначены для совместной работы. Запретив функции из языка A, поскольку у языка B их нет, вы наносите ущерб языку A, потому что вы не добавляете в то же время функции из B, которые делают B единым целым.
Это не значит, что вы не должны ограничивать разрешенные функции C ++. C ++ - это большой исторически сложившийся язык, в котором подчеркивается, что программист должен делать то, что он хочет, над безопасностью и простотой использования, и не все его функции во всей их гибкости необходимы для создания хороших программ. Существует много стандартов кодирования, которые ограничивают использование некоторых функций; например, руководящие принципы Google по большей части запрещают множественное наследование, сложные шаблоны и исключения (хотя последний по историческим причинам). Но никакая функция не запрещена «потому что у Java ее нет»; функции рассматриваются только в рамках C ++.
источник
Object
значительной степени подходитvoid*
для большинства применений.finally
не замена для них. Два языка просто принципиально разные.Я обсуждал, стоит ли беспокоиться о публикации другого ответа, когда у вас уже есть число, которое достигает того, что кажется вполне обоснованным выводом: что ваша идея - это, по сути, катастрофа, ожидающая случиться. Я думаю, однако, что они не смогли указать некоторые весьма важные причины этого вывода.
Различия между Java и C ++ намного глубже, чем детали, на которых вы, кажется, сосредоточились.
Например, вы говорите о запрете множественного наследования в C ++. Во-первых, я укажу, что это просто упущение. Java определяет «интерфейсы» как отдельные вещи от «классов». Один класс наследует только от одного другого класса, но может реализовывать произвольное количество интерфейсов.
C ++ не разделяет два понятия таким образом. Ближайший аналог C ++, обеспечивающий реализацию интерфейса в Java , наследует от другого класса. Таким образом, чтобы вообще выровнять два достаточно хорошо выровненных, вам, вероятно, нужно использовать множественное наследование в C ++, но вы хотите ограничить некоторые из этих базовых классов примерно такими же способами, как Java ограничивает интерфейс по сравнению с классом (то есть, по существу, что он определяет сигнатуры функций, но, по крайней мере, в основном, не реализации).
Это едва царапает поверхность реальных различий между этими двумя. В действительности, где код Java, вероятно, определяет интерфейсы, и классы, которые реализуют эти интерфейсы, код C ++ с гораздо большей вероятностью определяет некоторые шаблоны, которые будут работать с любым классом, который соответствует его требованиям (а не только те, которые определены специально для реализации интерфейса. (s) это указывает).
Если вы действительно хотите код, который в основном «Java использует синтаксис C ++», вам почти наверняка придется запретить что-либо и все, что похоже на последнее. Вам нужно будет ограничить использование шаблонов примерно до уровня «контейнера T», который поддерживают дженерики Java. К сожалению, выполнение этого приведет к тому, что код C ++ станет таким беспорядком, что никто не сможет поддерживать его таким, каким он существует сейчас, не говоря уже о долгосрочной возможности перевести его на какой-то другой язык программирования.
Если вы действительно хотите, чтобы в будущем код мог быть преобразован в какой-либо другой язык, постарайтесь сделать его максимально чистым и читабельным. В идеале нужно написать псевдокод и при этом выполнить его. Хорошо написанный современный C ++ подходит к этому идеалу гораздо ближе, чем предложенное вами подмножество. Независимо от того, как вы это пишете, если вы когда-либо переводите на Java, вам придется фактически переводить код, а не только синтаксис отдельных операторов.
источник
Если вы собираетесь писать код на языке X, потратьте время на то, чтобы правильно выучить язык и использовать все его возможности, чтобы помочь вам решить проблему. Плохие вещи случаются, когда вы пытаетесь сделать дословный перевод с одного языка на другой, будь то японский на английский или Java на C ++. Гораздо лучше начать с хорошего понимания проблемы и выразить решение так, как это наиболее естественно для используемого языка.
Несколько лет назад я видел программу на C, у которой не было отступов, и каждое утверждение начиналось в столбце 7, потому что автором кода был программист на Фортране, который, как оказалось, использовал C. Другие программисты на Фортране волновались по поводу этих новомодных вещей, называемых указателями. У меня не хватило ума упоминать указатели на указатели, я думаю, они бы упали в обморок на месте.
Представьте, что наймете кого-нибудь, чтобы сохранить этот код в будущем. Если это хороший код C ++, вы сможете нанять компетентного разработчика C ++, и он сможет найти способ обойти это. Если это «Java в C ++», то ни C ++, ни Java-разработчики не будут легко понимать код.
источник
Все ваши причины могут быть опровергнуты:
Это не означает, что эта функция не является хорошей (никакая функция не может быть изначально плохой). Это только означает, что эта функция часто использовалась неправильно (или ее невозможно реализовать из-за фундаментальных концепций, таких как прямые указатели или сборка мусора). Java по определению нацелена на то, чтобы быть проще и более дружественной к программисту, поэтому удаление функций, которые зарекомендовали себя как легко злоупотребляемые.
О, это может быть? Давайте посмотрим простейший код C ++:
К сожалению, никакие «специфичные для языка» функции не используются, но они уже не поддерживаются разработчиками Java! Потому что в Java вы разыменовываете с "." пока здесь это "->.
Или C #. Или Хаскелл. Или Питон. Или Рубин. Или КОБОЛ (да, вы можете!). Как вы можете сказать будущее?
Точно наоборот. Каждая функция была введена для того, чтобы сделать программирование проще и, следовательно, более удобным Например: взять программу, работающую на поплавках. Теперь обновите его для обработки комплексных чисел. Перегрузка оператора на помощь!
Но Java имеет множественное наследование! Это называется «интерфейс». Реализация Java - проблемный обходной путь, чтобы избежать страшного алмаза, вызванного тем, что все происходит из-за
Object
. Это делается путем введения,interface
единственной целью которого является быть чем-то, что не происходит отObject
. В C ++ никогда не было этой проблемы - нет обязательной общей базы, поэтому каждый класс может функционировать как интерфейс без страшного ромба.Примечание: недавно Java представила ... конкретные методы в интерфейсах. Добавленная функция C ++ всегда должна была решить проблему, которой никогда не было.
Вы также упомянули лишь несколько «вещей, которые есть у C ++, но у Java нет». Одним из самых больших различий между C ++ и Java является контроль над расположением памяти. Вы можете создать массив указателей на объекты (как в Java) ИЛИ вы можете создать непрерывный блок памяти. Теперь, если бы я беспокоился о функции C ++, которая может вводить в заблуждение разработчиков Java, что-то столь же скрытое и тонкое, как это, заняло бы место в моем списке намного выше, чем очевидное и узнаваемое на первый взгляд, как множественное наследование или перегруженные операторы.
Итог: чистый код - это чистый код. Java или C ++ - такая же разница. Просто будь проще. Ненужные осложнения являются основной причиной плохого кода.
источник
Нет, вы вообще не должны писать C ++, как это было на Java, и вам определенно не следует опускать функции языка C ++, которых нет в Java.
С одной стороны, Java является сборщиком мусора и, следовательно, не имеет эквивалента ключевого слова C ++ "delete". Итак, вы реализуете программу без удаления, потому что по вашим правилам это не разрешено.
Поздравляю, теперь у вас утечка памяти;). Это тоже не теоретически - я видел, как именно такая ситуация случается в игре с открытым исходным кодом.
Аналогично, в Java нет ничего похожего на указатели C ++, что исключает множество общих соглашений о вызовах функций.
В C ++ есть особенности, которых вы, возможно, следует избегать (см. Ниже), но «не быть в Java» не является хорошим лакмусовым тестом.
Лучшее руководство будет следующим:
Пункт (3) означает, что вы не должны иметь код Java-программистов на C ++ без обучения их на C ++. Есть некоторые тонкие, но очень важные различия, которые они могут не узнать, если они пытаются трактовать это как странный диалект Java.
Пункт (2) означает, что, если вашей команде, в частности, неудобно множественное наследование (например), и если существует адекватное решение, которое его не использует, то может быть лучше использовать это альтернативное решение. Однако это зависит именно от вашей команды. С другой стороны, если вашей команде больше неудобно с этим альтернативным решением, чем с множественным наследованием, используйте множественное наследование!
Наконец, существуют языковые особенности C ++, которые, возможно, следует избегать. Если вы хотите узнать, что это такое, спросите программистов на C ++ , а не программистов на другом языке. Некоторые примеры для начала - арифметика указателей (без универсального консенсуса) и goto.
источник
В других ответах уже есть несколько положительных моментов, но я хотел бы дать более полный ответ, обращаясь к вашим вопросам и заявлениям в отдельности.
На этот вопрос довольно хорошо ответили: Java не является «хорошими частями» C ++, и нет никаких причин так думать.
В частности, хотя достоинства каждой отдельной функции C ++ являются дискуссионными, многие из функций C ++ 11 / C ++ 14, которые не являются частью Java, не обязательно исключаются, поскольку дизайнеры Java считают их плохой идеей. Например, до версии 8 в Java не было лямбд, но они были представлены в C ++ в стандарте C ++ 11. До Java 8 ваше предположение о том, что функции C ++, отсутствующие в Java, отсутствовали по проекту, потому что они «не хороши», подразумевало бы, что лямбды как языковая функция «не хороши» (к ужасу LISPers везде, хотя они вероятно, в ужасе, чтобы услышать, что вам, видимо, на самом деле нравится Java). Но теперь Java-дизайнеры разместили свой штамп одобрения (TM) на лямбдах, так что теперь они A Good Thing.
Чтобы глубже вникнуть, даже в Java 8, лямбда-выражения-замыкания не так гибки, как лямбда-выражения C ++ 14, но это может быть связано с ограничениями архитектуры JVM, а не с сознательным решением о том, что более гибкий подход плох из-за Перспектива языкового дизайна.
Это главное, на что я хотел ответить.
Вообще говоря, может иметь смысл получать обзоры кода от программистов, которые не очень хорошо знакомы с языком, который вы используете. Они могут дать вам ценную информацию о ясности названий и комментариев вашей функции / метода, и (как правильно говорит ваш вопрос), если язык похож на один или несколько языков, которые они уже знают, они могут быть в состоянии следовать основному потоку программы и потенциально ловить логические ошибки.
Тем не менее, это не тот случай, когда такого рода рецензии когда-либо будут «столь же хороши, как» или «эквивалентны» рецензии от разработчиков, которые фактически знают язык, который вы используете. По существу, это происходит потому , что делает один язык вид похож на другой, как правило , скрывают тонкие различия, делая один язык , ведут себя , как другой (особенно в случае C ++ и Java) может быть не-идиоматических для языка и / или может оказаться слишком запутанной для рецензентов.
Во-первых, давайте подумаем о том, что значит сделать C ++ «похожим» на Java. В простом случае вы можете использовать
new
для создания объектов, как в Java:Но объекты, созданные таким способом, используют
->
вместо.
вызова методов, поэтому, если вы хотите, чтобы вызовы методов выглядели как Java, вы должны вместо этого написать:Но это не идиоматично; в частности, память должна быть позже очищена с использованием
delete &foo
, что некоторые опытные разработчики C ++ могут даже не осознавать, что это законный код . В любом случае, есть смешные , не Java-подобные символы пронизывают, поэтому мы не можем достаточно сделать язык «выглядеть» Java. (Вы можете отказаться от*new
использования#define New *new
или, что еще хуже,#define new *new
но тогда вы просто умоляете своих коллег-разработчиков ненавидеть вас.) И, как упоминалось выше,delete
в Java не существует, так что в любом случае (как упоминалось в другом ответе) ) вы никогда не сможете заставить объект «выглядеть» так, как в Java, без утечек памяти.Но современный C ++ включает в себя интеллектуальные общие указатели, которые во многом похожи на управляемые памятью ссылки на переменные в Java. Поэтому везде, где вы можете писать на Java
Foo foo = new Foo();
, вы можете написать:Теперь вы используете языковую функцию, которая на самом деле очень похожа на Java. Но вдруг вам есть что объяснить рецензентам, не относящимся к C ++: что это за
shared_ptr
штука? Какие тонкие хитрые "ошибки" изmake_shared
? (Он использует совершенную пересылку, которая имеет некоторые случаи сбоя и может привести к вызову «неправильного» конструктора.) Почему необходимо вызывать методы с помощью->
, но.
компилятор допускает использование с некоторыми методами? (shared_ptr
имеет свои собственные методы.) Если методFoo::reset(void)
существует, неосторожный разработчик может попытаться вызвать его с помощьюfoo.reset()
которого (если имеется только один общий указатель, указывающий на тот случай,Foo
когда происходит вызов) удалит базовую память и обнулитfoo
, а также Java-разработчики вряд ли поймут эту проблему.Кроме того, C ++ имеет много из ловушек , которые специфические для языка, Насколько я могу судить, большинство разработчиков C ++ учатся справляться с этими подводными камнями, постепенно разрабатывая свою собственную идиому для «безопасных» практик C ++, которая часто несколько уникальна для них или для их команды разработчиков (см., Например, существующий ответ, в котором упоминается Практика кодирования Google и комментарий к ней гласят, что «Опытные ветераны C ++ обычно отвергают правила кодирования Google»). Все утверждения о том, что язык может быть слишком сложным, кажется (по моему опыту, по крайней мере), обычно встречаются с некоторым изменением «ну, перестань использовать его неправильно». Я понимаю, что это крайне негативное мнение сообщества C ++, и, конечно, есть опытные разработчики, более охотно помогающие изучающим язык, но они Кажется, это определенная защита, например, в отношении неопределенного поведения (см., например, большую часть обсуждения в моей ссылке «Подводные камни» выше).
Java-разработчики просто не помогут найти и исправить эти ошибки с помощью анализа кода.
Это вполне допустимо - даже похвально - пытаться учесть, что может случиться с вашим кодом в будущем, пока вы находитесь на этапе разработки.
Но, во-первых, это конкретное соображение кажется отдаленной возможностью: код, как правило, либо повторно используется как есть (например, вы можете подключить часть или весь работающий код C ++ в какое-то будущее программное обеспечение Java с использованием интерфейса JNI), либо переписать полностью чем напрямую вручную «транскрибировать».
И, во-вторых, вы позже говорите,
Это по существу отменяет вашу точку «конвертировать в Java». Если программное обеспечение написано на идиоматическом C ++, а затем преобразовано в идиоматическую Java, нет никаких оснований ожидать, что это преобразование будет (или могло бы!) Быть выполнено путем применения точного однозначного отображения функций C ++ к функциям Java.
Непонятно, что вы имеете в виду здесь, но я на самом деле несколько согласен с частью этого: если вы не очень осторожны, и даже когда вы осторожны, функции C ++ могут привести к проблемам с удобством сопровождения. C ++ FQA Lite (сайт критически языка и его приверженцев из тех , кто , по крайней мере , кажется, на самом деле понять это достаточно хорошо) утверждает , что
ПОЖАЛУЙСТА, ОБРАТИТЕ ВНИМАНИЕ: Если вы фанат C ++ и вы добрались до этого момента в моем ответе и чувствуете склонность перейти к комментариям, чтобы доказать, что автор FQA на самом деле не понимает C ++ или неискренен в большинстве своих аргументов Обратите внимание, что (1) ровно через два предложения после того, как я его цитирую, я признаю, что FQA - это очень предвзятый источник, и (2) не имеет значения, что я пытаюсь сказать, понимает ли автор FQA C ++ и я не пытаюсь использовать C ++, и вы должны прочитать остальную часть поста, не предполагая, что я анти-C ++ только потому, что я цитировал FQA. Конец примечания.
Точно так же Линус Торвальдс ненавидит C ++ по существу по этой причине (предупреждение: ссылка включает в себя много ругательств в истинно печально известном стиле Линуса).
Очевидно, что это очень предвзятый подход к делу, но даже сторонники C ++ часто говорят, что вам не следует использовать весь набор языковых функций (еще раз, см. Рекомендации по кодированию Google; также, Бьярн Страуструп, создатель C ++) публично заявил: «В C ++ существует гораздо меньший и более чистый язык, изо всех сил пытающийся выйти»).
Поэтому я думаю, что есть некоторая заслуга в том, что функции C ++ могут быть слишком просты для неправильного использования, особенно если вы работаете в Java. Кроме того, есть смысл в том, чтобы облегчить эти проблемы, ограничив себя каким-то подмножеством языка.
Однако решение о том, какое подмножество использовать на основе другого языка, не кажется правильным подходом, если только «другой язык» не является C, поскольку в действительности существует C-подобное подмножество языка C ++. (Линус ссылается на это в своей статье выше, а Скотт Мейерс даже называет это подмножество «подъязыком».) Парадигма времени выполнения Java (сборщик мусора, работающий на виртуальной машине) настолько принципиально отличается от C ++, что это Не ясно, есть ли какие-то полезные уроки, которые можно извлечь из использования C ++, и, как отмечалось выше, попытка извлечь уроки о C ++ непосредственно из Java может привести к очень неидиоматическому коду.
Вместо этого попытайтесь определить свое «приемлемое подмножество» языка, понимая, как язык можно использовать идиоматически. Если вы хотите получить довольно ограниченное подмножество, которое по-прежнему использует многие из функций C ++, помимо того, что предлагает C, вышеупомянутая рекомендация по Google Coding может быть хорошим началом. Конечно, вы получите разработчиков, которые скажут, что для некоторых ограничений Google «нет рациональных аргументов» , но если вы не хотите нанимать Александреску подальше от его работы над языком D (который сам должен вам что-то сказать), это наверное хорошо Это, безусловно, лучше, чем пытаться превратить C ++ в Java.
Еще одна хорошая отправная точка для набора рекомендаций по коду - это новые основные принципы C ++ , работа которых ведется Бьярном Страуструпом и Хербом Саттером.
Единственный другой способ справиться с недостатками C ++ - это выбрать другой язык. Похоже, вам нравится Java, и вы думаете, что есть шанс, что этот проект в конечном итоге может быть преобразован в Java. Как отмечено в другом ответе, вы можете просто ... начать с Java.
Есть две причины, по которым вам действительно может понадобиться что-то, кроме Java:
Я уже несколько об этом говорил, но намеренно пропустил ваше второе предложение.
Я не уверен, что что-то подобное
constexpr
, что не имело бы никакого смысла в частично JIT-языке, таком как Java, указывает на неверную архитектуру. Я более открыт к идее, что чрезмерное использование шаблонного метапрограммирования может быть более сложным, чем оно того стоит, особенно сейчас, когдаconstexpr
существует оценка функций во время компиляции, но из случая видно,constexpr
что нет недостатка в дизайне, если вы вы используете его: вы просто гарантируете, что некоторые вычисления выполняются еще до запуска кода, что является огромным приростом производительности (см., например, эту запись для проблемы n-body в The Benchmark Game , которая превосходит все остальные записи, кроме другой написанный на C ++,источник
import SomeVeryBasicPackage
и просто сделать это ?» Задайте продвинутый вопрос и первый ответ почти неизбежно вдоль линий «Почему ты неimport SomeMagicalPackage
и просто делать что ?»Нет.
Если «из-за среды проекта» вы ограничены использованием C ++, то нет смысла даже думать о какой-либо другой технологии, независимо от того, насколько вы лично предпочитаете / надеетесь ее использовать / пропагандировать.
Независимо от того, поддерживает ли «Технология X» или «Y» какую-либо конкретную функцию, не должно быть никакого отношения к тому, как вы создаете свое приложение C ++.
Это приложение на C ++, предположительно для некоторой «доброй причины» (сейчас или в прошлом), поэтому вы должны написать его как приложение C ++, используя все, что обеспечивает этот конкретный «инструментарий».
Если и когда есть требование портировать приложение на какую-то другую технологию, тогда (и только тогда) вы можете рассмотреть функции на других платформах. Нет смысла «отрезать нос, чтобы прорезать лицо» на случай, если что-то может случиться. Помните, однако, что массовое переписывание - это дорогостоящая и рискованная операция, которую руководство вряд ли предпримет без очень веской причины.
Подобные дебаты («использовать или не использовать») проводились несколько лет назад в мире Visual Basic [.Net], где у кого-то возникла блестящая идея, что вы должны писать приложения на Visual Basic без использования какого-либо [основного языка] функциональность, предоставляемая пространством имен Microsoft.VisualBasic. Это все равно что пытаться написать приложение на C ++ без пространства имен std ::; Хорошо, это возможно, но с какой стати кто-то в здравом уме потрудится сделать это?
источник
Microsoft.VisualBasic
имен немного растянуто. Прошло много лет с тех пор, как я последний раз использовал его, но, по крайней мере, вначале он был нацелен на обратную совместимость с VB6 (и / или чтобы программисты VB6 чувствовали себя «как дома»); в основном это обеспечивало функциональность, которая уже была доступна в остальной части фреймворка в более современной (и лучше интегрированной) форме, поэтому в новых проектах редко имело смысл использовать ее. Напротив,std::
пространство имен находится там, где находится вся стандартная библиотека - избегать его - все равно, что избегать всего BCL в .NET.Все текущие ответы говорят, что это плохая вещь, так как вы должны воспользоваться языком, который вы используете, а также объяснить, почему функция C ++ не является «плохой» только потому, что она не в jave. Я отвечу на это под другим углом.
Одно дело избегать сложных функций C ++, таких как множественное наследование, перегрузка операторов и определение собственного шаблона.
Но любая проблема, которая делает больше, чем самая простая задача:
Не существует общего подмножества Java и C ++, которое допускает вышеизложенное, поэтому то, что вы просите, сделать невозможно. (Если бы вы спрашивали о Java и C #, у вас было бы гораздо больше шансов, так как они оба использовали сборщики мусора.)
Однако вы можете потребовать, чтобы код был написан так, чтобы Java-разработчик мог понять, что делает (но не детальное «как»), и это было бы разумно.
Вы также можете создать свой собственный язык, который вы реализовали в C ++ и JAVA .....
источник
Никто не должен писать код, который не понимают другие кодеры. Если вы считаете, что языковая блокировка является проблемой, подождите, пока у вас не появится блокировка разработчика. Один с большей вероятностью будет держать вас в заложниках, чем другой.
Там действительно нет технических причин. Вы создали сценарий, в котором язык использовался по любой причине, но многие нынешние и, возможно, будущие разработчики не совсем его понимают.
Я предполагаю, что разработчики Java, скорее всего, будут писать C ++ так, как они пишут на Java, так зачем делать это правилом. Вы можете обнаружить некоторые специфические функции C ++, которые проще реализовать и поддерживать с помощью небольшой инструкции / документации C ++ для ваших Java-разработчиков, чем большой шарик Java-беспорядка, с которым они в противном случае застряли бы.
Это был аргумент о проблемах перехода программистов на BASIC на объектно-ориентированные языки. Дело не в том, что они внедряют ООП-практику в ущерб новым разработчикам, которые этого не понимают, а в том, что они вообще не реализуют это. Если они это делают, они обычно ошибаются. Если что-то сделано плохо, его нужно удалить независимо от причины.
Кроме того, что кто-то просто слепо копирует и вставляет код, они собираются делать это во многих областях, которые они так или иначе не понимают.
источник