c++ - सी++में एक दूसरे को शामिल करने वाले शीर्षलेख




recursion header include (7)

मैं एक सी ++ नौसिखिया हूं, लेकिन मुझे ऑनलाइन (सबसे अधिक संभावना मामूली) प्रश्न का उत्तर ऑनलाइन नहीं मिला। मुझे कुछ कोड संकलित करने में कुछ परेशानी हो रही है जहां दो वर्ग एक-दूसरे को शामिल करते हैं। शुरू करने के लिए, क्या मेरे # अंतर्निहित बयान मेरे मैक्रोज़ के अंदर या बाहर जाना चाहिए? व्यवहार में, यह कोई फर्क नहीं पड़ता है। हालांकि, इस विशेष मामले में, मुझे परेशानी हो रही है। मैक्रोज़ के बाहर # अंतर्निहित बयान डालने से संकलक को रिकर्स करने का कारण बनता है और मुझे "# गहराई से घिरा हुआ" त्रुटियां मिलती हैं। यह मुझे समझ में आता है क्योंकि # शामिल होने से पहले न तो कक्षा पूरी तरह से परिभाषित की गई है। हालांकि, आश्चर्यजनक रूप से, जब मैं उन्हें अंदर रखने की कोशिश करता हूं, तो मैं कक्षाओं में से किसी एक को घोषित करने में असमर्थ हूं, क्योंकि यह पहचाना नहीं गया है। संक्षेप में, मैं संकलन करने की कोशिश कर रहा हूं:

आह

#ifndef A_H_
#define A_H_

#include "B.h"

class A
{
    private:
        B b;

    public:
        A() : b(*this) {}
};

#endif /*A_H_*/

Bh

#ifndef B_H_
#define B_H_

#include "A.h"

class B
{
    private:
            A& a;

    public:
        B(A& a) : a(a) {}
 };

#endif /*B_H_*/

main.cpp

#include "A.h"

int main()
{
    A a;
}

यदि इससे कोई फर्क पड़ता है, तो मैं g ++ 4.3.2 का उपयोग कर रहा हूं।

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


Answers

कुछ कंपाइलर्स (इंक। जीसीसी) #pragma का भी समर्थन करते हैं, हालांकि आपके प्रश्न में 'गार्ड शामिल' मुहावरे सामान्य अभ्यास है।


ऊप्स! मुझे लगता है कि मुझे एक समाधान मिला जिसमें कक्षा के अंदर # अंतर्निहित बयान डालने और आगे की घोषणा का उपयोग करना शामिल है। तो, कोड इस तरह दिखता है:

#ifndef A_H_
#define A_H_

class B;

#include "B.h"

class A
{
    private:
            B b;

    public:
            A() : b(*this) {}
};

#endif /*A_H_*/

और इसी तरह कक्षा बी के लिए यह संकलित करता है, लेकिन क्या यह सबसे अच्छा तरीका है?


और बस स्पष्ट होने के लिए, सामान्य रूप से, कहां बयान शामिल करना चाहिए?

आपके द्वारा उल्लिखित कारणों के लिए गार्ड शामिल करें।

आपकी दूसरी समस्या के लिए: आपको कक्षाओं में से कम से कम एक को अग्रेषित करने की आवश्यकता है, उदाहरण के लिए:

#ifndef B_H_
#define B_H_

// Instead of this:
//#include "A.h"

class A;

class B
{
    private:
            A& a;

    public:
            B(A& a) : a(a) {}
 };

#endif /*B_H_*/

यह केवल घोषणाओं के लिए काम करता है हालांकि: जैसे ही आप वास्तव में A उदाहरण का उपयोग करते हैं , आपको इसे भी परिभाषित करने की आवश्यकता होती है।

वैसे, नाथन क्या कहता है सत्य है: आप क्लास के उदाहरणों को एक-दूसरे में दोबारा नहीं डाल सकते हैं। यह केवल संकेतों के लिए पॉइंटर्स (या, आपके मामले में, संदर्भ) के साथ काम करता है।


