В інших відповідях вже є деякі хороші моменти, але я хотів би дати більш повну відповідь, вирішуючи ваші запитання та заяви окремо.
Якщо Java не надає функцію C ++, це означає, що ця функція не є хорошою, тому нам слід не допустити її використання.
На це досить добре відповіли: Java не є "хорошими частинами" C ++, і немає причин вважати це.
Зокрема, хоча достоїнства кожної окремої функції C ++ є дискусійними, багато особливостей C ++ 11 / C ++ 14, які не входять до складу Java, не обов'язково виключаються, оскільки дизайнери Java вважали, що вони є поганою ідеєю. Наприклад, до версії 8 у Java не було лямбда, але вони були введені до C ++ у стандарті C ++ 11. До Java 8, ваше припущення про те, що функції C ++, відсутні у Java, відсутній у дизайні, оскільки вони "непогані", це означало б, що лямбди як мовна особливість "не є гарними" (на жаль LISPers скрізь, хоча вони напевно, жахнувся, щоб почути, що вам, мабуть, справді подобається Java). Але тепер дизайнери Java поставили свій штамп схвалення (TM) на лямбдах, тож вони тепер хороша річ.
Щоб викопати трохи глибше, навіть у 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. Тож скрізь на Яві, яку ви могли написати Foo foo = new Foo();
, ви можете замість цього написати:
std::shared_ptr<Foo> foo = std::make_shared<Foo>();
Тепер ви використовуєте мовну функцію, яка насправді дуже схожа на Java під кришкою. Але раптом у вас є що пояснити рецензентам, які не містять С ++: що це за 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 щодо кодування; також, Bjarne Stroustrup, творець C ++ , публічно заявив: "У межах C ++ існує набагато менша та чистіша мова, яка намагається вийти").
Тому я думаю, що є деяка заслуга в ідеї, що функції C ++ можуть бути занадто простими для неправильного використання, особливо якщо ви надходите з фону Java. Крім того, заслуговує ідея полегшити ці проблеми, обмежившись деякою підмножиною мови.
Однак вирішити, який підмножина використовувати на основі іншої мови, не здається правильним підходом, якщо тільки "іншою мовою" є C, оскільки дійсно є С-подібний підмножина мови C ++. (Лінус посилається на це у своїй виклику вище, а Скотт Майєрс навіть називає це підмножиною як "підмовою".) Парадигма часу виконання Java (збирається сміття, працює на VM) настільки принципово відрізняється від C ++, що це Не ясно, є корисні уроки, щоб зробити з нього використання C ++, і як зазначалося вище, намагання витягнути уроки про C ++ безпосередньо з Java може призвести до дуже неідіоматичного коду.
Натомість спробуйте визначити свій "прийнятний підмножина" мови, щоб зрозуміти, як мовою можна користуватися ідіоматично. Якщо ви хочете досить обмежувати підмножину, яка все-таки користується багатьма можливостями C ++, ніж те, що пропонує C, вищезгадане керівництво Google щодо кодування може бути гарним місцем для початку. Звичайно, ви отримаєте розробників, які кажуть, що немає "раціональних аргументів" щодо деяких обмежень Google , але якщо ви не прагнете найняти Олександреску далеко від його роботи над мовою D (яка сама повинна вам щось сказати), це певно гаразд. Це, звичайно, краще, ніж намагатися перетворити C ++ на Java.
Ще однією гарною відправною точкою для набору кодових настанов є нові основні керівні принципи C ++ , незавершене виробництво Bjarne Stroustrup та Herb Sutter.
Єдиний інший спосіб вирішити недоліки C ++ - це вибрати іншу мову. Це здається, що вам подобається Java, і ви думаєте, що є ймовірність, що цей проект може з часом перетворитися на Java. Як зазначається в іншій відповіді, ви могли просто ... почати з Java.
З двох причин, чому вам може справді потрібно використовувати щось інше, ніж Java:
- Ви дійсно потребуєте виконання часу виконання. У цьому випадку лікування C ++, як-от Java, напевно, вам не допоможе, тому що подібні до Java методи, такі як загальні покажчики, погіршують вашу продуктивність.
- Вам потрібне програмне забезпечення для роботи на незрозумілій платформі, яка ще не підтримує JVM. У цьому випадку ви, мабуть, застрягли з мовами, які мають GCC або Clang фронти. C і C ++ є очевидними кандидатами, але ви також можете розглянути щось на зразок Руста. (Швидкий штекер: Я не використовував Руста широко, але це виглядає приголомшливо, і я готовий працювати над великим проектом Rust, як тільки можу, і я думаю, що всі, хто розглядає можливість створення проекту C ++, повинні розглядати Руст як альтернативу.)
Кожна специфічна мова мови C ++ (наприклад, багаторазове успадкування) повинна мати альтернативи для впровадження в Java. Якщо цього немає, це означає, що модель дизайну або архітектура коду є проблематичною.
Я вже дещо вирішував це, але навмисно викинув ваше друге речення.
Я не переконаний, що щось подібне constexpr
, яке не мало б сенсу в частково JIT мові, як Java, є вказівкою на недійсну архітектуру. Я більше відкритий до ідеї, що надмірне використання метапрограмування шаблонів може бути більшим клопотом, ніж це варто, особливо зараз, коли constexpr
це робиться для оцінки функції компіляції в часі, але з випадків зрозуміло, constexpr
що у вас немає вад дизайну, якщо ви Ви використовуєте це: ви просто гарантуєте, що деякі обчислення відбуваються до навіть запуску коду, що є приголомшливим підвищенням продуктивності (див., наприклад, цей запис щодо проблеми n-body The Game Benchmark Game , що перевершує будь-який інший запис, окрім іншого) написано на C ++,