В других ответах уже есть несколько положительных моментов, но я хотел бы дать более полный ответ, обращаясь к вашим вопросам и заявлениям в отдельности.
Если Java не предоставляет функцию, которая есть в C ++, это означает, что эта функция не очень хорошая, поэтому мы должны отказаться от ее использования.
На этот вопрос довольно хорошо ответили: 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 ++ со специальными функциями C ++ (например, функции-друзья, множественное наследование) может поддерживаться или проверяться только программистами C ++, но если мы просто напишем C ++, как Java (без специфической для языка C ++ функции), код может поддерживаться или проверяться обоими C ++ и Java программисты.
Это главное, на что я хотел ответить.
Вообще говоря, может иметь смысл получать обзоры кода от программистов, которые не очень хорошо знакомы с языком, который вы используете. Они могут дать вам ценную информацию о ясности названий и комментариев вашей функции / метода, и (как правильно говорит ваш вопрос), если язык похож на один или несколько языков, которые они уже знают, они могут быть в состоянии следовать основному потоку программы и потенциально ловить логические ошибки.
Тем не менее, это не тот случай, когда такого рода рецензии когда-либо будут «столь же хороши, как» или «эквивалентны» рецензии от разработчиков, которые фактически знают язык, который вы используете. По существу, это происходит потому , что делает один язык вид похож на другой, как правило , скрывают тонкие различия, делая один язык , ведут себя , как другой (особенно в случае C ++ и Java) может быть не-идиоматических для языка и / или может оказаться слишком запутанной для рецензентов.
Во-первых, давайте подумаем о том, что значит сделать C ++ «похожим» на Java. В простом случае вы можете использовать new
для создания объектов, как в Java:
Foo foo = new Foo();
Но объекты, созданные таким способом, используют ->
вместо .
вызова методов, поэтому, если вы хотите, чтобы вызовы методов выглядели как Java, вы должны вместо этого написать:
Foo& foo = *new Foo();
Но это не идиоматично; в частности, память должна быть позже очищена с использованием delete &foo
, что некоторые опытные разработчики C ++ могут даже не осознавать, что это законный код . В любом случае, есть смешные , не Java-подобные символы пронизывают, поэтому мы не можем достаточно сделать язык «выглядеть» Java. (Вы можете отказаться от *new
использования #define New *new
или, что еще хуже, #define new *new
но тогда вы просто умоляете своих коллег-разработчиков ненавидеть вас.) И, как упоминалось выше, delete
в Java не существует, так что в любом случае (как упоминалось в другом ответе) ) вы никогда не сможете заставить объект «выглядеть» так, как в Java, без утечек памяти.
Но современный C ++ включает в себя интеллектуальные общие указатели, которые во многом похожи на управляемые памятью ссылки на переменные в Java. Поэтому везде, где вы можете писать на Java Foo foo = new Foo();
, вы можете написать:
std::shared_ptr<Foo> foo = std::make_shared<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-разработчики просто не помогут найти и исправить эти ошибки с помощью анализа кода.
Вас могут попросить преобразовать код в Java когда-нибудь.
Это вполне допустимо - даже похвально - пытаться учесть, что может случиться с вашим кодом в будущем, пока вы находитесь на этапе разработки.
Но, во-первых, это конкретное соображение кажется отдаленной возможностью: код, как правило, либо повторно используется как есть (например, вы можете подключить часть или весь работающий код C ++ в какое-то будущее программное обеспечение Java с использованием интерфейса JNI), либо переписать полностью чем напрямую вручную «транскрибировать».
И, во-вторых, вы позже говорите,
Каждая особенность языка C ++ (например, множественное наследование) должна иметь альтернативы для реализации в Java ....
Это по существу отменяет вашу точку «конвертировать в Java». Если программное обеспечение написано на идиоматическом C ++, а затем преобразовано в идиоматическую Java, нет никаких оснований ожидать, что это преобразование будет (или могло бы!) Быть выполнено путем применения точного однозначного отображения функций C ++ к функциям Java.
Код без специфических особенностей C ++ обычно более удобен в обслуживании.
Непонятно, что вы имеете в виду здесь, но я на самом деле несколько согласен с частью этого: если вы не очень осторожны, и даже когда вы осторожны, функции C ++ могут привести к проблемам с удобством сопровождения. C ++ FQA Lite (сайт критически языка и его приверженцев из тех , кто , по крайней мере , кажется, на самом деле понять это достаточно хорошо) утверждает , что
... 80% разработчиков понимают не более 20% языка. Это не одинаковые 20% для разных людей, поэтому не рассчитывайте, что они поймут код друг друга.
ПОЖАЛУЙСТА, ОБРАТИТЕ ВНИМАНИЕ: Если вы фанат 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:
- Вам действительно нужна производительность во время выполнения. В этом случае обращение с C ++ как с Java, вероятно, на самом деле вам не поможет, потому что Java-подобные методы, такие как shared-указатели, снижают вашу производительность во время выполнения.
- Вам нужно программное обеспечение для работы на малоизвестной платформе, которая еще не поддерживает JVM. В этом случае вы, вероятно, застряли с языками, которые имеют интерфейсы GCC или Clang. C и C ++ являются очевидными кандидатами, но вы также можете посмотреть что-то вроде Rust. (Быстрый плагин: я не использовал Rust широко, но он выглядит потрясающе, и мне не терпится поработать над крупным проектом Rust, как только я смогу, и я думаю, что все, кто рассматривает возможность запуска проекта C ++, должны рассмотреть Rust в качестве альтернативы.)
Каждая особенность языка C ++ (например, множественное наследование) должна иметь альтернативы для реализации в Java. Если это не так, значит, шаблон проектирования или архитектура кода проблематичны.
Я уже несколько об этом говорил, но намеренно пропустил ваше второе предложение.
Я не уверен, что что-то подобное constexpr
, что не имело бы никакого смысла в частично JIT-языке, таком как Java, указывает на неверную архитектуру. Я более открыт к идее, что чрезмерное использование шаблонного метапрограммирования может быть более сложным, чем оно того стоит, особенно сейчас, когда constexpr
существует оценка функций во время компиляции, но из случая видно, constexpr
что нет недостатка в дизайне, если вы вы используете его: вы просто гарантируете, что некоторые вычисления выполняются еще до запуска кода, что является огромным приростом производительности (см., например, эту запись для проблемы n-body в The Benchmark Game , которая превосходит все остальные записи, кроме другой написанный на C ++,