В других ответах уже есть несколько положительных моментов, но я хотел бы дать более полный ответ, обращаясь к вашим вопросам и заявлениям в отдельности.
Если 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 ++,