स्टेटमेंट, हेडर या सोर्स को कहां शामिल करें?


106

क्या मुझे हेडर फ़ाइल या स्रोत फ़ाइल में शामिल करना चाहिए? यदि हेडर फ़ाइल में शामिल कथनों को शामिल किया जाता है, तो यदि मैं उस हेडर फ़ाइल को अपने स्रोत में शामिल करता हूँ, तो क्या मेरे स्रोत फ़ाइल में वे सभी सम्मिलित फ़ाइलें होंगी जो मेरे हेडर में थीं? या क्या मुझे उन्हें केवल अपने स्रोत फ़ाइल में शामिल करना चाहिए?


2
एसओ पर कई पिछले डुप्लिकेट, उदाहरण के लिए, जहां "शामिल होना चाहिए" को C ++ में डाल दिया जाना चाहिए
पॉल आर

1
डुप्लिकेट का संभावित डुप्लिकेट क्या मुझे हेडर में # उपयोग करना चाहिए?
schot

जवाबों:


141

यदि हेडर को उनकी आवश्यकता होती है तो केवल एक हेडर में शामिल होता है।

उदाहरण:

  • आपका फंक्शन रिटर्न टाइप करता है size_t। तब #include <stddef.h>में हैडर फ़ाइल।
  • आपका फ़ंक्शन उपयोग करता है strlen। तब #include <string.h>में स्रोत फ़ाइल।

2
यदि मेरा कार्य प्रकार का तर्क लेता है तो क्या होगा size_t?
और्रीबक

C ++ तक विस्तृत प्रश्न: क्या होगा यदि मेरी संरचना / वर्ग में फ़ील्ड / प्रकार का सदस्य size_tया है std::string?
और्रीबक

10
औचित्य क्या है?
पैट्रीज़ियो बर्तोनी

मेरे पास एक तार वाली स्थिति है, C ++ वर्ग A में एक अन्य वर्ग B की एक वस्तु है, और मैं A शीर्ष लेख को A शीर्ष लेख के अंदर B हेडर सहित B और एंड-अप का उपयोग नहीं कर सकता। (पॉइंटर का उपयोग करने से यह समस्या नहीं होती है)
शुवा

@andrybak आपकी स्रोत फ़ाइलों में आपकी हेडर फ़ाइल शामिल होनी चाहिए ताकि कोई भी आपके हेडर को आपके स्रोत के रूप में अच्छी तरह से मिल जाए।
जेरेमी ट्राइफिलो

27

वर्षों से इस बारे में काफी असहमति है। एक समय में, यह पारंपरिक था कि एक हेडर केवल यह घोषित करता है कि वह किस मॉड्यूल से संबंधित था, इसलिए कई हेडर की विशिष्ट आवश्यकताएं थीं जो आप #includeहेडर का एक निश्चित सेट (एक विशिष्ट क्रम में) करते हैं। कुछ अत्यंत पारंपरिक सी प्रोग्रामर अभी भी इस मॉडल का पालन करते हैं (धार्मिक रूप से, कम से कम कुछ मामलों में)।

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

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


2
यदि सभी हेडर दूसरी शैली में लिखे गए हैं, तो कोई क्रमबद्ध मुद्दे नहीं होने चाहिए। हेडर में समस्याओं का आदेश देने का मतलब आमतौर पर यह होता है कि आपने हेडर में अपनी जरूरत की सभी चीजों को शामिल नहीं किया है।
अलविदा एसई

12

आपकी #includes हेडर फ़ाइलों की होनी चाहिए, और प्रत्येक फ़ाइल (स्रोत या हेडर) को #includeहेडर फ़ाइलों की आवश्यकता होनी चाहिए । हेडर फाइलें #includeन्यूनतम हेडर फाइलें आवश्यक होनी चाहिए, और स्रोत फाइलें भी होनी चाहिए, हालांकि यह स्रोत फ़ाइलों के लिए महत्वपूर्ण नहीं है।

