2012-03-17 15 views
5

से गृहीत को छिपाने के लिए मैं कैसे एक प्रकार एक उस प्रकार टी का एक उद्देश्य के लिए अपने छिपा गृहीत उपज लेकिन बाकी सब से गृहीत छुपा देगा चाहते हैं। मेरा सी ++ कंपाइलर जीसीसी 4.4 होता है, लेकिन इससे कोई फर्क नहीं पड़ता। यह क्यों काम नहीं करेगा?हर किसी को है, लेकिन कक्षा टी

#include <iostream> 

template <class T> class A { 
    private: 
    int n1; 
    public: 
    friend class T; 
    A(const int n0 = 0) : n1(n0) {} 
}; 

class B { 
    public: 
    int f(const A<B> a) const { return a.n1; } 
    B() {} 
}; 

int main() { 
    const A<B> a(5); 
    const B b; 
    const int m = b.f(a); 
    std::cout << m << "\n"; 
    return 0; 
} 

संयोग से, इस ठीक काम करता है, को छोड़कर यह गृहीत को छिपाने के लिए विफल रहता है कि:

#include <iostream> 

template <class T> class A { 
    private: 
    int n1; 
    public: 
    int n() const { return n1; } 
    A(const int n0 = 0) : n1(n0) {} 
}; 

class B { 
    public: 
    int f(const A<B> a) const { return a.n(); } 
    B() {} 
}; 

int main() { 
    const A<B> a(5); 
    const B b; 
    const int m = b.f(a); 
    std::cout << m << "\n"; 
    return 0; 
} 

करता है सी ++ वास्तव में एक दोस्त वर्ग टेम्पलेट पैरामीटर के रूप में संकलन समय पर निर्दिष्ट किया जा करने की अनुमति नहीं? क्यों नहीं? यदि नहीं, तो डेटाम को छिपाने के लिए मुझे किस वैकल्पिक तकनीक का उपयोग करना चाहिए? (यदि संभव हो तो एक संकलन-समय तकनीक पसंद करेगी।)

कृपया मेरी गलतफहमी क्या है, कृपया?

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

धन्यवाद।

उत्तर

1

मुझे आपकी त्रुटि के पीछे मानक नहीं पता है (ज़ीओ का जवाब देखें), लेकिन मुझे सी ++ 03 के लिए एक समाधान मिला।

#include <iostream> 

template <class T> class A { 
    private: 
    int n1; 
    public: 
    friend int T::getN1(const A& a) const; 
    A(const int n0 = 0) : n1(n0) {} 
}; 

class B { 
    public: 
    int f(const A<B> a) const { return getN1(a); } 
    B() {} 
    private: 
    int getN1(const A<B>& a) const {return a.n1;} 
}; 

class C { 
    public: 
    int f(const A<B> a) const { return getN1(a); } 
    C() {} 
    private: 
    // Error, n1 is a private member of A<B> 
    int getN1(const A<B>& a) const {return a.n1;} 
}; 

int main() { 
    const A<B> a(5); 
    const B b; 
    const int m = b.f(a); 
    std::cout << m << "\n"; 
    return 0; 
} 

वैकल्पिक रूप से, आप टी की एक नेस्टेड वर्ग/struct कर सकते हो ए के एक दोस्त यह हो सकता है: इसके बजाय T बनाने एक दोस्त की, T के सदस्य कार्यों में से एक एक दोस्त बनाने के अधिक सुविधाजनक यदि ए के कई निजी सदस्य हैं जिन्हें आप टी तक पहुंच चाहते हैं।

#include <iostream> 

template <class T> class A { 
    private: 
    int n1; 
    public: 
    friend class T::AccessToA; 
    A(const int n0 = 0) : n1(n0) {} 
}; 

class B { 
    public: 
    int f(const A<B> a) const { return AccessToA::getN1(a); } 
    B() {}; 
    private: 
    friend class A<B>; 
    struct AccessToA 
    { 
     static int getN1(const A<B>& a) {return a.n1;} 
    }; 
}; 

class C { 
    public: 
    int f(const A<B> a) const { return AccessToA::getN1(a); } 
    C() {}; 

    private: 
    friend class A<C>; 
    struct AccessToA 
    { 
     // Error, n1 is a private member of A<B> 
     static int getN1(const A<B>& a) {return a.n1;} 
    }; 
}; 

int main() { 
    const A<B> a(5); 
    const B b; 
    const int m = b.f(a); 
    std::cout << m << "\n"; 
    return 0; 
} 
+0

अच्छी सलाह। जब तक मैं कुछ बेहतर तरीके से नहीं आ सकता, मुझे सलाह का पालन करना चाहिए। धन्यवाद। – thb

+0

ज़ीओ द्वारा सुझाए गए पासकी मुहावरे के साथ-साथ अटॉर्नी-क्लाइंट मुहावरे को भी देखें। यह थोड़ी देर हो गया है क्योंकि मैंने उन लोगों के बारे में पढ़ा है, इसलिए मेरा समाधान उन मुहावरों का एक रूप हो सकता है। –

4

आपका कंपाइलर बस बहुत पुराना है। सी ++ 11 आपको टेम्पलेट पैरामीटर को दोस्तों के रूप में घोषित करने की अनुमति देता है।

§11.3 [class.friend] p3

एक दोस्त ने घोषणा कि एक समारोह की घोषणा नहीं करता निम्नलिखित रूपों में से एक होगा:

  • friendelaborated-type-specifier;
  • friendsimple-type-specifier;
  • friendtypename-specifier;

एक friend घोषणा में प्रकार निर्दिष्टकर्ता (संभवत: सीवी-योग्य) वर्ग प्रकार निर्दिष्ट करता है, तो उस वर्ग एक friend के रूप में घोषित किया जाता है; अन्यथा, मित्र घोषणा को नजरअंदाज कर दिया जाता है।

और यह भी एक दोस्त के रूप में टेम्पलेट पैरामीटर का एक उदाहरण:

class C; 
// [...] 
template <typename T> class R { 
    friend T; 
}; 

R<C> rc; // class C is a friend of R<C> 
R<int> ri; // OK: "friend int;" is ignored 

सी ++ 03 उदासी कोई रास्ता नहीं यह करने के लिए है, फिर भी आप कर सकते हैं बस दोस्त एक भी मुक्त समारोह और जाने वह "गोंद" कोड के रूप में कार्य करता है जो डेटा को एक वर्ग से ले जाता है और इसे दूसरे स्थान पर ले जाता है। एक और तरीका passkey pattern हो सकता है।

+0

मैं देखता हूं। धन्यवाद। रोशनी पासकी लिंक के लिए भी धन्यवाद। – thb