Hangi sipariş dosyaları belirtilmelidir, yani bir üstbilgiyi diğerine eklemenin nedenleri nelerdir?
Örneğin, sistem dosyaları, STL ve Boost yerel içerme dosyalarından önce mi sonra mı gidiyor?
Hangi sipariş dosyaları belirtilmelidir, yani bir üstbilgiyi diğerine eklemenin nedenleri nelerdir?
Örneğin, sistem dosyaları, STL ve Boost yerel içerme dosyalarından önce mi sonra mı gidiyor?
Yanıtlar:
Derlediği sürece önerilen bir sipariş olduğunu sanmıyorum! Can sıkıcı olan, bazı başlıkların önce diğer başlıkların dahil edilmesini gerektirmesidir ... Bu, başlıkların sırası ile değil başlıkların kendileriyle ilgili bir sorundur.
Kişisel tercihim yerelden küresel olana, her alt bölümü alfabetik sırayla, yani:
Benim için #include
gerekçem , her başlığın (bir cpp olduğu) önkoşullar olmadan (terminus technicus: header "müstakil" olduğunu) kanıtlaması gerektiğidir . Ve geri kalanlar mantıklı bir şekilde oradan akıyor gibi görünüyor.
Akılda tutulması gereken en önemli şey, başlıklarınızın önce dahil edilen diğer başlıklara bağlı olmaması gerektiğidir. Bunu sağlamanın bir yolu da başlıklarınızı diğer başlıklardan önce eklemektir.
"C ++ 'da Düşünmek" özellikle bundan bahsediyor ve Lakos'un "Büyük Ölçekli C ++ Yazılım Tasarımına" atıfta bulunuyor:
Bir bileşenin .h dosyasının harici olarak sağlanan bildirimler veya tanımlar olmadan kendi kendine ayrıştırılmasını sağlayarak gizli kullanım hataları önlenebilir. .H dosyasını .c dosyasının ilk satırı olarak dahil etmek, kritik bir parçanın bileşeninin fiziksel arabirimine özgü bilgiler .h dosyasında eksiktir (veya varsa, .c dosyasını derlemeye çalıştığınızda bunu öğreneceksiniz).
Yani, aşağıdaki sırayla ekleyin:
Başlıklardan herhangi birinin bu siparişe dahil edilmeyle ilgili bir sorunu varsa, bunları düzeltin (sizinkini) veya kullanmayın. Temiz başlık yazmayan kütüphaneleri boykot edin.
Google'ın C ++ stil kılavuzu savunuyor neredeyse hiç gerçekten hiçbir gerekçe ile, ters; Şahsen Lakos yaklaşımını destekleme eğilimindeyim.
Sorunların büyük çoğunluğunu önleyen iki basit kurala uyuyorum:
Ayrıca aşağıdaki yönergeleri de takip ediyorum:
Diğer bir deyişle:
#include <stdio.h>
#include <string.h>
#include "btree.h"
#include "collect_hash.h"
#include "collect_arraylist.h"
#include "globals.h"
Her ne kadar, rehber olmak, bu öznel bir şeydir. Diğer yandan, kurallar, sıkıca, hatta 'sarıcı' başlık dosyaları korumaları ve gruplandırılmış bazı iğrenç üçüncü taraf geliştirici vizyonum abone olmazsa içerir sağlamak için bile zorlamak :-)
Duvara kendi tuğlamı eklemek için.
Bu yüzden genellikle şöyle giderim:
// 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"
Her grup bir sonrakinden boş bir satırla ayrılır:
Ayrıca, sistem başlıklarının yanı sıra, her dosyanın ad alanının adıyla bir klasörde olduğunu unutmayın, çünkü bunları bu şekilde izlemek daha kolaydır.
#define
diğer kodları bozan şeyler hakkında kötüdür ) ve örtük bağımlılıkları önlemek için. Örneğin, kod tabanı başlık dosyamız foo.h
gerçekten bağlıysa <map>
ancak .cc
dosyalarda kullanıldığı her yerde , <map>
zaten dahil edilmişse , muhtemelen fark etmeyeceğiz. Birisi foo.h
ilk dahil olmadan dahil etmeye çalışana kadar <map>
. Ve sonra sinirlenirlerdi.
.h
birinin .cpp
önce onu içeren en az bir tane var (gerçekten, kişisel ilişkili Birim testi önce içeriyor ve kaynak kodu bunu doğru grubuna dahil ediyor ). Etkilenmemekle ilgili olarak, başlıklardan herhangi birini içeriyorsa, <map>
daha sonra dahil edilen tüm başlıklar yine de etkilenir, bu yüzden bana kaybedilen bir savaş gibi görünüyor.
Header corresponding to this cpp file first (sanity check)
. #include "myproject/example.h"
Tüm içeriklerin sonuna taşınırsa özel bir şey var mı ?
Ben tavsiye ediyorum:
Ve elbette, mümkün olan her bölümdeki alfabetik sıra.
#include
Başlık dosyalarınızda gereksiz durumlardan kaçınmak için her zaman ileri bildirimler kullanın .
Bunun aklı başında dünyanın herhangi bir yerinde tavsiye edilen bir uygulama olmadığından eminim, ancak sisteme aynı uzunluktaki sözcük olarak sıralanan dosya adı uzunluğuna kadar sıralamayı seviyorum. Şöyle ki:
#include <set>
#include <vector>
#include <algorithm>
#include <functional>
Sanırım içerme düzenine bağımlılıktan utanmaktan kaçınmak için diğer kişilerin önüne kendi başlıklarınızı eklemek iyi bir fikirdir.
windows.h
.
Bu öznel değil. Başlıklarınızın #include
belirli bir sırada d olmasına bağlı olmadığından emin olun . STL veya Boost başlıklarını hangi sırayla eklediğinizin önemli olmadığından emin olabilirsiniz.
Öncelikle .cpp ... 'e karşılık gelen üstbilgiyi, başka bir şey eklemeden önce source1.cpp
içermelidir source1.h
. Aklıma gelen tek istisna, MSVC'yi önceden derlenmiş başlıklarla kullanırken, bu durumda stdafx.h
başka bir şeyden önce dahil etmek zorunda kalırsınız .
Muhakeme: dahil source1.h
o 's bağımlılıkları olmadan tek başına var olamayacağını başka dosyalardan önce garantiler. Daha source1.h
sonraki bir tarihte bir bağımlılık alırsanız , derleyici derhal gerekli ileri bildirimleri eklemeniz için sizi uyaracaktır source1.h
. Bu da başlıkların bağımlıları tarafından herhangi bir sıraya dahil edilmesini sağlar.
Misal:
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
...
MSVC kullanıcıları: Önceden derlenmiş başlıklar kullanmanızı önemle tavsiye ederim. Bu nedenle, #include
standart başlıklar (ve asla değişmeyecek diğer başlıklar) için tüm yönergeleri taşıyın stdafx.h
.
Varsa, .cpp için karşılık gelen .hpp ile başlayarak en spesifik olandan en az spesifik olana kadar ekleyin. Bu şekilde, başlık dosyalarındaki kendi kendine yeterli olmayan gizli bağımlılıklar ortaya çıkar.
Bu, önceden derlenmiş başlıkların kullanımı ile karmaşıktır. Bunun bir yolu, projenizi derleyiciye özgü yapmadan, proje başlıklarından birini önceden derlenmiş başlık içerme dosyası olarak kullanmaktır.
C / C ++ dünyasında zor bir sorudur ve standardın ötesinde pek çok unsuru vardır.
Bence başlık dosya sırası derliyordu gibi derliyorum ciddi bir sorun değildir, dedi.
Benim düşüncelerim: Tüm bu başlıklarda sembol çakışması yoksa, herhangi bir sipariş tamamdır ve başlık bağımlılığı sorunu daha sonra kusurlu .h'ye #include satırları eklenerek düzeltilebilir.
Gerçek zorluk, bazı üstbilgiler yukarıdaki başlıklara göre (#if koşullarını kontrol ederek) eylemini değiştirdiğinde ortaya çıkar.
Örneğin, VS2005'teki stddef.h dosyasında:
#ifdef _WIN64
#define offsetof(s,m) (size_t)( (ptrdiff_t)&(((s *)0)->m) )
#else
#define offsetof(s,m) (size_t)&(((s *)0)->m)
#endif
Şimdi sorun: offsetof
Kendi sistem başlıklarında sağlamayan bazı eski derleyiciler de dahil olmak üzere birçok derleyici ile kullanılması gereken özel bir üstbilgi ("custom.h") varsa, üstbilgime yazmalıyım:
#ifndef offsetof
#define offsetof(s,m) (size_t)&(((s *)0)->m)
#endif
Ve kullanıcıya tüm sistem başlıklarından #include "custom.h"
sonraoffsetof
bahsettiğinizden emin olun , aksi takdirde stddef.h satırı bir makro yeniden tanımlama hatası verir.
Kariyerimizde bu tür olaylarla daha fazla karşılaşmamak için dua ediyoruz.