स्रोत फ़ाइल में हेडर होगा जो इसे है #include, और हेडर वे #include, और इसी तरह अधिकतम नेस्टिंग गहराई तक। यही कारण है कि आप #includeशीर्ष लेख फ़ाइलों में शानदार एस नहीं चाहते हैं : वे एक स्रोत फ़ाइल को कई हेडर फ़ाइलों को शामिल करने का कारण बन सकते हैं जिनकी आवश्यकता नहीं हो सकती है, संकलन धीमा करना।

इसका मतलब है कि यह पूरी तरह से संभव है कि हेडर फाइलें दो बार शामिल हो सकती हैं, और यह एक समस्या हो सकती है। पारंपरिक पद्धति हेडर फ़ाइलों में "गार्ड्स शामिल करें", जैसे फ़ाइल foo.h के लिए है:

#ifndef INCLUDE_FOO_H
#define INCLUDE_FOO_H
/* everything in header goes here */
#endif

मुझे पता है कि यह उत्तर सुपर पुराना है, लेकिन तब से उन्होंने #pragma को एक बार जोड़ दिया, यदि आप #ifndef को शामिल नहीं करना चाहते हैं तो #includes घोषित करते समय मैंने इस cuz को पोस्ट किया है, लेकिन अधिक लोकप्रिय / उत्क्रमित थ्रेड्स Google खोजों में सबसे ऊपर हैं
डोगुनबाउंड

6

बीस वर्षों में मैंने जो दृष्टिकोण विकसित किया है वह यह है;

एक पुस्तकालय पर विचार करें।

कई सी फाइलें हैं, एक आंतरिक एच फाइल और एक बाहरी एच फाइल। C फ़ाइलों में आंतरिक H फ़ाइल शामिल है। आंतरिक H फ़ाइल में बाहरी H फ़ाइल शामिल है।

आप देखते हैं कि संकलक POV से, जैसा कि यह C फ़ाइल संकलित करता है, एक पदानुक्रम है;

बाहरी -> आंतरिक -> सी कोड

यह सही क्रम है, क्योंकि जो बाहरी है वह सब कुछ है जिसे तीसरे पक्ष को पुस्तकालय का उपयोग करने की आवश्यकता है। जो आंतरिक है उसे C कोड संकलित करना आवश्यक है।


4

अगर हेडर ए #includesहेडर फाइल बी और सी फाइल करता है, तो प्रत्येक स्रोत फाइल जो #includesए को बी और सी भी मिलेगा #included। प्री-प्रोसेसर का शाब्दिक अर्थ केवल पाठ प्रतिस्थापन होता है: कहीं भी यह पाठ पाता है जो कहता है कि #include <foo.h>यह इसे foo.hफ़ाइल के पाठ के साथ बदल देता है ।

इस पर अलग-अलग राय है कि आपको #includesहेडर या स्रोत फ़ाइलों में रखना चाहिए या नहीं। व्यक्तिगत रूप से, मैं #includesडिफ़ॉल्ट रूप से सभी स्रोत फ़ाइल में रखना पसंद करता हूं , लेकिन कोई भी हेडर फाइलें जो अन्य पूर्व-अपेक्षित हेडर के बिना संकलित नहीं कर सकती हैं, #includeउन्हें स्वयं हेडर चाहिए ।

और हर हेडर फ़ाइल में कई बार शामिल होने से रोकने के लिए एक शामिल गार्ड होना चाहिए।


4

कुछ वातावरणों में, संकलन सबसे तेज़ होगा यदि किसी में केवल हेडर फ़ाइलों की आवश्यकता हो। अन्य वातावरणों में, संकलन को अनुकूलित किया जाएगा यदि सभी स्रोत फ़ाइलें हेडर के समान प्राथमिक संग्रह का उपयोग कर सकती हैं (कुछ फ़ाइलों में सामान्य उपसमुच्चय से परे अतिरिक्त हेडर हो सकते हैं)। आदर्श रूप से, हेडर का निर्माण किया जाना चाहिए ताकि एकाधिक #include संचालन पर कोई प्रभाव न पड़े। फ़ाइल-से-शामिल-शामिल-गार्ड के लिए चेक के साथ #include स्टेटमेंट को घेरना अच्छा हो सकता है, हालांकि यह उस गार्ड के प्रारूप पर निर्भरता बनाता है। इसके अलावा, सिस्टम के फ़ाइल कैशिंग व्यवहार के आधार पर, एक अनावश्यक #include जिसका लक्ष्य पूरी तरह से समाप्त होने पर # ifdef'ed दूर होने में अधिक समय नहीं लग सकता है।

