2010-08-21 12 views
5
#include "DLLDefines.h" 
#include "DLLDefines.h" 

उपरोक्त वास्तव में पारित संकलन, लेकिन क्यों?सी ++ में दो बार हेडर फ़ाइल को शामिल करने के लिए मान्य क्यों है?

+7

यह अमान्य क्यों होगा? (गंभीर सवाल; यह देखने का प्रयास कर रहा है कि आप '# शामिल' कैसे समझते हैं।) – strager

+0

स्ट्रैगर के बिंदु पर अनुवर्ती करने के लिए: '# शामिल' शामिल फ़ाइल की सामग्री को वर्तमान फ़ाइल में चिपकाता है। कुछ और नहीं (शायद कुछ कार्यान्वयन-विशिष्ट एनोटेशन के अलावा संकलक को त्रुटियों के लिए लाइन नंबरों की रिपोर्ट करने में मदद करने के लिए, और डीबग जानकारी उत्सर्जित करने के लिए)। आपको दो बार ऐसा करने से मना करने का कोई विशेष कारण नहीं है, और अच्छी तरह से व्यवहार की गई '.h' फ़ाइलें गार्ड का उपयोग करके इसका समर्थन करती हैं। –

उत्तर

4

शायद आपके पास अपने कोड के आसपास DLLDefines.h में कुछ # परिभाषित है जो इसे दो बार शामिल करने से रोकता है।

#ifndef DLLDEFINES_H 
#define DLLDEFINES_H 
// your code 
#endif 
+7

नाइटपिक: यह तकनीक इसे दो बार शामिल करने से नहीं रोकती है; यह इसे कई बार शामिल करना सुरक्षित बनाता है। –

+1

@ चार्ल्स: यह हेडर में कोड को दो बार पढ़ने से रोकता है, जो आम तौर पर फ़ाइल को शामिल करने के साथ होता है। – rubenvb

+0

दरअसल, मुझे यकीन नहीं था कि स्पष्टीकरण को कम किए बिना इसे कैसे कहना है। दूसरी बार फ़ाइल शामिल होने पर प्रीप्रोसेसर #ifndef के अंदर सामग्री को अनदेखा कर देगा। – Zaki

8

यह हेडर फ़ाइल पर निर्भर करता है; एक ही फ़ाइल के एकाधिक शामिल पर कोई भाषा प्रतिबंध नहीं है।

कुछ फ़ाइलों को कई बार शामिल करने के लिए डिज़ाइन किया गया है (उदा। <assert.h> को 'चालू' और 'बंद' assert चालू करने के लिए कई बार शामिल किया जा सकता है)।

कई फाइलें कई बार शामिल होने के लिए सुरक्षित हैं क्योंकि उनके पास में गार्ड शामिल हैं, अन्य को केवल अनुवाद इकाई या यहां तक ​​कि एक प्रोग्राम में शामिल नहीं किया जाना चाहिए।

6

में सी या सी ++ भाषा के साथ कुछ भी नहीं है। यह एक फाइल लाने के लिए preprocessor के लिए एक निर्देश है। प्रीप्रोसेसर परवाह नहीं है कि कौन सी फाइल लाई गई है और इसे नहीं करना चाहिए। यह पूरी तरह से यह करने के लिए स्वीकार्य हो सकता है:

void Foo::SomeFunc(int cond) 
{ 
    switch (cond) { 
    case kThisCase: 
#include "longFirstCase.h" 
     break; 
    case kSecondCase: 
#include "longSecondCase.h" 
     break; 
    case kThirdCase: 
#include "longFirstCase.h" 
#include "longSecondCase.h" 
     break; 
    } 
} 

मैंने देखा है एक ही फाइल के साथ-साथ एक विन्यास तंत्र के रूप में कई बार शामिल थे।

माना जाता है कि उस उदाहरण को बेहतर बनाने के कई तरीके हैं जो बेहतर हैं, लेकिन मुद्दा यह है कि आप पूरी तरह से अच्छे कारण हो सकते हैं और इसलिए उपयोग पर कोई प्रतिबंध नहीं है।

+1

आप इसे कैसे काम करने की उम्मीद करते हैं? # रनटाइम जानकारी के आधार पर चीजों को शामिल करना? – Shautieh

+1

@Shautieh, '# शामिल 'स्रोत फ़ाइल verbatim सम्मिलित करता है। संभवतः फाइलें 'longFirstCase.h' और' longSecondCase.h' में 'स्विच' कथन के अंदर होने वाले सी कोड शामिल हैं। – strager

+0

