2009-03-05 18 views
31

शीर्षलेख/सीपीपी फ़ाइल में हेडर को किस क्रम में घोषित किया जाना चाहिए? जाहिर है, जो बाद के शीर्षकों द्वारा आवश्यक हैं, पहले होना चाहिए और कक्षा विशिष्ट शीर्षलेख सीपीपी दायरे में होना चाहिए, हेडर स्कोप नहीं, लेकिन क्या एक सेट ऑर्डर सम्मेलन/सर्वोत्तम अभ्यास है?सी ++ हैडर ऑर्डर

उत्तर

59

एक हेडर फ़ाइल में आपको सभी शीर्षलेखों को इसे संकलित करने के लिए शामिल करना होगा। और कुछ शीर्षकों की बजाय आगे की घोषणाओं का उपयोग करना न भूलें।

एक स्रोत फ़ाइल में:

  • corresponded हेडर फाइल
  • आवश्यक परियोजना हेडर
  • 3 पार्टी पुस्तकालयों
  • मानक पुस्तकालयों हेडर हेडर
  • प्रणाली हेडर

कि में आदेश आप किसी भी को याद नहीं करेंगे आर हेडर फाइलें जो पुस्तकालयों को स्वयं ही शामिल करना भूल गईं।

+2

मुझे लगता है कि "आवश्यक प्रोजेक्ट हेडर" दो आइटमों पर अलग होना चाहिए: - एक ही lib से प्रोजेक्ट हेडर; - अन्य प्रोजेक्ट libs के शीर्षलेख (क्रम में जहां सबसे आम प्रोजेक्ट libs शीर्षलेख कुछ विशेष प्रोजेक्ट libs शीर्षलेखों से नीचे का पालन करते हैं) – bayda

+2

मुझे वास्तव में आपका ऑर्डर पसंद है। इस तरह हेडर अपनी निर्भरताओं को शामिल करने के लिए अन्य शीर्षकों पर भरोसा नहीं करते हैं। शामिल हैं/हेडर गार्ड के लिए – fmuecke

3

मैं वर्णमाला के क्रम में उन्हें ऑर्डर करने के लिए (ढूंढना आसान)

+0

इस तरह एपिक अपने अवास्तविक इंजन 4 शैली दस्तावेज़ में भी ऐसा करता है। –

0

यह एक निर्भरता बात है और यह क्या आप हमारी हेडर में डाल पर काफी हद तक निर्भर करता है इस्तेमाल किया। एक तथ्य यह है कि आप इसके बारे में वास्तव में कुख्यात हो सकते हैं और अपने सख्त शामिल रखने के लिए कम कर सकते हैं लेकिन अंत में आप एक ऐसे परिदृश्य में भाग लेंगे जहां आप समावेशन गार्ड का उपयोग करना चाहते हैं।

#ifndef MY_HEADER_H 
#define MY_HEADER_H 
//... 
#endif 

समस्या शुरुआत में स्पष्ट नहीं है, लेकिन आपके सॉफ़्टवेयर की जटिलता बढ़ने पर आपकी निर्भरताएं बढ़ती हैं। आप अच्छी तरह से कर सकते हैं, और इसके बारे में स्मार्ट बन सकते हैं लेकिन बड़ी सी ++ परियोजनाओं को आमतौर पर शामिल किया जाता है। आप कोशिश कर सकते हैं, लेकिन आप केवल इतना ही कर सकते हैं। तो मेहनती रहें और अपने शामिल होने के बारे में सोचें, हां! लेकिन आप निश्चित रूप से कुछ बिंदु पर चक्रीय निर्भरता प्राप्त करेंगे और यही कारण है कि आपको शामिल करने वाले गार्ड की आवश्यकता है।

+1

क्या यह '#pragma एक बार' कॉल करने जैसा नहीं है? – Konrad

+1

हां यह (अधिक या कम) वही है, लेकिन #pragma एक बार मानक नहीं है। –

+0

रिकॉर्ड #pragma के लिए एक बार माइक्रोसॉफ्ट एक्सटेंशन है। यदि मैं एक बहु-मंच परियोजना पर काम कर रहा हूं, तो मैं इसका उपयोग करता हूं और साथ ही गार्ड भी शामिल करता हूं क्योंकि #pragma वास्तव में फ़ाइल की पार्सिंग को रोकता है। –

20

अच्छा अभ्यास: प्रत्येक .h फ़ाइल में एक .cpp होना चाहिए जिसमें वह शामिल है। पहले किसी और चीज़ से पहले। यह साबित करता है कि किसी भी .h फ़ाइल को पहले रखा जा सकता है।

भले ही हेडर को कोई कार्यान्वयन की आवश्यकता न हो, फिर भी आप एक .cpp बनाते हैं जिसमें केवल .h फ़ाइल शामिल है और कुछ भी नहीं।

