Sudah ada beberapa poin bagus dalam jawaban lain, tetapi saya ingin memberikan jawaban yang lebih lengkap, menjawab pertanyaan dan pernyataan Anda secara individual.
Jika Java tidak menyediakan fitur yang dimiliki C ++, itu berarti fitur tersebut tidak bagus, jadi kami harus mencegah menggunakannya.
Ini telah dijawab dengan cukup baik: Java bukan "bagian yang baik" dari C ++, juga tidak ada alasan untuk berpikir demikian.
Secara khusus, meskipun kelebihan masing-masing fitur C ++ individu masih bisa diperdebatkan, banyak fitur C ++ 11 / C ++ 14 yang bukan bagian dari Java tidak selalu dikecualikan karena desainer Java berpikir mereka adalah ide yang buruk. Sebagai contoh, sampai versi 8, Java tidak memiliki lambdas, tetapi mereka diperkenalkan ke C ++ dalam standar C ++ 11. Sebelum ke Java 8, asumsi Anda bahwa fitur C ++ yang hilang dari Jawa hilang karena desain karena "tidak baik" akan menyiratkan bahwa lambdas sebagai fitur bahasa "tidak baik" (yang membuat LISPers ketakutan di mana-mana, meskipun mereka mungkin cukup ngeri mendengar Anda ternyata benar - benar menyukai Java). Tapi sekarang para desainer Java telah menggunakan Stamp of Approval (TM) mereka di lambdas, jadi mereka sekarang A Good Thing.
Untuk menggali lebih dalam, bahkan di Jawa 8, lambdas-closure tidak sefleksibel lambda C ++ 14, tetapi ini mungkin disebabkan oleh keterbatasan arsitektur JVM daripada keputusan sadar bahwa pendekatan yang lebih fleksibel buruk dari suatu perspektif desain bahasa.
Kode C ++ dengan fitur khusus C ++ (mis: fungsi teman, pewarisan berganda) hanya dapat dipertahankan atau ditinjau oleh programmer C ++, tetapi jika kita hanya menulis C ++ seperti Java (tanpa fitur khusus bahasa C ++), kode tersebut dapat dipertahankan atau ditinjau oleh keduanya Pemrogram C ++ dan Java.
Ini adalah hal utama yang ingin saya tanggapi.
Secara umum, mungkin ada beberapa nilai untuk mendapatkan ulasan kode dari programmer yang tidak akrab dengan bahasa yang Anda gunakan. Mereka dapat memberi Anda umpan balik yang berharga tentang kejelasan fungsi / nama metode dan komentar Anda, dan (seperti yang disiratkan oleh pertanyaan Anda dengan benar) jika bahasanya mirip dengan satu atau lebih bahasa yang telah mereka ketahui, mereka mungkin dapat mengikuti alur program dasar dan berpotensi menangkap kesalahan logika.
Namun, ini bukan masalah bahwa ulasan semacam ini akan pernah "sebagus" atau "setara dengan" ulasan dari pengembang yang benar-benar tahu bahasa yang Anda gunakan. Pada dasarnya, ini karena membuat satu bahasa terlihat seperti yang lain biasanya akan menyembunyikan perbedaan yang halus, sementara membuat satu bahasa berperilaku seperti yang lain (terutama dalam kasus C ++ dan Java) mungkin tidak idiomatis untuk bahasa dan / atau mungkin masih terlalu membingungkan untuk pengulas.
Pertama, mari kita pikirkan apa artinya membuat C ++ "mirip" Java. Sebagai kasus sederhana, Anda dapat menggunakan new
untuk membuat instance objek, seperti di Jawa:
Foo foo = new Foo();
Tetapi objek yang dipakai dengan cara ini menggunakan ->
alih-alih .
memanggil metode, jadi jika Anda ingin panggilan metode terlihat seperti Java, Anda harus menulis:
Foo& foo = *new Foo();
Tetapi ini tidak idiomatis; khususnya, memori kemudian harus dibersihkan menggunakan delete &foo
, yang beberapa pengembang C ++ berpengalaman mungkin bahkan tidak sadari adalah kode hukum . Either way, ada yang lucu simbol non-Jawa-seperti ditaburi seluruh, jadi kita tidak bisa cukup membuat bahasa "terlihat seperti" Java. (Anda bisa dihilangkan *new
dengan menggunakan #define New *new
, atau, lebih buruk,, #define new *new
tetapi kemudian Anda hanya meminta rekan pengembang untuk membenci Anda.) Dan, seperti yang disebutkan di atas, delete
tidak ada di Jawa, jadi dalam hal apa pun (seperti disebutkan dalam jawaban lain ) Anda tidak dapat benar - benar membuat penggunaan objek "terlihat" seperti di Jawa tanpa kebocoran memori.
Tapi C ++ modern termasuk pointer berbagi cerdas, yang berperilaku banyak seperti referensi variabel yang dikelola memori Java. Jadi di mana pun di Jawa yang bisa Anda tulis Foo foo = new Foo();
, Anda bisa menulis:
std::shared_ptr<Foo> foo = std::make_shared<Foo>();
Sekarang Anda menggunakan fitur bahasa yang sebenarnya sangat mirip dengan Java di bawah tenda. Tetapi tiba-tiba Anda memiliki banyak hal untuk dijelaskan kepada pengulas non-C ++: shared_ptr
barang apa ini ? Apa "gotcha" rumit yang rumit itu make_shared
? (Menggunakan forward-forwarding, yang memiliki beberapa kasus kegagalan dan dapat menyebabkan konstruktor "salah" dipanggil.) Mengapa metode perlu dipanggil dengan ->
, tetapi menggunakan .
dengan beberapa metode diizinkan oleh kompiler? ( shared_ptr
memiliki metode sendiri.) Jika metode itu Foo::reset(void)
ada, pengembang yang tidak waspada mungkin mencoba memanggilnya foo.reset()
, yang (jika hanya ada satu pointer bersama yang menunjuk ke instance Foo
ketika panggilan terjadi) akan menghapus memori yang mendasari dan membatalkan foo
, dan Pengembang Java sepertinya tidak akan mengalami masalah ini.
Selain itu, C ++ memiliki banyak dari perangkap yang spesifik dengan bahasa. Seperti yang bisa saya katakan, sebagian besar pengembang C ++ belajar untuk menangani perangkap ini dengan secara bertahap mengembangkan idiom mereka sendiri untuk praktik C ++ yang "aman", yang seringkali agak unik bagi mereka atau tim pengembangan mereka (lihat misalnya jawaban yang ada yang menyebutkan Google praktik pengkodean dan komentar di atasnya mengatakan bahwa "veteran C ++ berpengalaman biasanya menolak pedoman pengkodean Google"). Semua klaim bahwa bahasa itu mungkin terlalu rumit, tampaknya (dalam pengalaman saya, setidaknya), biasanya bertemu dengan beberapa variasi "yah, berhenti menggunakannya salah." Saya menyadari ini adalah pandangan yang sangat negatif dari C ++ masyarakat, dan tentu ada pengembang yang berpengalaman lebih bersedia untuk membantu bahasa-peserta didik, tapi ada tidak tampaknya menjadi pembelaan tertentu tentang misalnya perilaku yang tidak terdefinisi (lihat misalnya banyak diskusi di tautan 'perangkap' saya di atas).
Pengembang Java tidak akan sangat membantu dalam menemukan dan memperbaiki perangkap ini melalui review kode.
Anda mungkin akan diminta untuk mengonversi kode ke Java suatu hari nanti.
Ini sepenuhnya valid - patut dipuji, bahkan - untuk mencoba memperhitungkan apa yang mungkin terjadi pada kode Anda di masa depan saat Anda dalam tahap desain.
Tapi, pertama, pertimbangan khusus ini tampak seperti kemungkinan jarak jauh: kode biasanya digunakan kembali sebagaimana mestinya (misalnya Anda bisa menyambungkan sebagian atau semua kode C ++ yang berfungsi ke beberapa perangkat lunak Java masa depan menggunakan antarmuka JNI) atau ditulis ulang seluruhnya agak daripada langsung secara manual "ditranskrip".
Dan, kedua, Anda kemudian berkata,
Setiap fitur khusus bahasa C ++ (mis: multiple inheritance) harus memiliki alternatif untuk diimplementasikan di Java ....
Ini pada dasarnya membatalkan titik "convert to Java" Anda. Jika perangkat lunak ditulis dalam C ++ idiomatik dan kemudian dikonversi ke Java idiomatik, tidak ada alasan untuk berharap bahwa konversi ini akan (atau bisa!) Dilakukan dengan menerapkan pemetaan satu-ke-satu yang tepat dari fitur C ++ ke fitur Java.
Kode tanpa fitur spesifik C ++ biasanya lebih mudah dikelola.
Tidak jelas apa yang Anda maksud di sini, tapi saya sebenarnya agak setuju dengan bagian ini: kecuali Anda sangat berhati-hati, dan bahkan ketika Anda berhati-hati, fitur C ++ dapat menyebabkan masalah pemeliharaan. The C ++ FQA Lite (website kritis terhadap bahasa dan pemeluknya dari seseorang yang setidaknya tampaknya benar-benar mengerti dengan cukup baik) menyatakan bahwa
... 80% pengembang mengerti paling banyak 20% bahasa. Ini bukan 20% sama untuk orang yang berbeda, jadi jangan mengandalkan mereka untuk memahami kode masing-masing.
TOLONG DICATAT: Jika Anda seorang penggemar C ++ dan Anda sampai pada titik ini dalam jawaban saya dan merasa cenderung untuk melompat ke komentar untuk berpendapat bahwa penulis FQA tidak benar-benar memahami C ++ atau tidak jujur dalam sebagian besar argumennya , perhatikan bahwa (1) tepat dua kalimat setelah saya mengutipnya, saya mengakui bahwa FQA adalah sumber yang sangat bias, dan (2) tidak terlalu penting untuk apa yang saya coba katakan apakah penulis FQA memahami C ++ atau tidak. , dan saya tidak mencoba untuk mem-bash C ++, dan Anda harus membaca sisa postingan tanpa berasumsi bahwa saya anti-C ++ hanya karena saya telah mengutip FQA. Akhir catatan.
Demikian pula, Linus Torvalds membenci C ++ karena alasan ini (peringatan: tautan melibatkan banyak sumpah, dalam gaya Linus yang benar-benar terkenal).
Jelas, ini sangat bias mengambil masalah ini, tetapi bahkan pendukung C ++ sering mengatakan bahwa Anda tidak boleh menggunakan keseluruhan set fitur bahasa (sekali lagi, lihat pedoman pengkodean Google; juga, Bjarne Stroustrup, pencipta C ++ , telah secara terbuka menyatakan, "Di dalam C ++, ada bahasa yang jauh lebih kecil dan lebih bersih yang berjuang untuk keluar").
Jadi saya pikir ada beberapa manfaat dengan gagasan bahwa fitur C ++ mungkin terlalu mudah untuk disalahgunakan, terutama jika Anda berasal dari latar belakang Java. Selain itu, ada baiknya untuk meringankan masalah ini dengan membatasi diri Anda ke beberapa bagian dari bahasa.
Namun, memutuskan subset mana yang akan digunakan berdasarkan bahasa yang berbeda tidak tampak seperti pendekatan yang tepat, kecuali jika "bahasa yang berbeda" adalah C, karena memang ada subset seperti-C dari bahasa C ++. (Linus menyebut ini dalam kata-katanya di atas, dan Scott Meyers bahkan menyebut subset ini sebagai "sub-bahasa.") Paradigma run-time Java (pengumpulan sampah, menjalankan pada VM) sangat berbeda dengan C ++ sehingga tidak jelas ada pelajaran berguna untuk menggambar tentang penggunaan C ++ dari itu, dan seperti yang disebutkan di atas, mencoba menggambar pelajaran tentang C ++ langsung dari Jawa dapat menyebabkan kode yang sangat non-idiomatik.
Alih-alih, cobalah untuk mendefinisikan "bagian yang dapat diterima" dari bahasa tersebut pada pemahaman tentang bagaimana bahasa tersebut dapat digunakan secara idiomatis. Jika Anda menginginkan subset yang cukup ketat yang masih memanfaatkan banyak fitur C ++ di luar apa yang ditawarkan C, pedoman Google Coding yang disebutkan di atas mungkin merupakan tempat yang baik untuk memulai. Tentu, Anda akan mendapatkan pengembang yang mengatakan bahwa "tidak ada argumen rasional" untuk beberapa batasan Google , tetapi kecuali jika Anda ingin mempekerjakan Alexandrescu jauh dari pekerjaannya pada bahasa D (yang dengan sendirinya harus memberi tahu Anda sesuatu), itu mungkin baik-baik saja. Ini tentu lebih baik daripada mencoba mengubah C ++ menjadi Java.
Titik awal lain yang baik untuk seperangkat pedoman kode adalah C + + Core Guidelines , yang sedang dalam proses oleh Bjarne Stroustrup dan Herb Sutter.
Satu-satunya cara lain untuk mengatasi kekurangan C ++ adalah memilih bahasa yang berbeda. Sepertinya Anda menyukai Java, dan Anda pikir ada kemungkinan proyek ini mungkin akan dikonversi menjadi Java pada akhirnya. Seperti disebutkan dalam jawaban lain, Anda bisa ... mulai dengan Java.
Ada dua alasan mengapa Anda mungkin benar-benar perlu menggunakan sesuatu selain Java:
- Anda benar-benar membutuhkan kinerja run-time. Dalam hal ini, memperlakukan C ++ seperti Java mungkin tidak akan benar-benar membantu Anda, karena teknik mirip Java seperti pointer-bersama menurunkan kinerja run-time Anda.
- Anda memerlukan perangkat lunak untuk bekerja pada platform yang tidak jelas yang belum mendukung JVM. Dalam hal ini, Anda mungkin terjebak dengan bahasa yang memiliki antarmuka GCC atau Dentang. C dan C ++ adalah kandidat yang jelas, tetapi Anda juga bisa melihat sesuatu seperti Rust. (Sumbat cepat: Saya belum pernah menggunakan Rust secara luas, tetapi terlihat keren dan saya ingin segera mengerjakan proyek Rust utama, dan saya pikir semua orang yang mempertimbangkan memulai proyek C ++ harus mempertimbangkan Rust sebagai alternatif.)
Setiap fitur khusus bahasa C ++ (mis: multiple inheritance) harus memiliki alternatif untuk diimplementasikan di Java. Jika tidak, itu berarti pola desain atau arsitektur kode bermasalah.
Saya sudah membahas ini agak, tapi saya sengaja mengabaikan kalimat kedua Anda.
Saya tidak yakin bahwa sesuatu seperti constexpr
, yang tidak masuk akal dalam bahasa JIT sebagian seperti Java, merupakan indikasi arsitektur yang tidak valid. Saya lebih terbuka pada gagasan bahwa penggunaan berlebihan meta-programming template mungkin lebih banyak masalah daripada nilainya, terutama sekarang yang constexpr
ada untuk melakukan evaluasi fungsi waktu kompilasi, tetapi jelas dari kasus constexpr
bahwa tidak ada cacat desain jika Anda sedang menggunakannya: Anda hanya memastikan bahwa beberapa perhitungan terjadi bahkan sebelum menjalankan kode, yang merupakan peningkatan kinerja yang luar biasa (lihat misalnya entri ini untuk masalah n-tubuh The Benchmark Game , yang mengungguli setiap entri lainnya kecuali yang lain ditulis dalam C ++,