Mengapa C ++ tidak memiliki refleksi?


337

Ini adalah pertanyaan yang agak aneh. Tujuan saya adalah untuk memahami keputusan desain bahasa dan untuk mengidentifikasi kemungkinan refleksi dalam C ++.

  1. Mengapa komite bahasa C ++ tidak menerapkan refleksi dalam bahasa? Apakah refleksi terlalu sulit dalam bahasa yang tidak berjalan di mesin virtual (seperti java)?

  2. Jika seseorang menerapkan refleksi untuk C ++, apa yang akan menjadi tantangan?

Saya kira penggunaan refleksi sudah terkenal: editor dapat lebih mudah ditulis, kode program akan lebih kecil, tiruan dapat dihasilkan untuk tes unit dan sebagainya. Tapi alangkah baiknya jika Anda bisa mengomentari penggunaan refleksi juga.

Jawaban:


631

Ada beberapa masalah dengan refleksi di C ++.

  • Banyak pekerjaan yang harus ditambahkan, dan komite C ++ cukup konservatif, dan tidak menghabiskan waktu untuk fitur baru yang radikal kecuali mereka yakin itu akan membayar. (Sebuah saran untuk menambahkan sistem modul yang mirip dengan .NET rakitan telah dibuat, dan sementara saya pikir ada konsensus umum yang akan menyenangkan untuk dimiliki, itu bukan prioritas utama mereka saat ini, dan telah didorong kembali sampai setelah C ++ 0x Motivasi untuk fitur ini adalah untuk menyingkirkan #includesistem, tetapi juga akan mengaktifkan setidaknya beberapa metadata).

  • Anda tidak membayar apa yang tidak Anda gunakan. Itulah salah satu keharusan filosofi desain dasar yang mendasari C ++. Mengapa kode saya harus membawa metadata jika saya tidak pernah membutuhkannya? Selain itu, penambahan metadata dapat menghambat kompiler untuk mengoptimalkan. Mengapa saya harus membayar biaya itu dalam kode saya jika saya mungkin tidak pernah membutuhkan metadata itu?

  • Yang membawa kita ke titik besar lain: C ++ membuat sangat sedikit jaminan tentang kode yang dikompilasi. Kompiler diperbolehkan untuk melakukan hampir semua hal yang disukainya, asalkan fungsionalitas yang dihasilkan sesuai dengan yang diharapkan. Misalnya, kelas Anda tidak diharuskan benar - benar ada di sana . Kompiler dapat mengoptimalkannya, sebariskan semua yang mereka lakukan, dan sering kali hanya melakukannya, karena bahkan kode templat sederhana cenderung membuat beberapa contoh templat. Pustaka standar C ++ bergantung pada optimisasi agresif ini. Functors hanya performant jika overhead instantiating dan destructing objek dapat dioptimalkan. operator[]pada vektor hanya sebanding dengan pengindeksan array mentah dalam kinerja karena seluruh operator dapat digarisbawahi dan dengan demikian dihapus seluruhnya dari kode yang dikompilasi. C # dan Java membuat banyak jaminan tentang output dari kompiler. Jika saya mendefinisikan kelas di C #, maka kelas itu akan ada di perakitan yang dihasilkan. Bahkan jika saya tidak pernah menggunakannya. Bahkan jika semua panggilan ke fungsi anggotanya dapat diuraikan. Kelas harus ada di sana, sehingga refleksi dapat menemukannya. Sebagian dari ini diringankan oleh kompilasi C # menjadi bytecode, yang berarti kompiler JIT dapathapus definisi kelas dan fungsi sebaris jika suka, bahkan jika kompiler C # awal tidak bisa. Di C ++, Anda hanya memiliki satu kompiler, dan harus mengeluarkan kode yang efisien. Jika Anda diizinkan untuk memeriksa metadata dari eksekusi C ++, Anda akan berharap untuk melihat setiap kelas yang didefinisikan, yang berarti bahwa kompiler harus melestarikan semua kelas yang ditentukan, bahkan jika mereka tidak diperlukan.

  • Dan kemudian ada template. Templat di C ++ tidak seperti generik dalam bahasa lain. Setiap instantiasi template membuat tipe baru . std::vector<int>adalah kelas yang sepenuhnya terpisah dari std::vector<float>. Itu menambahkan hingga banyak jenis berbeda di seluruh program. Apa yang harus dilihat oleh refleksi kita? The Template std::vector ? Tetapi bagaimana bisa, karena itu adalah konstruksi kode sumber, yang tidak memiliki arti pada saat runtime? Itu harus melihat kelas yang terpisah std::vector<int>dan std::vector<float>. Dan std::vector<int>::iteratordan std::vector<float>::iterator, sama untukconst_iteratordan seterusnya. Dan begitu Anda masuk ke metaprogramming template, Anda dengan cepat berakhir instantiating ratusan template, yang semuanya mendapatkan inline dan dihapus lagi oleh kompiler. Mereka tidak memiliki arti, kecuali sebagai bagian dari program metap-waktu kompilasi. Haruskah semua ratusan kelas ini terlihat oleh refleksi? Mereka harus, karena kalau tidak refleksi kita tidak akan berguna, jika itu bahkan tidak menjamin bahwa kelas yang saya definisikan akan benar - benar ada . Dan masalah sampingannya adalah bahwa kelas template tidak ada sampai instantiated. Bayangkan sebuah program yang digunakan std::vector<int>. Haruskah sistem refleksi kita dapat melihat std::vector<int>::iterator? Di satu sisi, Anda tentu mengharapkannya. Ini adalah kelas yang penting, dan itu didefinisikan dalam hal std::vector<int>, yang berlakuada di metadata. Di sisi lain, jika program tidak pernah benar-benar menggunakan templat kelas iterator ini, tipenya tidak akan pernah instantiated, dan kompiler tidak akan membuat kelas di tempat pertama. Dan sudah terlambat untuk membuatnya saat runtime, karena membutuhkan akses ke kode sumber.

  • Dan akhirnya, refleksi tidak begitu vital di C ++ seperti di C #. Alasannya lagi, templat metaprogramming. Itu tidak bisa menyelesaikan semuanya, tetapi untuk banyak kasus di mana Anda seharusnya menggunakan refleksi, dimungkinkan untuk menulis sebuah program metap yang melakukan hal yang sama pada waktu kompilasi. boost::type_traitsadalah contoh sederhana. Anda ingin tahu tentang tipe T? Periksa itu type_traits. Di C #, Anda harus memancing setelah mengetik menggunakan refleksi. Refleksi masih akan berguna untuk beberapa hal (penggunaan utama yang dapat saya lihat, yang tidak dapat dengan mudah diganti oleh metaprogramming, adalah untuk kode serialisasi yang di-autogenerasi), tetapi itu akan membawa beberapa biaya signifikan untuk C ++, dan itu tidak perlu sesering mungkin dalam bahasa lain.

Sunting: Menanggapi komentar:

cdleary: Ya, simbol debug melakukan sesuatu yang serupa, karena mereka menyimpan metadata tentang tipe yang digunakan dalam executable. Tetapi mereka juga menderita dari masalah yang saya jelaskan. Jika Anda pernah mencoba debug versi rilis, Anda akan tahu apa yang saya maksud. Ada kesenjangan logis besar di mana Anda membuat kelas dalam kode sumber, yang telah diuraikan dalam kode akhir. Jika Anda menggunakan refleksi untuk sesuatu yang berguna, Anda perlu membuatnya lebih dapat diandalkan dan konsisten. Karena itu, tipe akan menghilang dan menghilang hampir setiap kali Anda kompilasi. Anda mengubah sedikit detail kecil, dan kompilator memutuskan untuk mengubah tipe mana yang dimasukkan dan mana yang tidak, sebagai respons. Bagaimana Anda mengekstrak sesuatu yang berguna dari itu, ketika Anda apakah bahkan tidak dijamin bahwa jenis yang paling relevan akan terwakili dalam metadata Anda? Jenis yang Anda cari mungkin ada di versi terakhir, tetapi sekarang sudah tidak ada. Dan besok, seseorang akan memeriksa perubahan kecil yang tidak bersalah ke fungsi kecil yang tidak bersalah, yang membuat jenisnya cukup besar sehingga tidak akan sepenuhnya diuraikan, sehingga akan kembali lagi. Itu masih berguna untuk simbol debug, tetapi tidak lebih dari itu. Aku benci mencoba membuat kode serialisasi untuk kelas berdasarkan ketentuan-ketentuan itu. tapi tidak lebih dari itu. Aku benci mencoba membuat kode serialisasi untuk kelas berdasarkan ketentuan-ketentuan itu. tapi tidak lebih dari itu. Aku benci mencoba membuat kode serialisasi untuk kelas berdasarkan ketentuan-ketentuan itu.

Evan Teran: Tentu saja masalah ini dapat diselesaikan. Tapi itu kembali ke poin saya # 1. Dibutuhkan banyak pekerjaan, dan komite C ++ memiliki banyak hal yang mereka anggap lebih penting. Apakah manfaat mendapatkan beberapa refleksi terbatas (dan itu akan terbatas) di C ++ benar-benar cukup besar untuk membenarkan fokus pada hal itu dengan mengorbankan fitur lain? Apakah benar-benar ada manfaat besar dalam menambahkan fitur bahasa inti yang sudah (sebagian besar) dapat dilakukan melalui perpustakaan dan preprosesor seperti QT? Mungkin, tetapi kebutuhannya jauh kurang mendesak daripada jika perpustakaan seperti itu tidak ada. Untuk saran spesifik Anda, saya yakin tidak mengizinkannya pada template akan membuatnya sama sekali tidak berguna. Anda tidak dapat menggunakan refleksi di perpustakaan standar, misalnya. Refleksi seperti apa yang tidakstd::vector? Template adalah bagian besar dari C ++. Fitur yang tidak berfungsi pada templat pada dasarnya tidak berguna.

Tapi Anda benar, beberapa bentuk refleksi bisa diterapkan. Tapi itu akan menjadi perubahan besar dalam bahasa. Seperti sekarang, jenis secara eksklusif membangun waktu kompilasi. Mereka ada untuk kepentingan kompiler, dan tidak ada yang lain. Setelah kode telah disusun, ada yang tidak ada kelas. Jika Anda meregangkan diri, Anda bisa berpendapat bahwa fungsi masih ada, tetapi sungguh, semua yang ada hanyalah kumpulan instruksi assembler lompatan, dan banyak tumpukan dorong / pop. Tidak banyak yang bisa dilanjutkan, ketika menambahkan metadata seperti itu.

Tapi seperti yang saya katakan, ada proposal untuk perubahan pada model kompilasi, menambahkan modul mandiri, menyimpan metadata untuk tipe tertentu, memungkinkan modul lain untuk merujuk mereka tanpa harus mengacaukan #includes. Itu awal yang baik, dan sejujurnya, saya terkejut komite standar tidak hanya membuang proposal karena perubahan yang terlalu besar. Jadi mungkin dalam 5-10 tahun? :)


2
Bukankah sebagian besar masalah ini sudah harus diselesaikan dengan simbol debug? Bukan berarti itu akan menjadi performant (karena inlining dan optimasi yang Anda sebutkan), tapi Anda bisa memungkinkan untuk kemungkinan refleksi dengan melakukan simbol-simbol debug apapun lakukan.
cdleary

2
Hal lain tentang poin pertama Anda: sejauh yang saya tahu tidak ada yang mencoba menambahkan refleksi ke implementasi C ++. Tidak ada pengalaman bagus dengannya. Komite mungkin akan enggan untuk memimpin, terutama setelah exportdan vector<bool>.
David Thornley

18
Saya setuju bahwa C ++ seharusnya tidak menjalankan refleksi waktu. Tetapi kompilasi refleksi waktu memiliki beberapa masalah di atas, dan dapat digunakan bagi seseorang untuk membangun refleksi waktu berjalan pada kelas-kelas tertentu jika mereka mau. Mampu mengakses jenis dan nama dan fitur metode ke-n dan induk ke-n dari suatu kelas melalui templat? Dan dapatkan nomor seperti itu pada waktu kompilasi? Akan membuat refleksi otomatis berbasis CRTP dapat dilakukan, sementara tidak ada yang membayar untuk apa yang tidak mereka gunakan.
Yakk - Adam Nevraumont

15
Poin ketiga Anda dalam banyak hal yang paling penting: C ++ dimaksudkan agar sesuai untuk menulis kode mandiri pada platform di mana memori membutuhkan biaya; jika menghilangkan beberapa kode yang tidak digunakan akan memungkinkan program untuk masuk ke dalam mikrokontroler yang harganya $ 2,00, daripada yang harganya $ 2,50, dan jika kode akan dalam 1.000.000 unit, menghilangkan kode yang dapat menghemat $ 500.000. Tanpa refleksi, analisis statis sering dapat mengidentifikasi 90% + kode yang tidak dapat dijangkau; jika Refleksi diperbolehkan, apa pun yang dapat dihubungi melalui Refleksi harus dianggap dapat dijangkau, bahkan jika 90% tidak.
supercat

2
pasti ada sesuatu yang dapat diperbaiki dengan mudah oleh comitee, adalah untuk akhirnya mengatakan hitam putih yang typeinfo's name()fungsi HARUS mengembalikan nama yang diketik oleh programmer dan bukan sesuatu terdefinisi. Dan beri kami pengikat untuk enumerator juga. Ini sebenarnya penting untuk serialisasi / deserialisasi, membantu dalam pembuatan pabrik dll.
v.oddou

38

Refleksi membutuhkan beberapa metadata tentang jenis yang akan disimpan di suatu tempat yang dapat ditanyakan. Karena C ++ mengkompilasi ke kode mesin asli dan mengalami perubahan besar karena optimisasi, tampilan aplikasi tingkat tinggi cukup banyak hilang dalam proses kompilasi, akibatnya, tidak mungkin untuk meminta mereka pada saat run time. Java dan .NET menggunakan representasi tingkat yang sangat tinggi dalam kode biner untuk mesin virtual yang memungkinkan tingkat refleksi ini. Namun, dalam beberapa implementasi C ++, ada sesuatu yang disebut Run Time Type Information (RTTI) yang dapat dianggap versi refleksi yang dipreteli.


15
RTTI dalam standar C ++.
Daniel Earwicker

1
Tetapi tidak semua implementasi C ++ standar. Saya telah melihat implementasi yang tidak mendukung RTTI.
Mehrdad Afshari

3
Dan sebagian besar implementasi yang mendukung RTTI juga mendukung mematikannya melalui opsi kompiler.
Michael Kohne

21

Semua bahasa tidak boleh mencoba untuk memasukkan setiap fitur dari setiap bahasa lainnya.

C ++ pada dasarnya adalah assembler makro yang sangat, sangat canggih. Ini BUKAN (dalam arti tradisional) bahasa tingkat tinggi seperti C #, Java, Objective-C, Smalltalk, dll.

Adalah baik untuk memiliki alat yang berbeda untuk pekerjaan yang berbeda. Jika kita hanya memiliki palu, semua hal akan terlihat seperti paku, dll. Memiliki bahasa skrip berguna untuk beberapa pekerjaan, dan bahasa OO reflektif (Java, Obj-C, C #) berguna untuk kelas pekerjaan lain, dan super bahasa-telanjang-tulang dekat-ke-mesin-efisien berguna untuk kelas pekerjaan lain (C ++, C, Assembler).

C ++ melakukan pekerjaan yang luar biasa untuk memperluas teknologi Assembler ke tingkat manajemen kompleksitas yang luar biasa, dan abstraksi untuk membuat pemrograman lebih besar, tugas yang lebih kompleks sangat mungkin bagi manusia. Tetapi itu tidak selalu merupakan bahasa yang paling cocok untuk mereka yang mendekati masalah mereka dari perspektif tingkat tinggi (Lisp, Smalltalk, Java, C #). Jika Anda membutuhkan bahasa dengan fitur-fitur tersebut untuk mengimplementasikan solusi terbaik untuk masalah Anda, maka terima kasih kepada mereka yang telah membuat bahasa seperti itu untuk kita semua gunakan!

Tetapi C ++ adalah untuk mereka yang, untuk alasan apa pun, perlu memiliki korelasi yang kuat antara kode mereka dan operasi mesin yang mendasarinya. Baik efisiensinya, atau driver perangkat pemrograman, atau interaksi dengan layanan OS tingkat rendah, atau apa pun, C ++ lebih cocok untuk tugas-tugas itu.

C #, Java, Objective-C semuanya membutuhkan sistem runtime yang lebih besar dan lebih kaya untuk mendukung eksekusi mereka. Runtime itu harus dikirimkan ke sistem yang dipermasalahkan - sudah diinstal sebelumnya untuk mendukung pengoperasian perangkat lunak Anda. Dan layer itu harus dipertahankan untuk berbagai sistem target, dikustomisasi oleh BEBERAPA BAHASA LAIN untuk membuatnya bekerja pada platform itu. Dan lapisan tengah itu - lapisan adaptif antara OS host dan kode Anda - runtime, hampir selalu ditulis dalam bahasa seperti C atau C ++ di mana efisiensinya adalah # 1, di mana pemahaman dapat diprediksi interaksi yang tepat antara perangkat lunak dan perangkat keras dapat dengan baik dipahami, dan dimanipulasi untuk mendapatkan hasil maksimal.

Saya suka Smalltalk, Objective-C, dan memiliki sistem runtime yang kaya dengan refleksi, meta-data, pengumpulan sampah, dll. Kode yang luar biasa dapat ditulis untuk memanfaatkan fasilitas ini! Tapi itu hanyalah lapisan yang lebih tinggi pada tumpukan, lapisan yang harus bersandar pada lapisan yang lebih rendah, yang pada akhirnya harus berada di atas OS dan perangkat keras. Dan kita akan selalu membutuhkan bahasa yang paling cocok untuk membangun lapisan itu: C ++ / C / Assembler.

Tambahan: C ++ 11/14 terus memperluas kemampuan C ++ untuk mendukung abstraksi dan sistem tingkat tinggi. Threading, sinkronisasi, model memori yang tepat, definisi mesin abstrak yang lebih tepat memungkinkan pengembang C ++ untuk mencapai banyak abstraksi tingkat tinggi yang beberapa bahasa tingkat tinggi ini hanya digunakan untuk memiliki domain eksklusif, sambil terus menyediakan dekat dengan kinerja logam dan kemampuan prediksi yang sangat baik (yaitu subsistem runtime minimal). Mungkin fasilitas refleksi akan diaktifkan secara selektif dalam revisi C ++ di masa mendatang, bagi mereka yang menginginkannya - atau mungkin perpustakaan akan menyediakan layanan runtime seperti itu (mungkin sekarang ada, atau awal dari salah satu yang mendorong?).


Poin Anda tentang runtime bahasa yang harus dikompilasi dalam bahasa lain tidak benar dalam kasus Objective-C, karena runtime itu ditulis dalam C (yang Objective-C adalah superset dari).
Richard J. Ross III

Itu perbedaan tanpa perbedaan. Apa bedanya, ketika pada akhirnya, subsistem runtime yang digunakan Objective-C sebenarnya tidak ditulis dalam Objective-C, melainkan dalam C?
Mordachai

3
Maafkan saya; tetapi selama Anda menautkannya dengan benar, Anda dapat mengkompilasi program objektif-c di C, pada kenyataannya saya melakukannya di sini: stackoverflow.com/a/10290255/427309 . Seluruh pernyataan Anda di atas salah. Runtime sepenuhnya dapat diakses melalui C, dan salah satu hal yang menjadikannya bahasa dinamis yang kuat.
Richard J. Ross III

1
"C runtime" hanyalah pustaka dinamis yang berisi kode untuk pustaka standar C. Sama untuk "C ++ runtime". Ini sangat berbeda dari sistem runtime seperti itu dari Objective-C. Juga ... sementara saya kira Anda bisa secara teknis menggunakan runtime Objective-C di C, itu masih hanya sebuah program C yang menggunakan runtime Objective-C - Anda tidak dapat mengkompilasi program Objective-C yang sebenarnya di C.
celticminstrel

2
C ++ 11 memiliki model memori + atom membuatnya lebih seperti assembler portabel. Itu bukan hal-hal tingkat tinggi, mereka hal-hal tingkat rendah yang sebelumnya tidak memiliki dukungan portabel untuk C ++. Tetapi jumlah UB di C ++ jika Anda melakukan kesalahan membuatnya sangat tidak seperti bahasa berbasis VM seperti Java, dan juga tidak seperti bahasa assembly khusus. misalnya ditandatangani-overflow benar-benar UB dalam sumber C ++ dan kompiler dapat mengoptimalkan berdasarkan fakta itu bahkan jika kompilasi untuk katakanlah x86, tetapi dalam hampir semua platform itu hanya akan membungkus. C ++ modern sangat jauh dari bahasa rakitan portabel.
Peter Cordes

11

Jika Anda benar-benar ingin memahami keputusan desain seputar C ++, temukan salinan Manual Referensi C ++ Beranotasi oleh Ellis dan Stroustrup. BUKAN dengan standar terbaru, tetapi melewati standar asli dan menjelaskan cara kerja dan sering, bagaimana mereka mendapatkannya.


6
Juga Desain dan Evolusi C ++ oleh Stroustrup
James Hopkin

9

Refleksi untuk bahasa yang memilikinya adalah tentang seberapa banyak kode sumber yang bersedia ditinggalkan oleh kompiler dalam kode objek Anda untuk mengaktifkan refleksi, dan berapa banyak mesin analisis yang tersedia untuk menafsirkan informasi yang direfleksikan itu. Kecuali jika kompilator menyimpan semua kode sumber, refleksi akan terbatas dalam kemampuannya untuk menganalisis fakta yang tersedia tentang kode sumber.

Kompiler C ++ tidak menyimpan apa-apa (well, mengabaikan RTTI), jadi Anda tidak mendapatkan refleksi dalam bahasa tersebut. (Kompiler Java dan C # hanya menyimpan kelas, nama metode dan jenis kembali, sehingga Anda mendapatkan sedikit data refleksi, tetapi Anda tidak dapat memeriksa ekspresi atau struktur program, dan itu berarti bahkan dalam bahasa yang "berkemampuan refleksi" itu informasi yang Anda dapat sangat jarang dan akibatnya Anda benar-benar tidak dapat melakukan banyak analisis).

Tapi Anda bisa keluar dari bahasa dan mendapatkan kemampuan refleksi penuh. Jawaban untuk diskusi stack overflow pada refleksi di C membahas hal ini.


7

Refleksi dapat dan telah diimplementasikan dalam c ++ sebelumnya.

Ini bukan fitur c ++ asli karena memiliki biaya yang besar (memori dan kecepatan) yang tidak boleh diatur secara default oleh bahasa - bahasanya berorientasi "kinerja maksimum secara default".

Karena Anda tidak boleh membayar untuk apa yang tidak Anda butuhkan, dan seperti yang Anda katakan pada diri sendiri, itu diperlukan lebih banyak di editor daripada di aplikasi lain, maka itu harus diimplementasikan hanya di mana Anda membutuhkannya, dan tidak "dipaksa" untuk semua kode ( Anda tidak perlu merefleksikan semua data yang akan bekerja dengan Anda di editor atau aplikasi serupa lainnya).


3
dan Anda tidak mengirim simbol karena itu akan memungkinkan pelanggan / pesaing Anda untuk melihat kode Anda ... ini sering dianggap sebagai hal yang buruk.
gbjbaanb

Anda benar, saya tidak memikirkan masalah kode eksposisi :)
Klaim

6

Alasan C ++ tidak memiliki refleksi adalah karena ini membutuhkan kompiler untuk menambahkan informasi simbol ke file objek, seperti apa yang anggota kelas miliki, informasi tentang anggota, tentang fungsi dan semuanya. Ini pada dasarnya akan membuat menyertakan file tidak berguna, karena informasi yang dikirim oleh deklarasi kemudian akan dibaca dari file objek tersebut (modul kemudian). Dalam C ++, definisi tipe dapat muncul beberapa kali dalam suatu program dengan memasukkan header masing-masing (asalkan semua definisi itu sama), sehingga harus diputuskan di mana harus meletakkan informasi tentang tipe itu, seperti menyebutkan satu komplikasi di sini. Optimasi agresif yang dilakukan oleh kompiler C ++, yang dapat mengoptimalkan lusinan contoh template kelas, adalah titik kuat lainnya. Itu mungkin, tetapi karena C ++ kompatibel dengan C,


1
Saya tidak mengerti bagaimana optimasi agresif kompiler adalah poin yang kuat. Bisakah Anda menguraikan? Jika tautan dapat menghapus duplikat definisi fungsi sebaris, apa masalahnya dengan informasi refleksi duplikat? Bukankah informasi simbol ditambahkan ke file objek, untuk debugger?
Rob Kennedy

1
Masalahnya adalah bahwa informasi refleksi Anda mungkin tidak valid. Jika kompilator menghilangkan 80% dari definisi kelas Anda, apa yang akan dikatakan oleh metadata refleksi Anda? Di C # dan Java, bahasa menjamin bahwa jika Anda mendefinisikan kelas, itu tetap didefinisikan. C ++ memungkinkan kompiler mengoptimalkannya.
jalf

1
@Rob, optimisasi adalah hal lain, tidak terkait dengan komplikasi beberapa kelas. Lihat @ jalf's komentar (dan jawabannya) untuk apa yang saya maksud.
Johannes Schaub - litb

4
Jika saya instantiate mencerminkan <T>, maka jangan membuang informasi T apa pun. Ini sepertinya bukan masalah yang tidak bisa diselesaikan.
Joseph Garvin

3

Ada banyak kasus untuk menggunakan refleksi dalam C + + yang tidak dapat ditangani secara memadai menggunakan konstruksi waktu kompilasi seperti meta-pemrograman template.

N3340 mengusulkan pointer kaya sebagai cara untuk memperkenalkan refleksi dalam C ++. Di antara hal-hal lain yang dibahas adalah masalah tidak membayar fitur kecuali Anda menggunakannya.


2

Menurut Alistair Cockburn, subtyping tidak dapat dijamin dalam lingkungan yang reflektif .

Refleksi lebih relevan untuk sistem pengetikan laten. Di C ++, Anda tahu jenis apa yang Anda miliki dan Anda tahu apa yang dapat Anda lakukan dengannya.


Secara umum, kemampuan untuk memeriksa keberadaan fitur yang tidak ada tanpa memperkenalkan Perilaku Tidak Terdefinisi memungkinkan penambahan fitur tersebut ke versi kelas yang lebih baru akan mengubah perilaku yang didefinisikan dengan baik dari program yang sudah ada sebelumnya, dan akan akibatnya membuatnya mustahil untuk menjamin bahwa menambahkan fitur itu tidak akan "merusak" sesuatu.
supercat

2

Refleksi bisa opsional, seperti arahan preprosesor. Sesuatu seperti

#pragma enable reflection

Dengan begitu kita dapat memiliki yang terbaik dari kedua dunia, tanpa pragma ini perpustakaan akan dibuat tanpa refleksi (tanpa overhead seperti yang dibahas), maka akan tergantung pengembang individu apakah mereka ingin kecepatan atau kemudahan penggunaan.


2

Jika C ++ dapat memiliki:

  • data anggota kelas untuk nama variabel, tipe variabel, dan constpengubah
  • iterator argumen fungsi (hanya posisi alih-alih nama)
  • data anggota kelas untuk nama fungsi, tipe kembali, dan constpengubah
  • daftar kelas induk (dalam urutan yang sama seperti yang ditentukan)
  • data untuk anggota templat dan kelas induk; templat yang diperluas (artinya tipe aktual akan tersedia untuk API refleksi dan bukan 'informasi templat cara menuju ke sana')

Itu akan cukup untuk membuat perpustakaan yang sangat mudah digunakan pada inti dari pemrosesan data tanpa jenis yang begitu lazim dalam aplikasi web dan database saat ini (semua orme, mekanisme pengiriman pesan, parser xml / json, serialisasi data, dll).

Misalnya, informasi dasar yang didukung oleh Q_PROPERTYmakro (bagian dari Qt Framework) http://qt.nokia.com/doc/4.5/properties.html diperluas untuk mencakup metode kelas dan e) - akan sangat bermanfaat bagi C ++ dan untuk komunitas perangkat lunak secara umum.

Tentu saja refleksi yang saya maksudkan tidak akan mencakup makna semantik atau masalah yang lebih kompleks (seperti komentar nomor baris kode sumber, analisis aliran data, dll) - tetapi saya juga tidak berpikir itu diperlukan untuk menjadi bagian dari standar bahasa.


@Vlad: Ya, jika seseorang menambahkan fitur yang mendukung refleksi ke bahasa, Anda mendapatkan refleksi dalam bahasa tersebut. Ini hanya mungkin terjadi jika komite bahasa mengeluarkannya, dan saya pikir mereka belum pada tahun 2011, dan saya ragu akan ada standar C ++ lain sebelum tahun 2020 Masehi. Jadi, pemikiran yang bagus. Sementara itu, jika Anda ingin membuat kemajuan, Anda harus keluar dari C ++.
Ira Baxter


0

Refleksi dalam C ++, saya percaya sangat penting jika C ++ akan digunakan sebagai bahasa untuk Akses Database, penanganan sesi Web / http dan pengembangan GUI. Kurangnya refleksi mencegah ORM (seperti Hibernate atau LINQ), parser XML dan JSON yang meng-instancinate class, serialisasi data, dan banyak thigns lainnya (di mana data tanpa tipe awalnya harus digunakan untuk membuat instance kelas).

Pergantian waktu kompilasi yang tersedia untuk pengembang perangkat lunak selama proses pembuatan dapat digunakan untuk menghilangkan kekhawatiran 'Anda membayar untuk apa yang Anda gunakan'.

Saya seorang firmwaredeveloper tidak perlu refleksi untuk membaca data dari port serial - maka denda tidak menggunakan saklar. Tetapi sebagai pengembang basis data yang ingin terus menggunakan C ++ saya secara bertahap dihapus dengan kode yang mengerikan, sulit untuk mempertahankan yang memetakan data antara anggota data dan konstruksi basis data.

Baik serialisasi Boost maupun mekanisme lainnya tidak benar-benar menyelesaikan refleksi - itu harus dilakukan oleh kompiler - dan begitu selesai C ++ akan kembali menjadi sulit di sekolah dan digunakan dalam perangkat lunak yang berurusan dengan pemrosesan data

Bagi saya masalah ini # 1 (dan primitif threading naitive adalah masalah # 2).


4
Siapa bilang C ++ adalah untuk digunakan sebagai bahasa untuk DB Access, Web sesi hnadling atau dev gui? Ada banyak bahasa yang jauh lebih baik untuk digunakan untuk hal-hal semacam itu. Dan saklar waktu kompilasi tidak akan menyelesaikan masalah. Biasanya, keputusan untuk mengaktifkan atau menonaktifkan refleksi tidak akan berdasarkan per file. Ini bisa berfungsi jika bisa diaktifkan pada tipe individu. Jika programmer dapat menentukan dengan atribut atau serupa ketika mendefinisikan suatu tipe, apakah atau tidak metadata refleksi untuk itu harus dihasilkan. Tapi perubahan global? Anda akan melumpuhkan 90% dari kerugian hanya untuk membuat 10% lebih sederhana.
jalf

Lalu, jika saya menginginkan program yang lintas platform dan memiliki akses ke gui, apa yang harus saya gunakan? Ayunan java yang tidak fleksibel? Hanya windows C #? Tetapi kebenaran harus diceritakan, dan kebenarannya adalah bahwa ada banyak program yang dikompilasi dalam kode yang dapat dieksekusi, dan menawarkan antarmuka gui dan akses ke database, sehingga mereka harus menggunakan beberapa basis data dan dukungan gui ... Dan mereka tidak t menggunakan QT. (seharusnya dinamai MT (monster toolkit))
Coyote21

1
@ Coyote21: C # tidak hanya Windows selama bertahun-tahun. (Meskipun saya bukan penggemar Mono, ini berfungsi cukup baik untuk sebagian besar hal.) Dan Swing bukan satu-satunya toolkit GUI untuk Java. Sejujurnya, salah satu akan menjadi pilihan yang lebih baik jika Anda ingin lintas platform. C ++ hampir selalu memiliki bagian platform tertentu di sini atau di sana jika Anda melakukan sesuatu yang tidak sepele.
cHao

Tidak ada alasan mengapa Anda perlu refleksi untuk ORM. Anda dapat mencapai semua itu dengan templat. Ada banyak kerangka kerja yang menyediakan ORM untuk C ++.
MrFox

0

Ini pada dasarnya karena ini adalah "tambahan opsional". Banyak orang memilih C ++ daripada bahasa seperti Java dan C # sehingga mereka memiliki kontrol lebih besar atas keluaran kompiler, mis. Program yang lebih kecil, dan / atau lebih cepat.

Jika Anda memilih untuk menambahkan refleksi ada berbagai solusi yang tersedia .

Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.