विचार करने के लिए एक और बात यह है कि यदि कोई फ़ंक्शन एक पॉइंटर को एक संरचना में ले जाता है, तो कोई प्रोटोटाइप को लिख सकता है

शून्य फू (संरचना BAR_s * बार);

बिना BAR_s की परिभाषा के दायरे में होना। अनावश्यक से बचने के लिए एक बहुत ही आसान तरीका शामिल है।

PS - मेरी कई परियोजनाओं में, एक फाइल होगी, जिसमें यह उम्मीद की जाती है कि हर मॉड्यूल #include होगा, जिसमें पूर्णांक आकार और कुछ सामान्य संरचनाओं और यूनियनों के लिए टाइप-सीफ़ जैसी चीज़ें शामिल होंगी [जैसे

टंकण संघ
  अहस्ताक्षरित लंबे एल;
  अहस्ताक्षरित लघु lw [2];
  अहस्ताक्षरित चार lb [4];
} U_QUAD;

(हां, मुझे पता है कि अगर मैं एक बड़े-एंडियन आर्किटेक्चर में चला गया, तो मैं परेशानी में पड़ जाऊंगा, लेकिन चूंकि मेरे कंपाइलर यूनियनों में अनाम संरचना की अनुमति नहीं देते हैं, इसलिए यूनियन के भीतर बाइट्स के लिए नामांकित पहचानकर्ताओं का उपयोग करने की आवश्यकता होगी क्योंकि उन्हें एक्सेस किया जाना चाहिए। TheUnion.b.b1 आदि जो बल्कि कष्टप्रद लगता है।


3

अपनी सभी फाइलें बना लें ताकि वे केवल उसी का उपयोग करके बनाई जा सकें जिसमें वे शामिल हैं। यदि आपको अपने हेडर में शामिल करने की आवश्यकता नहीं है, तो उसे हटा दें। एक बड़ी परियोजना में यदि आप इस अनुशासन को बनाए नहीं रखते हैं, तो आप अपने आप को एक संपूर्ण बिल्ड को तोड़ने के लिए खुला छोड़ देते हैं जब कोई हेडर फ़ाइल से एक सम्मिलित करता है जिसे उस फ़ाइल के उपभोक्ता द्वारा उपयोग किया जा रहा है और हेडर द्वारा भी नहीं।


1

यदि आप इसे हेडर में रखते हैं तो आपकी सोर्स फाइल में स्टेटमेंट शामिल होंगे। हालांकि, कुछ मामलों में उन्हें स्रोत फ़ाइल में रखना बेहतर होगा।

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


1

आपको केवल अपने हेडर में फ़ाइलें शामिल करनी चाहिए जिन्हें आपको स्थिरांक और फ़ंक्शन घोषणाओं की घोषणा करने की आवश्यकता है। तकनीकी रूप से, ये आपके स्रोत फ़ाइल में भी शामिल किए जाएंगे, लेकिन स्पष्टता के लिए, आपको केवल प्रत्येक फ़ाइल में उन फ़ाइलों को शामिल करना चाहिए जिन्हें आपको वास्तव में उपयोग करने की आवश्यकता है। आपको उन्हें अपने हेडर में कई समावेश से भी सुरक्षित रखना चाहिए:

#ifndef NAME_OF_HEADER_H
#define NAME_OF_HEADER_H

...definition of header file...

#endif

यह हेडर को कई बार शामिल करने से रोकता है, जिसके परिणामस्वरूप कंपाइलर त्रुटि होती है।

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.