इसका मतलब यह है कि आप किसी भी तरह से अपने प्रश्न का उत्तर दे सकते हैं। इससे कोई फर्क नहीं पड़ता कि आप उन्हें किस क्रम में शामिल करते हैं।

और अधिक अच्छी युक्तियों के लिए, इस पुस्तक को आजमाएं: Large-Scale C++ Software Design - यह शर्म की बात है कि यह महंगा है, लेकिन यह व्यावहारिक रूप से सी ++ स्रोत कोड लेआउट के लिए एक जीवित मार्गदर्शिका है।

+0

मैं इसके बजाय अपने यूनिट परीक्षण में ऐसा करता हूं। – Ferruccio

+4

परीक्षण स्वचालित करने के लिए एक आसान: बस प्रत्येक हेडर फ़ाइल (हाँ, g ++ -c blah.h) संकलित करें (और) संकलित करें और सुनिश्चित करें कि यह संकलित करता है। फिर आप ऑब्जेक्ट फ़ाइलों को दूर फेंक सकते हैं। –

+0

+1, उस उत्तर में बहुत कुछ छोड़ दिया गया है। महान टिप! –

1

.cpp फ़ाइलों के लिए, आपको कक्षा के शीर्षलेख या जो भी आप पहले कार्यान्वित कर रहे हैं, उसे शामिल करना चाहिए, ताकि आप उस मामले को पकड़ सकें जहां इस शीर्षलेख में कुछ शामिल है। इसके बाद, अधिकांश कोडिंग दिशानिर्देशों में पहले सिस्टम हेडर शामिल होते हैं, प्रोजेक्ट हेडर दूसरे, उदाहरण के लिए Google C++ Style Guide

0

यदि किसी शीर्षलेख को अन्य शीर्षकों की आवश्यकता होती है तो यह उन्हें उस शीर्षलेख में शामिल करता है।

अपने कोड को व्यवस्थित करने का प्रयास करें ताकि आप पॉइंटर्स या संदर्भ पास कर सकें और आगे बता सकें कि आप कहां कर सकते हैं।

कार्यान्वयन में तब हेडर जो इसे परिभाषित करता है उसे पहले सूचीबद्ध किया जाना चाहिए (यदि आप पीएच का उपयोग कर रहे हैं तो दृश्य स्टूडियो को छोड़कर stdafx पहले जाएगा)।

मैं आम तौर पर उन्हें सूचीबद्ध करता हूं जैसा कि मुझे चाहिए।

6

शीर्षलेख फ़ाइलों में, मैं मानक शीर्षलेख पहले रखना चाहता हूं, फिर मेरे अपने शीर्षलेख (दोनों सूचियों को वर्णानुक्रमित क्रमबद्ध किया जा रहा है)। कार्यान्वयन फाइलों में, मैंने पहले हेडर को संबंधित (यदि कोई हो), फिर मानकों के शीर्षलेख और अन्य निर्भरता शीर्षलेख डाले।

आदेश थोड़ा महत्व है, सिवाय इसके कि यदि आप मैक्रोज़ का एक अच्छा उपयोग करते हैं और #define; उस स्थिति में, आपको यह जांचना होगा कि आपके द्वारा परिभाषित एक मैक्रो पहले शामिल एक को प्रतिस्थापित नहीं करता है (सिवाय इसके कि यदि आप वही चाहते हैं, तो निश्चित रूप से)।

इस बयान

के संबंध में उन बाद हैडर के आधार पर है कि आवश्यक हैं पहले यह पहले

एक हैडर अन्य हेडर पर निर्भर नहीं होना चाहिए शामिल किया जा रहा होना चाहिए! अगर इसे हेडर की आवश्यकता है, तो इसमें बस शामिल है। हैडर गार्ड शामिल किए जाने के पाएगा: जब से मैं इस जवाब लिखा

#ifndef FOO_HEADER_H 
#define FOO_HEADER_H 
... 
#endif 

संपादित

, मैं अपने कोड में निर्देशों में शामिल हैं का आदेश देने का मेरा तरीका बदल दिया है। अब, मैं मानकों को मानकीकरण के क्रम में हमेशा रखने की कोशिश करता हूं, इसलिए मेरी परियोजना के शीर्षलेख पहले आते हैं, इसके बाद तीसरे पक्ष के पुस्तकालय शीर्षलेख होते हैं, इसके बाद मानक शीर्षलेख होते हैं।

उदाहरण के लिए

, अगर मेरी फाइल में से एक एक पुस्तकालय मैंने लिखा उपयोग करता है, क्यूटी, बूस्ट और मानक पुस्तकालय, मैं इस प्रकार भी शामिल है आदेश देगा:

//foo.cpp 
#include "foo.hpp" 

#include <my_library.hpp> 
// other headers related to my_library 

#include <QtCore/qalgorithms.h> 
// other Qt headers 

