C ++ Header files design: sama seperti mendefinisikan API?

8

Saya agak baru dalam pengembangan perangkat lunak skala besar di C ++, dan saya bertanya-tanya di sisi desain.

Saya membaca pertanyaan ini , dan saya pikir, secara keseluruhan, setelah kami melewati definisi konstan dan hal-hal sepele lainnya, file header C ++ hanyalah definisi API :

Mereka menentukan apa yang bisa digunakan oleh programmer lain (atau diri Anda dari modul lain) (kelas, fungsi publik), tetapi tidak ada kelas atau fungsi pribadi yang harus didefinisikan di dalamnya. Ini seperti file header yang mendefinisikan abstraksi (antarmuka ...) dan file sumber mengimplementasikannya. Setelah file sumber dikompilasi, detail implementasi disembunyikan, dan tetap menjadi header yang tersedia untuk umum yang mendefinisikan apa yang dapat dilakukan modul.

Saya merasa pandangan tentang pemisahan file sumber / header ini jauh lebih mudah dipahami dan diikuti daripada penjelasan yang biasa, karena Anda hanya bisa berpikir "akan XXXtersedia materi API untuk umum, atau apakah ini merupakan detail pembuatan sosis untuk disembunyikan di dalam file sumber yang dirahasiakan? "

Apakah model mental file header saya kira-kira benar? Apa yang saya lewatkan?

Jiby
sumber
Lihat juga UML untuk sistem yang dibuat untuk membantu merancang perangkat lunak - kelasnya menunjukkan metode dan data API (atribut) dalam diagram kelas
gbjbaanb
Oh percayalah, saya tahu tentang UML! = p Ini hanya cara berpikir C ++ yang membuat saya kesulitan membungkus kepala saya. Saya "berasal dari dunia Python", dengan semua bias berpikir "Mengapa bahasa membutuhkan file header?" =)
Jiby

Jawaban:

10

Ini bukan model mental yang buruk untuk digunakan sebagai panduan tetapi sayangnya karena alasan historis / teknis header C ++ mengacaukan antarmuka dan implementasi dengan cara yang model mental sederhana ini tidak sepenuhnya menangkap.

Untuk membuat keputusan desain fisik yang baik ketika segala sesuatunya menjadi sedikit lebih kompleks, umumnya perlu untuk memahami cara header bekerja di C ++ pada tingkat yang lebih rinci.

Untuk memberikan contoh: dari tampilan API Anda, file header tidak boleh menyertakan definisi kelas implementasi pribadi. Namun dalam praktiknya, definisi kelas seperti itu akan sering muncul dalam file header karena kompiler perlu mengetahui ukurannya jika terkandung dalam kelas publik apa pun. Ada teknik untuk memecah ketergantungan seperti ini tetapi mereka umumnya membebankan biaya dalam hal kompleksitas kode, kinerja atau keduanya. Memahami kapan saat yang tepat untuk menggunakan salah satu dari teknik ini membutuhkan pemahaman yang lebih dalam tentang bagaimana header bekerja di C ++.

mattnewport
sumber
Saya sedang memikirkan definisi maju dari kelas privat: dapatkah kita menipu dengan meletakkannya di file header "tersembunyi" yang terpisah dan memasukkannya? Dengan cara ini Anda akan menyimpan "header API biasa" dan "trik pribadi kotor". Tidak yakin itu akan melakukan banyak hal baik.
Jiby
@ Jiby Header "detail" yang terpisah adalah cara yang cukup umum untuk membagi detail implementasi pribadi jadi ya, itu bisa menjadi pendekatan yang baik. Ini juga cukup umum untuk meletakkan detail implementasi di detailnamespace bersarang sehingga mereka tidak mencemari namespace perpustakaan utama dan untuk memperjelas mereka tidak dimaksudkan untuk digunakan secara langsung.
mattnewport
3

Cukup banyak, ada sedikit perbedaan antara file header dan antarmuka seperti yang digunakan oleh bahasa lain untuk bagian utama. Meskipun ada perbedaan dalam implementasi karena header juga akan berisi informasi pribadi, tetapi pada dasarnya mereka digunakan untuk menggambarkan fitur-fitur yang akan disediakan oleh kelas atau modul.

Di satu sisi kemudian, ini juga merupakan model mental dari struktur data yang dikombinasikan dengan API sehingga bisa lebih berguna ketika Anda melakukan jenis desain awal yang Anda jelaskan.

Idealnya sebuah header yang mendefinisikan API hanya akan berisi antarmuka murni tetapi karena C ++ tidak memiliki ABI, ini tidak terlalu penting. Jika Anda membangun sistem tingkat yang lebih tinggi yang menyediakan antarmuka klien murni, Anda akan menggunakan mekanisme yang berbeda seperti IDL atau WSDL untuk mendefinisikannya.

gbjbaanb
sumber
2
Lihat juga: Pointer-to-implementasi idiom
rwong
-1

File header sebagai antarmuka murni berfungsi kurang lebih baik dengan kelas. Segera setelah template muncul, model ini berhenti berfungsi apa pun. Templat tidak dapat dikompilasi, dan seluruh implementasi templat harus muncul di header.

pengguna58697
sumber
Bisakah kita menipu dengan menulis kode terkait templat di header terpisah dan memasukkannya?
Jiby