"मैक्रोज़" से मेरा मानना ​​है कि #ifndef में गार्ड शामिल हैं? यदि ऐसा है, तो # निश्चित रूप से अंदर जाना चाहिए। यह प्रमुख कारणों में से एक है जिसमें गार्ड शामिल हैं, क्योंकि अन्यथा आप आसानी से एक अनंत रिकर्सन के साथ समाप्त होते हैं जैसा आपने देखा था।

वैसे भी, समस्या यह है कि जब आप ए और बी कक्षाओं (दूसरे वर्ग के अंदर) का उपयोग करते हैं, तब तक उन्हें अभी तक घोषित नहीं किया गया है। देखें कि # समावेशन संसाधित होने के बाद कोड कैसा दिखता है:

//#include "A.h" start
#ifndef A_H_
#define A_H_

//#include "B.h" start
#ifndef B_H_
#define B_H_

//#include "A.h" start
#ifndef A_H_ // A_H_ is already defined, so the contents of the file are skipped at this point
#endif /*A_H_*/

//#include "A.h" end

class B
{
    private:
            A& a;

    public:
            B(A& a) : a(a) {}
 };

#endif /*B_H_*/

//#include "B.h" end

class A
{
    private:
            B b;

    public:
            A() : b(*this) {}
};

#endif /*A_H_*/
//#include "A.h" end

int main()
{
    A a;
}

अब कोड पढ़ें। बी कंपाइलर मुठभेड़ों की पहली श्रेणी है, और इसमें A& सदस्य शामिल हैं। A क्या है कंपाइलर को अभी तक A की किसी भी परिभाषा का सामना नहीं हुआ है, इसलिए यह एक त्रुटि जारी करता है।

समाधान ए की आगे की घोषणा करना है बी की परिभाषा से पहले किसी बिंदु पर, एक लाइन class A; जोड़ें class A;

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


एक अच्छे सॉफ्टवेयर डिजाइन में दो वर्गों के बीच निर्भरता पेड़ के रूप में खींचा जा सकता है।

इस कारण से सी ++ दो .h फाइलों को # एक दूसरे को शामिल नहीं करेगा।


ऐसी परिस्थितियों में, मैं आगे की घोषणाओं के साथ सभी स्रोतों में शामिल होने के लिए एक सामान्य शीर्षलेख बनाता हूं:

#ifndef common_hpp
#define common_hpp

class A;
class B;

#endif

फिर व्यक्तिगत वर्ग शीर्षलेख फ़ाइलों को आम तौर पर अन्य वर्गों के संदर्भ में किसी भी # शामिल करने की आवश्यकता नहीं होती है, यदि आवश्यक हो तो उन वर्गों के पॉइंटर्स या संदर्भ हैं। आधा समय हालांकि उन शीर्षकों में अन्य उपहार हैं, लेकिन कम से कम परिपत्र संदर्भों के साथ किसी भी समस्या को सामान्य.hpp के साथ हल किया जाता है


उपयोग

ob_start ();

आपकी लिपि के शीर्ष पर, और

ob_end_flush ();

आपकी लिपि के नीचे। इस पृष्ठ को बफर करने के बाद आउटपुट बफरिंग हो जाएगी और आपके हेडर बनाए जाएंगे।

सामान्य समस्यायें:

====================

( source से कॉपी किया गया: source )

1) header(.......); से पहले कोई आउटपुट (यानी echo.. या एचटीएमएल कोड) नहीं होना चाहिए header(.......); आदेश।

2) <?php और बाद में ?> टैग से पहले किसी भी सफेद-स्थान (या नई लाइन ) को हटा दें।

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

4) header(...); बाद header(...); आपको exit; उपयोग करना चाहिए exit;

5) हमेशा 301 या 302 संदर्भ का उपयोग करें:

header("location: http://example.com",  true,  301 );  exit;

6) त्रुटि रिपोर्टिंग चालू करें। और त्रुटि बताओ।

7) यदि उपरोक्त में से कोई भी मदद नहीं करता है, तो JAVSCRIPT पुनर्निर्देशन (हालांकि, दृढ़ता से अनुशंसित विधि) का उपयोग करें, कस्टम मामलों में अंतिम मौका हो सकता है ...:

echo "<script type='text/javascript'>window.top.location='http://website.com/';</script>"; exit;




c++ recursion header include