2014-07-24 6 views
8

मैं एक फ़ाइल में एक ही हेडर के कई समावेशन के बारे में पढ़ रहा था, और एक दिलचस्प बयान (link) में पाया गया:एक ही हेडर को एक फ़ाइल में कई बार शामिल करना उपयोगी होता है?

हेडर फाइल के साथ चाल के एक जोड़े थे रहे हैं आप जानबूझकर इसे कई बार शामिल हैं (इस वास्तव में एक उपयोगी सुविधा प्रदान करता है)।

मैं समझता हूँ कि उन चाल शायद अवांछित और वास्तविक दुनिया परियोजनाओं में भ्रमित कर रहे हैं (विशेष रूप से लोगों को, कई समावेशन के खिलाफ सावधानी बरतने include guards और #pragma once की तरह)। लेकिन फिर भी, ये चाल क्या हैं? मैं कुछ विचारों के साथ आया, लेकिन कुछ वास्तविक उदाहरण देखना चाहते हैं (आदर्श, सुरक्षित और कोशिश की)।

मेरे विचार: सी, जहां टेम्प्लेट पैरामीटर पूर्वप्रक्रमक परिभाषा के साथ प्रतिस्थापित कर रहे हैं में

  • छद्म टेम्पलेट्स। इसे बिना किसी समावेशन के किया जा सकता है, लेकिन फ़ंक्शंस बहुत बड़े या बहुत अधिक हो सकते हैं, इसलिए एक अलग फ़ाइल बनाना समझ में आता है।
  • ब्लॉक-दर-ब्लॉक संरचना/वर्ग निर्माण (टुकड़ों का संयोजन)। यह सी में विरासत को अनुकरण करने में मदद कर सकता है और सामान्य सदस्यों के साथ structs परिभाषित करते समय कोड डुप्लिकेशन को रोक सकता है।
  • लुक-अप टेबल और अन्य संकलन-समय डेटा संरचनाएं (फिर से, प्रीप्रोसेसर परिभाषाओं की सहायता से)।
+3

एक्स मैक्रोज़ –

+0

हो सकता है कि आप एक स्रोत फ़ाइल में छिड़काव '# परिभाषित' और '# undef' का उपयोग कर रहे हों ... –

+0

आप उस व्यक्ति से क्यों नहीं पूछते हैं? – juanchopanza

उत्तर

7

#include "file" का अर्थ हेडर फ़ाइल लेना और #include लाइन की बजाय इसकी सभी सामग्री डालना है।

हम आमतौर पर टाइप परिभाषाओं के लिए हेडर का उपयोग करते हैं और स्रोत फ़ाइलों को अग्रेषित घोषणाओं के लिए उपयोग करते हैं। फ़ाइल में दो बार एक ही प्रकार को परिभाषित करना (एक परिपत्र शामिल करना हमेशा इसका कारण बनता है) संकलन त्रुटि देता है, इसलिए हम #ifndef या #pragma once का उपयोग करते हैं। (या दोनों)

लेकिन हम एक दोहराव कोड और मैक्रोज़ भी डाल सकते हैं और इसे एक ही फ़ाइल में भी कई बार शामिल कर सकते हैं। इस तरह के मामले में, हम #ifndef और न ही #pragma once का उपयोग नहीं करेंगे। यदि आप ऐसा करते हैं तो आपको अतिरिक्त सावधान रहना चाहिए, और केवल तभी करें जब आप जानते हों कि आप क्या कर रहे हैं।

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

//suppress the warnings: 
#if defined(__GNUC__) 
    #if __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6) 
    #pragma GCC diagnostic push 
    #pragma GCC diagnostic ignored "-Wreorder" 
    #pragma GCC diagnostic ignored "-Wunused-function" 
    #pragma GCC diagnostic ignored "-Wunused-variable" 
    #pragma GCC diagnostic ignored "-Wsign-compare" 
    #pragma GCC diagnostic ignored "-Wmaybe-uninitialized" 
    #pragma GCC diagnostic ignored "-Wsequence-point" 
    #endif 
#endif // __GNUC__ 

//here you call the function... 
func(x,y,z); 

//unsupress: bring back the warnings to normal state 
#if defined(__GNUC__) 
    #if __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6) 
    #pragma GCC diagnostic pop 
    #endif 
#endif // __GNUC__ 

यह आपके कोड को बहुत गंदा दिखने देगा, खासकर यदि आप कई बार फ़ंक्शन को कॉल करते हैं।

एक संभावित समाधान, (मैं सुझाव नहीं दे रहा हूं कि यह सबसे अच्छा है ...) चेतावनी को दबाने के लिए और दूसरे में दमन को रद्द करने के लिए 2 शीर्षलेख बनाना है।

उस मामले अपने कोड कुछ ऐसा दिखाई देगा में:

#include "suppress.h" 
func(x,y,z); 
#include "unsuppress.h" 

//.... more code come here 
//now when call it again: 
#include "suppress.h" 
func(x,y,z); 
#include "unsuppress.h" 
1

'मानक' उदाहरण <assert.h> हैडर है। यह भी शामिल है के प्रभाव NDEBUG के मूल्य पर निर्भर करता है:

#include <assert.h> 

void func1(void) 
{ 
    assert(...); 
} 

#undef NDEBUG 
#include <assert.h> 

void func2(void) 
{ 
    assert(...); 
} 

#define NDEBUG 
#include <assert.h> 

void func3(void) 
{ 
    assert(...); 
} 

अभिकथन func1() में सक्रिय है, जब तक कि संकलन के माहौल में कुछ समय में NDEBUG की स्थापना की है जब <assert.h> शामिल किया गया था। func2() में दावा सक्रिय है क्योंकि को अपरिभाषित किया गया था जब <assert.h> शामिल था। func3() में दावा निष्क्रिय है क्योंकि NDEBUG को परिभाषित किया गया था जब <assert.h> शामिल था।

ऐसा कहकर, मैंने वास्तविक जीवन में इस सुविधा का कभी भी उपयोग नहीं किया है, लेकिन सी मानक दिखाए गए व्यवहार को आशीर्वाद देता है (जनादेश)।

ध्यान दें कि यह दुर्घटना से नहीं होता है; ऐसा इसलिए होता है क्योंकि शीर्षलेख को जानबूझकर इंजीनियर किया जाता है (पुनः) एक ही टीयू में कई बार उपयोग किया जाता है।

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