2012-03-27 18 views
10

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

मेरी कक्षाओं के

सभी और (उप) फ़ोल्डरों के माध्यम से अलग होती है एक अलग और सीपीपी फ़ाइल में हर एक को है, लेकिन इस निर्भरता के बारे में लग रहा है करने के लिए पर्याप्त होना चाहिए:

// FE.h - no implementations - no .cpp file 
class FE 
{ 
    private: 
     virtual void somePrivateFunc() = 0; 
    // 90% virtual class, interface for further implementations 
    friend class TLS; 
}; 

// DummyFE.h 
#include "FE.h" 
class DummyFE :: public FE { 
    /* singleton dummy */ 
    private: 
     // constructor 
    public: 
     static DummyFE& instance(); 
}; 
// DummyFE.cpp 
#include "DummyFE.h" 
// all Dummy FE implementation 

// ImplFE.h 
#include "FE.h" 
class ImplFE :: public FE { /* implemented */ }; 
// ImplFE.cpp 
#include "FE.cpp" 
// all Impl FE implementations 


// SD.h - implements strategy design pattern 
//  (real project has more than just FE class in here) 
#include "FE.h" 
#include "DummyFE.h" 
class SD 
{ 
    private: 
     FE &localFE; 
    public: 
     SD(FE &paramFE = DummyFE::instance()); 
    // ... and all the other phun stuff ... 
    friend class TLS; 
}; 
// SD.cpp - implementations 
# include "SD.h" 
/* SD implemented */ 

// TLS.h - implements strategy design pattern 
      (on a higher level) 
#include SD.h 
class TLS{ 
    private: 
     SD *subStrategy; 
    public: 
     void someFunctionRequiringFriendliness(); 
} 

// TLS.cpp - implementations 
#include "TLS.h" 
void TLS::someFunctionRequiringFriendliness(){ 
    this->subStrategy->localFE.somePrivateFunc(); // ok! 
} 

अब, मुझे पार्टी को सभी निर्भरताओं के साथ वास्तव में संकलित करने के लिए यह मिल रहा है (इसे इसे काम करने के लिए अंत में कक्षा आरेख में लिखना था), लेकिन अब यह करता है। तथ्य यह है कि वास्तव में मुझे भ्रमित कर रहा है, यह कोई आगे की घोषणा की आवश्यकता नहीं थी। मैं पहले से आगे की घोषणाओं के बारे में जानता हूं, और बस मामले में, मैंने this answer के साथ अपनी याददाश्त को ताज़ा कर दिया।

तो, कोशिश करते हैं और यह स्पष्ट रखने के लिए, मेरे सवाल: जब एक दोस्त के रूप class TLS घोषणा करते हुए किस तरह कोई स्पष्ट आगे घोषणाओं की जरूरत थी? क्या इसका मतलब यह है कि friend class घोषणा सभी में आगे की घोषणा है? मेरे लिए, सहजता से, यहां कुछ याद आ रही है ... और चूंकि यह सामान्य रूप से संकलित और काम करता है, क्या कोई मेरी अंतर्ज्ञान को सही करने में मदद कर सकता है? : डी

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

उत्तर

6

आप सही हैं, मित्र घोषणा एक आगे की घोषणा की तरह है।

निम्नलिखित compiles:

class A; 
class B 
{ 
    friend A; 
}; 

या

class B 
{ 
    friend class A; 
}; 

इस नहीं करता है:

class B 
{ 
    friend A; 
}; 

यह नहीं वास्तव में friend घोषणा कि आगे की वाणी class A, लेकिन class ke yword। यही कारण है कि दूसरा उदाहरण काम नहीं करता है, क्योंकि यह नहीं जानता कि A क्या है। यदि आप पहले स्निपेट की तरह A घोषित करते हैं, तो यह कक्षा घोषणा के लिए A को हल कर सकता है।

I stand corrected.

+0