@ शॉटिह ने स्ट्रैजर की तरह कहा, यह उस फ़ाइल में कोड चिपकाता है जहां # शामिल है। एक उदाहरण के रूप में इस तकनीक का अक्सर उपयोग किया जाता है ताकि स्वत: उत्पन्न कोड के हिस्सों को शामिल किया जा सके। –

1

इसे include guard कहा जाता है। विकिपीडिया से

#ifndef GRANDFATHER_H 
#define GRANDFATHER_H 

struct foo { 
    int member; 
}; 

#endif 

उद्धरण: अधिक जानकारी के लिए ऊपर

In the C and C++ programming languages, an #include guard, sometimes called a macro guard, is a particular construct used to avoid the problem of double inclusion when dealing with the #include directive. The addition of #include guards to a header file is one way to make that file idempotent.

लिंक देखें।

2

जब तक हेडर फाइलों के एकाधिक समावेशन ओडीआर (एक परिभाषा नियम) $ 3.2 का उल्लंघन नहीं करते हैं, तो कोड अच्छी तरह से गठित होता है।

0

DLLDefines.h में शीर्ष पर #pragma भी हो सकता है, #pragma एक बार यह सुनिश्चित करता है कि फ़ाइल केवल एक बार शामिल हो।

+0

यह माइक्रोसॉफ्ट केवल विस्तार है, आईआईआरसी। – JustBoo

+0

@ जस्टबू [विकिपीडिया] के अनुसार (http://en.wikipedia.org/wiki/Pragma_once#Portability), अधिकांश कंपाइलर '#pragma एक बार' का समर्थन करते हैं – Angew

12

अच्छा, यह कानूनी है क्योंकि में कानूनी होने के लिए है। क्योंकि आप अक्सर इसे एक ही शीर्षलेख को बिना महसूस किए कई बार शामिल करते हैं।

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

उदाहरण के लिए, सभी मानक लाइब्रेरी शीर्षलेख (कहें, string या vector उदाहरण के लिए) शायद आपके अधिकांश शीर्षकों में शामिल हैं। तो आप उसी ही शीर्षलेख के साथ जल्दी ही समाप्त हो जाते हैं, अप्रत्यक्ष रूप से उसी .cpp फ़ाइल में कई बार शामिल किया जाता है।

तो संक्षेप में, में काम करने के लिए है, या सभी सी ++ कोड अलग हो जाएंगे।

के लिए यह आमतौर पर गार्ड शामिल करने के माध्यम से काम करता है। याद रखें कि #include बस एक साधारण प्रतिलिपि/पेस्ट करता है: यह #include साइट पर हेडर फ़ाइल की सामग्री को सम्मिलित करता है।

class MyClass {}; 

अब चलो एक cpp फ़ाइल जो इसे दो बार शामिल बना सकते हैं:

#include "header.h" 
#include "header.h" 

पूर्वप्रक्रमक को यह फैलता है:

तो मान लीजिए कि आप निम्नलिखित सामग्री के साथ एक हेडर फाइल header.h डालते हैं

class MyClass {}; 
class MyClass {}; 

जो स्पष्ट रूप से एक त्रुटि का कारण बनता है: एक ही कक्षा परिभाषित है दो बार तो यह काम नहीं करता है। ,

#ifndef HEADER_H 
#define HEADER_H 

class MyClass {}; 

#endif 

अब अगर हम इसे दो बार में शामिल हैं, हम इस मिल:

#ifndef HEADER_H 
#define HEADER_H 

class MyClass {}; 

#endif 

#ifndef HEADER_H 
#define HEADER_H 

class MyClass {}; 

#endif 

और यह क्या होता है जब पूर्वप्रक्रमक यह संसाधित करता है इसके बजाय, के हेडर को रोकने के लिए गार्ड शामिल संशोधित:

#ifndef HEADER_H // HEADER_H is not defined, so we enter the "if" block 
#define HEADER_H // HEADER_H is now defined 

class MyClass {};// MyClass is now defined 

#endif   // leaving the "if" block 

#ifndef HEADER_H // HEADER_H *is* defined, so we do *not* enter the "if" block 
//#define HEADER_H 
// 
//class MyClass {}; 
// 
#endif   // end of the skipped "if" block 

तो, अंतिम परिणाम है कि MyClass परिभाषित किया गया केवल एक बार, ई है ven हालांकि हेडर दो बार शामिल किया गया था। और इसलिए परिणामी कोड मान्य है।

यह हेडर फ़ाइलों की एक महत्वपूर्ण संपत्ति है। हमेशा अपने शीर्षकों को परिभाषित करें ताकि उन्हें कई बार शामिल किया जा सके।

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