Apakah saya harus memasukkan include di file header atau file sumber? Jika file header berisi pernyataan include, maka jika saya menyertakan file header itu di sumber saya, apakah file sumber saya akan memiliki semua file yang disertakan yang ada di header saya? Atau haruskah saya memasukkannya hanya dalam file sumber saya?
107
Jawaban:
Hanya letakkan include di header jika header itu sendiri membutuhkannya.
Contoh:
size_t
. Kemudian#include <stddef.h>
di file header .strlen
. Kemudian#include <string.h>
di file sumber .sumber
size_t
?size_t
ataustd::string
?Ada sedikit ketidaksepakatan tentang ini selama bertahun-tahun. Pada suatu waktu, sudah menjadi tradisi bahwa header hanya mendeklarasikan apa yang ada di modul apa pun yang terkait dengannya, begitu banyak header memiliki persyaratan khusus sehingga Anda
#include
memiliki sekumpulan header tertentu (dalam urutan tertentu). Beberapa programmer C yang sangat tradisional masih mengikuti model ini (secara religius, setidaknya dalam beberapa kasus).Baru-baru ini, ada pergerakan untuk membuat sebagian besar tajuk berdiri sendiri. Jika tajuk itu membutuhkan sesuatu yang lain, tajuk itu sendiri yang menanganinya, memastikan bahwa apa pun yang dibutuhkannya disertakan (dalam urutan yang benar, jika ada masalah pengurutan). Secara pribadi, saya lebih suka ini - terutama ketika urutan tajuk bisa menjadi penting, ini memecahkan masalah sekali, daripada meminta semua orang yang menggunakannya untuk memecahkan masalah lagi.
Perhatikan bahwa kebanyakan header hanya berisi deklarasi. Ini berarti menambahkan tajuk yang tidak perlu seharusnya (biasanya) berdampak pada eksekusi akhir Anda. Hal terburuk yang terjadi adalah sedikit memperlambat kompilasi.
sumber
#include
S Anda harus berupa file header, dan setiap file (sumber atau header) harus#include
berupa file header yang dibutuhkannya. File header harus file#include
header minimum yang diperlukan, dan file sumber juga harus, meskipun tidak sepenting file sumber.File sumber akan memiliki header itu
#include
, dan headernya#include
, dan seterusnya hingga kedalaman bersarang maksimum. Inilah sebabnya mengapa Anda tidak ingin kelebihan#include
dalam file header: mereka dapat menyebabkan file sumber menyertakan banyak file header yang mungkin tidak diperlukan, memperlambat kompilasi.Ini berarti sangat mungkin file header disertakan dua kali, dan itu bisa menjadi masalah. Metode tradisionalnya adalah dengan meletakkan "include guards" di file header, seperti ini untuk file foo.h:
sumber
Pendekatan yang telah saya kembangkan selama lebih dari dua puluh tahun adalah ini;
Pertimbangkan perpustakaan.
Ada beberapa file C, satu file H internal dan satu file H eksternal. File C menyertakan file H. internal. File H internal menyertakan file H eksternal.
Anda melihat bahwa dari POV kompiler, saat ia mengkompilasi file C, ada hierarki;
eksternal -> internal -> kode C.
Ini adalah urutan yang benar, karena yang eksternal adalah semua yang dibutuhkan pihak ketiga untuk menggunakan perpustakaan. Yang internal diperlukan untuk mengkompilasi kode C.
sumber
Jika file header A
#includes
sundulan file B dan C, maka setiap file sumber yang#includes
A akan juga mendapatkan B dan C#included
. Pra-prosesor secara harfiah hanya melakukan substitusi teks: di mana pun ia menemukan teks yang mengatakan#include <foo.h>
ia menggantikannya dengan teksfoo.h
file.Ada beberapa pendapat berbeda tentang apakah Anda harus memasukkan
#includes
header atau file sumber. Secara pribadi, saya lebih suka meletakkan semua#includes
dalam file sumber secara default, tetapi file header apa pun yang tidak dapat dikompilasi tanpa header prasyarat lainnya harus#include
header itu sendiri.Dan setiap file header harus berisi penjaga penyertaan untuk mencegahnya disertakan beberapa kali.
sumber
Di beberapa lingkungan, kompilasi akan menjadi tercepat jika seseorang hanya menyertakan file header yang dibutuhkan. Di lingkungan lain, kompilasi akan dioptimalkan jika semua file sumber dapat menggunakan kumpulan header utama yang sama (beberapa file mungkin memiliki header tambahan di luar subset umum). Idealnya, tajuk harus dibuat sehingga beberapa operasi #include tidak akan berpengaruh. Mungkin bagus untuk mengapit pernyataan #include dengan pemeriksaan file-to-be-Included's include-guard, meskipun hal itu menciptakan ketergantungan pada format penjaga itu. Lebih lanjut, bergantung pada perilaku cache file sistem, #include yang tidak perlu yang targetnya # ifdef'ed seluruhnya mungkin tidak butuh waktu lama.
Hal lain yang perlu dipertimbangkan adalah jika suatu fungsi membawa pointer ke struct, seseorang dapat menulis prototipe sebagai
tanpa definisi untuk BAR_s harus berada dalam cakupan. Pendekatan yang sangat berguna untuk menghindari penyertaan yang tidak perlu.
PS - di banyak proyek saya, akan ada file yang diharapkan setiap modul akan #include, berisi hal-hal seperti typedefs untuk ukuran integer dan beberapa struktur dan kesatuan umum [mis.
(Ya, saya tahu saya akan mendapat masalah jika saya pindah ke arsitektur big-endian, tetapi karena kompiler saya tidak mengizinkan struct anonim dalam serikat, menggunakan pengidentifikasi bernama untuk byte dalam serikat akan mengharuskan mereka diakses sebagai theUnion.b.b1 dll. yang tampaknya agak mengganggu.
sumber
Buat semua file Anda agar dapat dibuat hanya menggunakan apa yang disertakan. Jika Anda tidak perlu menyertakan di header Anda, hapuslah. Dalam proyek besar jika Anda tidak mempertahankan disiplin ini, Anda membiarkan diri Anda terbuka untuk merusak seluruh build ketika seseorang menghapus penyertaan dari file header yang digunakan oleh konsumen file itu dan bahkan tidak oleh header.
sumber
File sumber Anda akan memiliki pernyataan include jika Anda meletakkannya di header. Namun, dalam beberapa kasus, akan lebih baik untuk meletakkannya di file sumber.
Ingat bahwa jika Anda menyertakan tajuk itu di sumber lain, mereka juga akan mendapatkan penyertaan dari tajuk, dan itu tidak selalu diinginkan. Anda hanya boleh memasukkan barang di tempat yang digunakan.
sumber
Anda hanya boleh menyertakan file di header yang Anda perlukan untuk mendeklarasikan konstanta dan deklarasi fungsi. Secara teknis, penyertaan ini juga akan disertakan dalam file sumber Anda, tetapi demi kejelasan, Anda hanya perlu menyertakan file yang benar-benar perlu Anda gunakan di setiap file. Anda juga harus melindunginya di header Anda dari beberapa penyertaan sebagai berikut:
Ini mencegah header dimasukkan beberapa kali, mengakibatkan kesalahan compiler.
sumber