#include <boost/format.hpp> // Boost is arguably more standard than Qt 
// other boost headers 

#include <algorithms> 
// other standard algorithms 

कारण है कि मुझे लगता है कि पता लगाने के लिए है मेरे अपने शीर्षलेखों में निर्भरताएं गायब हैं: उदाहरण के लिए मान लें कि my_library.hppstd::copy का उपयोग करता है, लेकिन इसमें <algorithm> शामिल नहीं है। अगर मैं इसे foo.cpp में शामिल करता हूं, तो यह लापता निर्भरता अनजान हो जाएगी। इसके विपरीत, मैंने जो ऑर्डर प्रस्तुत किया है, उसके साथ संकलक शिकायत करेगा कि std::copy घोषित नहीं किया गया है, जिससे मुझे my_library.hpp सही करने की अनुमति मिलती है।

प्रत्येक "लाइब्रेरी" समूह में, मैं उन्हें आसानी से ढूंढने के लिए वर्णानुक्रमित क्रमबद्ध निर्देशों को शामिल रखने का प्रयास करता हूं।

एक साइडेनोट पर, एक अच्छा अभ्यास हेडर फ़ाइलों के बीच अधिकतम निर्भरता पर भी सीमित होना है। फ़ाइलों को जितना संभव हो सके छोटे हेडर के रूप में शामिल करना चाहिए, विशेष रूप से हेडर फ़ाइल। दरअसल, आपके द्वारा शामिल किए जाने वाले अधिक शीर्षलेख, कुछ परिवर्तन होने पर अधिक कोड को पुन: संकलित करने की आवश्यकता होती है। इन निर्भरताओं को सीमित करने का एक अच्छा तरीका आगे की घोषणा का उपयोग करना है, जो हेडर फ़ाइलों में अक्सर पर्याप्त होता है (When can I use a forward declaration? देखें)।

मॉड्यूल:

+0

+1। – polarise

-1

मैं इन नियमों का पालन सबसे अधिक उपयोगी पाया है।सीपीपी:

// this is the header used to trigger inclusion of precompiled headers 
#include <precompiled.h> 
// this ensures that anything that includes "module.h" works 
#include "module.h" 
// other headers, usually system headers, the project 

महत्वपूर्ण बात यह पहली गैर precompiled शीर्ष लेख के रूप में मॉड्यूल के हेडर डाल करने के लिए है। यह सुनिश्चित करता है कि "module.h" में कोई अप्रत्याशित निर्भरता नहीं है।

आप धीमी डिस्क का उपयोग समय के साथ एक बड़ी परियोजना पर काम कर रहे हैं, मैं इस शैली का निर्माण बार घटाने में इस्तेमाल किया देखा है:

module.cpp:

// this is the header used to trigger inclusion of precompiled headers 
#include <precompiled.h> 
// this ensures that anything that includes "module.h" works 
#include "module.h" 
// other headers, usually system headers, the project 
#if !defined _OTHER_MODULE_GUARD_ 
#include "other_module.h" 
#endif 

#if !defined _ANOTHER_MODULE_GUARD_ 
#include "another_module.h" 
#endif 

यह थोड़ा वर्बोज़ है लेकिन डिस्क पर सहेजने से बचाता है क्योंकि हेडर को पहले से ही शामिल नहीं किया गया है/खोला नहीं जाएगा। गार्ड चेक के बिना, कंपाइलर हेडर फ़ाइल की तलाश करेगा और खोल देगा, पूरी फाइल को #ifdef को पूरी फ़ाइल में समाप्त करने के लिए पार्स करेगा।

2

"कैसे" स्पष्ट नहीं है, लेकिन "क्या" है। आपका लक्ष्य यह सुनिश्चित करना है कि जिस क्रम में आप हेडर फाइलें शामिल करते हैं, वह कभी मायने रखता है (और मेरा मतलब है "कभी नहीं!")।

एक अच्छी मदद यह जांचने के लिए है कि हेडर फाइलें सीपीपी फाइलों (प्रत्येक हेडर फ़ाइल के लिए एक) बनाने के दौरान संकलित करती हैं या नहीं, जिनमें से केवल उनमें से एक शामिल है।

5

Google C++ Style Guide, Names and Order of Includes:

dir/foo.cc, जिसका मुख्य उद्देश्य लागू करने या परीक्षण dir2/foo2.h में सामान, आदेश इस प्रकार अपने में शामिल करने के लिए है में:

  • dir2/foo2.h (पसंदीदा स्थान - नीचे विवरण देखें)।
  • सी सिस्टम फाइलें।
  • सी ++ सिस्टम फाइलें।
  • अन्य पुस्तकालयों '.एच फाइलें।
  • आपकी प्रोजेक्ट की .h फ़ाइलें।
+5

हाँ लेकिन जीजीएल शैली गाइड में कुछ गंदा चीजें हैं :) –

संबंधित मुद्दे