Mengapa C ++ memiliki file header dan file .cpp?
c++
header-files
Peter Mortensen
sumber
sumber
Jawaban:
Nah, alasan utama adalah untuk memisahkan antarmuka dari implementasi. Header menyatakan "apa" yang akan dilakukan oleh suatu kelas (atau apa pun yang sedang dilaksanakan), sementara file cpp mendefinisikan "bagaimana" ia akan melakukan fitur-fitur tersebut.
Ini mengurangi dependensi sehingga kode yang menggunakan header tidak perlu mengetahui semua detail implementasi dan setiap kelas / header lainnya yang diperlukan hanya untuk itu. Ini akan mengurangi waktu kompilasi dan juga jumlah kompilasi yang dibutuhkan ketika sesuatu dalam implementasi berubah.
Ini tidak sempurna, dan Anda biasanya menggunakan teknik seperti Pimpl Idiom untuk memisahkan antarmuka dan implementasi dengan benar, tetapi ini adalah awal yang baik.
sumber
Kompilasi C ++
Kompilasi dalam C ++ dilakukan dalam 2 fase utama:
Yang pertama adalah kompilasi file teks "sumber" menjadi file "objek" biner: File CPP adalah file yang dikompilasi dan dikompilasi tanpa sepengetahuan tentang file CPP lainnya (atau bahkan perpustakaan), kecuali diumpankan melalui deklarasi mentah atau inklusi tajuk. File CPP biasanya dikompilasi menjadi file .OBJ atau .O "object".
Yang kedua adalah menghubungkan bersama semua file "objek", dan dengan demikian, pembuatan file biner akhir (baik perpustakaan atau file yang dapat dieksekusi).
Di mana HPP cocok dalam semua proses ini?
File CPP kesepian yang buruk ...
Kompilasi setiap file CPP independen dari semua file CPP lainnya, yang berarti bahwa jika A.CPP memerlukan simbol yang didefinisikan dalam B.CPP, seperti:
Itu tidak akan dikompilasi karena A.CPP tidak memiliki cara untuk mengetahui "doSomethingElse" ada ... Kecuali ada deklarasi di A.CPP, seperti:
Kemudian, jika Anda memiliki C.CPP yang menggunakan simbol yang sama, Anda kemudian menyalin / menempelkan deklarasi ...
ALERT COPY / PASTE!
Ya, ada masalah. Salinan / pasta berbahaya, dan sulit untuk dipelihara. Yang berarti itu akan keren jika kita punya cara untuk TIDAK menyalin / menempel, dan masih mendeklarasikan simbol ... Bagaimana kita bisa melakukannya? Dengan menyertakan beberapa file teks, yang biasanya diakhiri dengan .h, .hxx, .h ++ atau, saya lebih suka untuk file C ++, .hpp:
Bagaimana cara
include
kerjanya?Termasuk sebuah file, pada dasarnya, akan menguraikan dan kemudian menyalin-menempelkan isinya dalam file CPP.
Misalnya, dalam kode berikut, dengan header A.HPP:
... sumber B.CPP:
... akan menjadi setelah dimasukkan:
Satu hal kecil - mengapa menyertakan B.HPP dalam B.CPP?
Dalam kasus saat ini, ini tidak diperlukan, dan B.HPP memiliki
doSomethingElse
deklarasi fungsi, dan B.CPP memilikidoSomethingElse
definisi fungsi (yang dengan sendirinya merupakan deklarasi). Tetapi dalam kasus yang lebih umum, di mana B.HPP digunakan untuk deklarasi (dan kode inline), mungkin tidak ada definisi yang sesuai (misalnya, enum, struct polos, dll.), Sehingga menyertakan bisa diperlukan jika B.CPP menggunakan deklarasi tersebut dari B.HPP. Semua dalam semua, itu adalah "selera yang baik" untuk suatu sumber untuk memasukkan secara default tajuknya.Kesimpulan
Karena itu file header diperlukan, karena kompilator C ++ tidak dapat mencari deklarasi simbol saja, dan karenanya, Anda harus membantunya dengan menyertakan deklarasi tersebut.
Satu kata terakhir: Anda harus meletakkan pelindung tajuk di sekitar konten file HPP Anda, untuk memastikan beberapa inklusi tidak merusak apa pun, tetapi semuanya, saya yakin alasan utama keberadaan file HPP dijelaskan di atas.
atau bahkan lebih sederhana
sumber
You still have to copy paste the signature from header file to cpp file, don't you?
Tidak perlu. Selama CPP "memasukkan" HPP, precompiler akan secara otomatis melakukan copy-paste dari isi file HPP ke dalam file CPP. Saya memperbarui jawaban untuk mengklarifikasi itu.While compiling A.cpp, compiler knows the types of arguments and return value of doSomethingElse from the call itself
. Tidak, tidak. Ia hanya tahu jenis yang disediakan oleh pengguna, yang akan, separuh waktu, bahkan tidak akan repot-repot membaca nilai pengembalian. Kemudian, konversi implisit terjadi. Dan kemudian, ketika Anda memiliki kode:,foo(bar)
Anda bahkan tidak bisa memastikanfoo
apakah fungsinya. Jadi kompiler harus memiliki akses ke informasi dalam header untuk memutuskan apakah sumber mengkompilasi dengan benar, atau tidak ... Kemudian, setelah kode dikompilasi, tautan hanya akan menghubungkan fungsi panggilan.Seems, they're just a pretty ugly arbitrary design.
: Jika C ++ telah dibuat pada 2012, memang. Tapi ingat C ++ dibangun di atas C pada 1980-an, dan pada saat itu, kendala sangat berbeda pada waktu itu (IIRC, diputuskan untuk tujuan adopsi untuk menjaga linker yang sama dari C).foo(bar)
adalah fungsi - jika itu diperoleh sebagai pointer? Bahkan, berbicara tentang desain yang buruk, saya menyalahkan C, bukan C ++. Saya benar-benar tidak suka beberapa kendala dari murni C, seperti memiliki file header atau memiliki fungsi mengembalikan satu dan hanya satu nilai, sambil mengambil beberapa argumen pada input (bukankah terasa alami untuk memiliki input dan output berperilaku dengan cara yang sama ; mengapa banyak argumen, tetapi output tunggal?) :)Why can't I be sure, that foo(bar) is a function
foo bisa berupa tipe, jadi Anda akan memiliki konstruktor kelas yang dipanggil.In fact, speaking of bad design, I blame C, not C++
: Saya bisa menyalahkan C untuk banyak hal, tetapi dirancang pada tahun 70-an tidak akan menjadi salah satunya. Sekali lagi, kendala waktu itu ...such as having header files or having functions return one and only one value
: Tuples dapat membantu mengurangi itu, serta melewati argumen dengan referensi. Sekarang, apa yang akan menjadi sintaks untuk mengambil kembali beberapa nilai, dan apakah layak untuk mengubah bahasa?Karena C, tempat konsep itu berasal, berusia 30 tahun, dan saat itu, itu adalah satu-satunya cara yang layak untuk menautkan kode bersama dari beberapa file.
Hari ini, ini adalah hack yang mengerikan yang benar-benar menghancurkan waktu kompilasi di C ++, menyebabkan banyak dependensi yang tidak perlu (karena definisi kelas dalam file header mengekspos terlalu banyak informasi tentang implementasi), dan seterusnya.
sumber
Karena di C ++, kode yang dapat dieksekusi akhir tidak membawa informasi simbol, itu kode mesin lebih atau kurang murni.
Dengan demikian, Anda memerlukan cara untuk menggambarkan antarmuka sepotong kode, yang terpisah dari kode itu sendiri. Deskripsi ini ada di file header.
sumber
Karena C ++ mewarisi mereka dari C. Sayangnya.
sumber
Karena orang-orang yang mendesain format perpustakaan tidak ingin "menyia-nyiakan" ruang untuk informasi yang jarang digunakan seperti makro preprocessor C dan deklarasi fungsi.
Karena Anda memerlukan info itu untuk memberi tahu kompiler Anda "fungsi ini tersedia nanti ketika linker melakukan tugasnya", mereka harus membuat file kedua di mana informasi yang dibagikan ini dapat disimpan.
Sebagian besar bahasa setelah C / C ++ menyimpan informasi ini dalam output (Java bytecode, misalnya) atau mereka tidak menggunakan format yang dikompilasi sama sekali, selalu didistribusikan dalam bentuk sumber dan kompilasi dengan cepat (Python, Perl).
sumber
Ini adalah cara preprocessor untuk mendeklarasikan antarmuka. Anda menempatkan antarmuka (deklarasi metode) ke dalam file header, dan implementasinya ke cpp. Aplikasi yang menggunakan perpustakaan Anda hanya perlu mengetahui antarmuka, yang dapat mereka akses melalui #include.
sumber
Seringkali Anda ingin memiliki definisi antarmuka tanpa harus mengirimkan seluruh kode. Misalnya, jika Anda memiliki perpustakaan bersama, Anda akan mengirimkan file header dengan itu yang mendefinisikan semua fungsi dan simbol yang digunakan di perpustakaan bersama. Tanpa file header, Anda harus mengirimkan sumbernya.
Dalam satu proyek, file header digunakan, IMHO, untuk setidaknya dua tujuan:
sumber
Menanggapi jawaban MadKeithV ,
Alasan lain adalah bahwa header memberikan id unik untuk setiap kelas.
Jadi jika kita punya sesuatu seperti
Kami akan memiliki kesalahan, ketika kami mencoba membangun proyek, karena A adalah bagian dari B, dengan header kami akan menghindari sakit kepala semacam ini ...
sumber