एचएम। अजीब। मेरे पास सिर्फ वह स्थिति है जो आपने कहा है * कोड के मेरे संस्करण में संकलित नहीं है (यह इस तथ्य से यहां परिलक्षित होता है कि एफई टीएलएस घोषित नहीं करता है, या इसे बिल्कुल शामिल नहीं करता है) - और यह काम करता है! यही मुझे भ्रमित कर रहा है! आह, और साथ ही, मैंने अभी देखा है कि आपने 'मित्र श्रेणी ए' के ​​बजाय वाक्यविन्यास 'मित्र ए' का उपयोग किया था। क्या आप उस पर विस्तार कर सकते हैं, क्या मैंने गलती से आगे बढ़ने और मित्र घोषणा को एक में विलय करने का प्रबंधन किया? – penelope

+1

नोट: पहला स्निपेट सी ++ 03 में संकलित नहीं होगा (उन लोगों के लिए जो अभी तक सी ++ 11 का उपयोग नहीं कर सकते हैं)। दूसरा स्निपेट जी ++ 4.5 या क्लैंग ++ 3.0 (यहां तक ​​कि सी ++ 11 मोड में) के साथ संकलित नहीं है। –

+0

@ लचियन मैं उलझन में हूं कि आपने अपना दूसरा उदाहरण कैसे संकलित किया? इसने मुझे यह प्रश्न पूछने के लिए प्रेरित किया जो आपके दूसरे उदाहरण को संकलित नहीं करना चाहिए: http://stackoverflow.com/questions/14114956/friend-declaration-not-forward-declaring – JaredC

0

कि मतलब यह है कि एक दोस्त वर्ग घोषणा एक आगे यह सारे घोषणा स्वयं है?

हाँ

7
friend class TLS; 

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

विशेष रूप से, जब तक कि नामांकन नाम में घोषणा भी न हो, friend घोषणा में घोषित एक फ़ंक्शन केवल तर्क निर्भर लुकअप (और कक्षा के बाहर परिभाषित नहीं किया जा सकता) द्वारा पाया जा सकता है। कक्षाओं के लिए यह वही है, जब तक कि नामस्थान स्तर पर कोई घोषणा न हो, तब तक घोषित प्रकार कक्षा के बाहर इसे मित्र के रूप में घोषित नहीं किया जाएगा।

class B { 
    friend class A; 
}; 
//A foo(); // Error: A is not declared here! 
class A; 
A foo();  // Fine 
+0

मैं बस सोच रहा था कि मुझे 'एफई' और' एसडी 'में स्पष्ट रूप से' टीएलएस 'घोषित करने की आवश्यकता क्यों नहीं है, लेकिन यह बहुत सारी नई जानकारी है। आपने जो सुझाव दिया है (किसी अन्य वर्ग 'शरीर में केवल * * * घोषित करना) का उपयोग कक्षा के आंतरिक उपयोगिता कार्यों या ऐसे कुछ को लागू करने के लिए किया जाएगा? – penelope

+0

@पेनेलोप: मुझे लगता है कि यह लुकअप कैसे किया जाता है इसका एक दुष्प्रभाव है। मैंने इसे प्रकारों के बारे में ज्यादा विचार नहीं दिया है, जहां इसका मतलब है * एक प्रकार ए है जिसके पास इस वर्ग * तक पहुंच है, और कुछ भी नहीं (यानी आप 'बी' के अंदर भी 'ए' का उचित प्रकार के रूप में उपयोग नहीं कर सकते)। लेकिन कार्यों के मामले में और विशेष रूप से यदि आप कक्षा परिभाषा के अंदर फ़ंक्शन को परिभाषित करते हैं तो यह लुकअप को थोड़ा सा प्रभावित करता है। –

2

आगे घोषणा फ़ाइल के शीर्ष पर होना करने के लिए इस प्रकार

class A; 
class C; 
class D; 
class B 
{ 
    A* a; 
    C* c; 
    D* d; 
}; 

रूप

class B 
{ 
    class A* a; 
    class C* c; 
    class D* d; 
}; 

सिफारिश दोस्त वाक्य रचना सिर्फ बाद में उपयोग करता ही है की जरूरत नहीं है

+1

मित्र घोषणाओं के लिए यह * अनुशंसित नहीं है * बल्कि * आवश्यक * सी ++ 03 में, और सी ++ 11 में थोड़ा अलग अर्थ है (जहां और 'मित्र वर्ग एक्स' का उपयोग टेम्पलेट पैरामीटर को संदर्भित करने के लिए नहीं किया जा सकता है) –

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