Urutan apa yang harus dimasukkan file yang ditentukan, yaitu apa alasan untuk menyertakan satu header sebelum yang lain?
Misalnya, apakah file sistem, STL, dan Boost berjalan sebelum atau setelah file include lokal?
Urutan apa yang harus dimasukkan file yang ditentukan, yaitu apa alasan untuk menyertakan satu header sebelum yang lain?
Misalnya, apakah file sistem, STL, dan Boost berjalan sebelum atau setelah file include lokal?
Jawaban:
Saya tidak berpikir ada pesanan yang disarankan, asalkan dikompilasi! Yang menjengkelkan adalah ketika beberapa header membutuhkan header lain untuk dimasukkan terlebih dahulu ... Itu masalah dengan header itu sendiri, bukan dengan urutan menyertakan.
Preferensi pribadi saya adalah beralih dari lokal ke global, masing-masing subbagian dalam urutan abjad, yaitu:
Alasan saya untuk 1. adalah bahwa itu harus membuktikan bahwa setiap header (yang ada cpp) dapat #include
d tanpa prasyarat (terminus technicus: header adalah "mandiri"). Dan sisanya sepertinya mengalir secara logis dari sana.
Hal besar yang perlu diingat adalah bahwa tajuk Anda tidak boleh bergantung pada tajuk lainnya yang dimasukkan terlebih dahulu. Salah satu cara untuk memastikan ini adalah dengan memasukkan header Anda sebelum header lainnya.
"Berpikir dalam C ++" secara khusus menyebutkan ini, merujuk pada Lakos '"Desain Perangkat Lunak C ++ Skala Besar":
Kesalahan penggunaan laten dapat dihindari dengan memastikan bahwa file .h komponen diurai dengan sendirinya - tanpa deklarasi atau definisi yang disediakan secara eksternal ... Termasuk file .h sebagai baris pertama dari file .c memastikan bahwa tidak ada bagian penting informasi intrinsik ke antarmuka fisik komponen hilang dari file .h (atau, jika ada, Anda akan mengetahuinya segera setelah Anda mencoba untuk mengkompilasi file .c).
Artinya, termasuk dalam urutan berikut:
Jika ada header yang memiliki masalah untuk dimasukkan dalam pesanan ini, perbaiki (atau milik Anda) atau jangan gunakan. Boikot perpustakaan yang tidak menulis tajuk bersih.
Panduan gaya C ++ Google berargumen hampir secara terbalik, dengan benar-benar tidak ada pembenaran sama sekali; Saya pribadi cenderung menyukai pendekatan Lakos.
Saya mengikuti dua aturan sederhana yang menghindari sebagian besar masalah:
Saya juga mengikuti pedoman:
Dengan kata lain:
#include <stdio.h>
#include <string.h>
#include "btree.h"
#include "collect_hash.h"
#include "collect_arraylist.h"
#include "globals.h"
Meskipun, sebagai pedoman, itu adalah hal subjektif. Peraturan di sisi lain, saya tegakkan dengan kaku, bahkan sampai memberikan file header 'wrapper' dengan mencakup penjaga dan dikelompokkan termasuk jika beberapa pengembang pihak ketiga yang menjengkelkan tidak berlangganan visi saya :-)
Untuk menambahkan batu bata saya sendiri ke dinding.
Jadi saya biasanya pergi seperti ini:
// myproject/src/example.cpp
#include "myproject/example.h"
#include <algorithm>
#include <set>
#include <vector>
#include <3rdparty/foo.h>
#include <3rdparty/bar.h>
#include "myproject/another.h"
#include "myproject/specific/bla.h"
#include "detail/impl.h"
Setiap grup dipisahkan oleh garis kosong dari yang berikutnya:
Juga perhatikan bahwa, selain dari header sistem, setiap file ada dalam folder dengan nama namespace-nya, hanya karena lebih mudah untuk melacaknya dengan cara ini.
#define
's yang mengacaukan kode lain) dan untuk mencegah dependensi implisit. Sebagai contoh, jika file header basis kode kita foo.h
benar-benar bergantung pada <map>
tetapi di mana-mana itu digunakan dalam .cc
file, <map>
kebetulan sudah termasuk, kita mungkin tidak akan melihat. Sampai seseorang mencoba memasukkan foo.h
tanpa terlebih dahulu memasukkan <map>
. Dan kemudian mereka akan jengkel.
.h
memiliki paling tidak satu .cpp
yang memasukkannya terlebih dahulu (memang, dalam kode pribadi saya tes Unit terkait menyertakannya terlebih dahulu, dan kode sumber memasukkannya dalam kelompok yang sah ). Mengenai tidak terpengaruh, jika ada header yang termasuk <map>
maka semua header yang dimasukkan setelahnya dipengaruhi, jadi sepertinya kalah perang bagi saya.
Header corresponding to this cpp file first (sanity check)
. Apakah ada sesuatu yang khusus jika #include "myproject/example.h"
dipindahkan ke akhir semua termasuk?
Saya merekomendasi:
Dan tentu saja, urutan abjad dalam setiap bagian, jika memungkinkan.
Selalu gunakan deklarasi maju untuk menghindari yang tidak perlu #include
dalam file header Anda.
Saya cukup yakin ini bukan praktik yang direkomendasikan di mana pun di dunia waras, tapi saya suka sistem line termasuk oleh panjang nama file, diurutkan secara leksikal dalam panjang yang sama. Seperti itu:
#include <set>
#include <vector>
#include <algorithm>
#include <functional>
Saya pikir itu ide yang baik untuk memasukkan header Anda sendiri di depan orang lain, untuk menghindari rasa malu dari ketergantungan keteraturan.
windows.h
.
Ini tidak subyektif. Pastikan tajuk Anda tidak bergantung pada #include
d dalam urutan tertentu. Anda dapat yakin tidak masalah urutan apa yang Anda sertakan STL atau Boost header.
Pertama-tama sertakan tajuk yang sesuai dengan .cpp ... dengan kata lain, source1.cpp
harus termasuk source1.h
sebelum memasukkan hal lain. Satu-satunya pengecualian yang dapat saya pikirkan adalah ketika menggunakan MSVC dengan header yang telah dikompilasi dalam hal ini, Anda dipaksa untuk memasukkan stdafx.h
sebelum hal lain.
Alasan: Termasuk source1.h
sebelum file lain memastikan bahwa itu dapat berdiri sendiri tanpa ketergantungan itu. Jika source1.h
menggunakan dependensi di kemudian hari, kompiler akan segera memperingatkan Anda untuk menambahkan deklarasi penerusan yang diperlukan source1.h
. Ini pada gilirannya memastikan bahwa tajuk dapat dimasukkan dalam urutan apa pun oleh tanggungan mereka.
Contoh:
source1.h
class Class1 {
Class2 c2; // a dependency which has not been forward declared
};
source1.cpp
#include "source1.h" // now compiler will alert you saying that Class2 is undefined
// so you can forward declare Class2 within source1.h
...
Pengguna MSVC: Saya sangat merekomendasikan menggunakan header yang telah dikompilasi sebelumnya. Jadi, pindahkan semua #include
arahan untuk tajuk standar (dan tajuk lainnya yang tidak akan pernah berubah) ke stdafx.h
.
Sertakan dari yang paling spesifik ke yang paling spesifik, mulai dengan .hpp yang sesuai untuk .cpp, jika ada. Dengan begitu, setiap dependensi tersembunyi dalam file header yang tidak mencukupi akan terungkap.
Ini rumit dengan penggunaan header yang dikompilasi sebelumnya. Salah satu cara mengatasi hal ini adalah, tanpa membuat kompiler proyek Anda spesifik, adalah dengan menggunakan salah satu header proyek sebagai header termasuk file yang dikompilasi.
Ini adalah pertanyaan sulit di dunia C / C ++, dengan begitu banyak elemen di luar standar.
Saya pikir urutan file header bukan masalah serius selama dikompilasi, seperti kata squelart.
Gagasan saya adalah: Jika tidak ada konflik simbol di semua header itu, urutan apa pun OK, dan masalah ketergantungan header dapat diperbaiki nanti dengan menambahkan #include baris ke cacat .h.
Kerumitan sebenarnya muncul ketika beberapa tajuk mengubah aksinya (dengan memeriksa kondisi #jika) sesuai dengan tajuk di atas.
Misalnya, di stddef.h di VS2005, ada:
#ifdef _WIN64
#define offsetof(s,m) (size_t)( (ptrdiff_t)&(((s *)0)->m) )
#else
#define offsetof(s,m) (size_t)&(((s *)0)->m)
#endif
Sekarang masalahnya: Jika saya memiliki header khusus ("custom.h") yang perlu digunakan dengan banyak kompiler, termasuk beberapa yang lebih tua yang tidak menyediakan offsetof
header sistem mereka, saya harus menulis di header saya:
#ifndef offsetof
#define offsetof(s,m) (size_t)&(((s *)0)->m)
#endif
Dan pastikan untuk memberi tahu pengguna #include "custom.h"
setelah semua header sistem, jika tidak, baris offsetof
di stddef.h akan menyatakan kesalahan redefinisi makro.
Kami berdoa agar tidak bertemu lagi dengan kasus-kasus seperti itu dalam karier kami.