2010-05-14 20 views
10

मेरे सी ++ प्रोजेक्ट में मुझे हेडर फ़ाइलों के समावेशन (#include "myclass.h") का उपयोग करना होगा? और मुझे कक्षा के आगे की घोषणा का उपयोग कब करना होगा (class CMyClass;)?शीर्षलेख फ़ाइलें शामिल/अग्रेषित घोषणा

+1

http://stackoverflow.com/questions/553682/when-to-use-forward-declaration देखें – ChrisN

उत्तर

16

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

  1. कक्षा के सदस्य या कार्य को एक्सेस करें।
  2. पॉइंटर अंकगणित का प्रयोग करें।
  3. आकार का उपयोग करें।
  4. कोई भी आरटीटीआई जानकारी।
  5. new/delete, प्रतिलिपि आदि
  6. इसे मूल्य के आधार पर उपयोग करें।
  7. इससे प्रवेश करें।
  8. इसे एक सदस्य के रूप में रखें।
  9. फ़ंक्शन में इंस्टेंस।

(6,7,8,9 @Mooing बतख से)

वे शायद और अधिक कर रहे हैं, लेकिन मैं आज पर मेरी भाषा कानून टोपी नहीं मिला है।

+4

आप भी इसे करने के लिए शामिल करने की ज़रूरत मूल्य से इसका इस्तेमाल करें। तो यदि आप इससे प्राप्त करते हैं, तो इसे सदस्य के रूप में लें, या किसी फ़ंक्शन में एक उदाहरण दें। –

10

यदि आपको कक्षा में केवल एक सूचक की आवश्यकता है और आपको कक्षा के बारे में किसी भी ज्ञान की आवश्यकता नहीं है, तो आप आगे की घोषणा का उपयोग कर सकते हैं।

2

शुरुआत के रूप में, आपको हमेशा उन प्रकारों या कार्यों का उपयोग करने की आवश्यकता होने पर हेडर फाइलों को शामिल करना चाहिए - चीजों को घोषित करके अपने निर्माण को "अनुकूलित" करने का प्रयास न करें - यह शायद ही कभी आवश्यक है, यहां तक ​​कि बड़े पैमाने पर परियोजनाओं, बशर्ते परियोजना अच्छी तरह से वास्तुकार है।

केवल समय आप पूरी तरह जरूरत है एक आगे घोषणा इस तरह की स्थितियों में है:

struct A { 
    void f(B b); 
}; 

struct B { 
    void f(A a); 
}; 

जहां प्रत्येक struct (या वर्ग) अन्य के प्रकार को दर्शाता है। इस मामले में, आप समस्या को हल करने के लिए बी के आगे घोषणा की जरूरत है:

struct B; // forward declaration 

struct A { 
    void f(B b); 
}; 

struct B { 
    void f(A a); 
}; 
+0

बड़ी परियोजनाओं पर रखरखाव करना जिसमें एक बड़ी "forward_declarations.h" फ़ाइल एक दुःस्वप्न हो सकती है क्योंकि यह अक्सर विकास उपकरण को भ्रमित करती है और इसे अपरिचित कोड आधार ब्राउज़ करना कठिन बनाता है। हालांकि कभी-कभी आपके कोड में युग्मन को कम करने के लिए महत्वपूर्ण होता है, न केवल प्रत्येक वर्ग को अगली डीसी फ़ाइल में डाल दें। – bd2357

2

आप दोनों आदेश संकलन के समय को कम करने के लिए, लेकिन यह भी प्रतिरूपकता और testability के साथ मदद करने के लिए अपने #include रों को कम करने की दिशा में प्रयास करना चाहिए। जैसा कि @ypnos कहते हैं, कक्षा के आगे उत्कृष्ट होते हैं जब आपको केवल पॉइंटर्स की आवश्यकता होती है।

शीर्षलेख निर्भरताओं को कम करने के तरीके पर कुछ व्यावहारिक युक्तियों के लिए, उदाहरण देखें। this article

11

घोषणा अग्रेषित करने के लिए कई समस्याएं हैं:

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

    include "MyProject/MyWidgets/MyFooWidgets/FooUtil/Foo.h" 
    
    आगे घोषणा

    बजाय

    class Foo ; 
    

    यह आसान जहां वर्ग फू घोषित किया जाता है दूसरों को खोजने के लिए है। आगे की घोषणा के साथ, यह स्पष्ट नहीं है; एक्सेप्से जैसे कुछ आईडीई अग्रेषित घोषणा खोल सकते हैं जब उपयोगकर्ता को एक चर की घोषणा खोलने का प्रयास करता है।

  • लिंकिंग अपरिभाषित प्रतीक त्रुटियों के साथ असफल हो सकती है जब आप अपने कोड में एक हेडर फ़ाइल शामिल करते हैं जिसमें आगे की घोषणा होती है लेकिन वास्तविक कोड परिभाषा किसी अन्य लाइब्रेरी में स्थित होती है जिसे आपने लिंक नहीं किया था। "Could not find file MyProject/MyWidgets/MyFooWidgets/FooUtil/Foo.h" जैसी त्रुटियों के साथ संकलन समय पर इस समस्या को पकड़ना अधिक सुविधाजनक है, तब से आप जानते होंगे कि संबंधित Foo.cpp के लिए कहां देखना है और इसमें शामिल लाइब्रेरी की पहचान करें।

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

तो घोषणा कब करना ठीक है? यदि आप इसे वास्तविक हेडर फ़ाइल में वास्तविक घोषणा के रूप में करते हैं।

उदाहरण:

class Foo ; 

typedef Foo* FooPtr ; 
typedef Foo& FooRef ; 

class Foo 
{ 
    public: 
     Foo() ; 
     ~Foo() ; 
} 

या

class TreeNode ; 

class Tree 
{ 
private: 
    TreeNode m_root ; 
} 

class TreeNode 
{ 
    void* m_data ; 
} ; 
+1

मैं आगे की घोषणाओं के लिए @ डेविड सूचियों की समस्याओं से सहमत हूं। लेकिन मैं इस निष्कर्ष से असहमत हूं: "तो घोषणा कब करना ठीक है? अगर आप इसे वास्तविक घोषणा के रूप में एक ही हेडर फ़ाइल में करते हैं।" जैसा कि अन्य ने इंगित किया है, आगे की घोषणा भौतिक लेआउट को कम करने और गति को बढ़ाने के लिए एक महत्वपूर्ण उपकरण है। // अधिक से अधिक मुझे आश्चर्य है कि हमें # Foo.hf "शामिल करना चाहिए - .hf" एक हेडर फ़ाइल जिसमें आगे की घोषणाओं को छोड़कर कुछ भी नहीं है। " // बेशक, मैं स्वचालित रूप से इसे उत्पन्न करूंगा। –

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