2010-06-17 22 views
15

कृपया नीचे दिए गए उदाहरण कोड को देखें:नेस्टेड क्लास सदस्य फ़ंक्शन संलग्न कक्षा के फ़ंक्शन तक नहीं पहुंच सकता है। क्यूं कर?

class A 
{ 
private: 
    class B 
    { 
    public: 
     foobar(); 
    }; 
public: 
    foo(); 
    bar(); 
}; 

कक्षा ए & बी कार्यान्वयन के भीतर:

A::foo() 
{ 
    //do something 
} 

A::bar() 
{ 
    //some code 
    foo(); 
    //more code 
} 

A::B::foobar() 
{ 
    //some code 
    foo(); //<<compiler doesn't like this 
} 

संकलक विधि foobar() के भीतर foo() को कॉल करता है। इससे पहले, मैंने कक्षा ए के निजी सदस्य समारोह के रूप में foo() को सार्वजनिक रूप से माना था कि बी का कार्य इसे देख नहीं सकता है। बेशक, यह मदद नहीं की। मैं ए की विधि द्वारा प्रदान की गई कार्यक्षमता का दोबारा उपयोग करने की कोशिश कर रहा हूं। संकलक इस फ़ंक्शन कॉल को क्यों अनुमति नहीं देता है? जैसा कि मैंने इसे देखा, वे एक ही संलग्न वर्ग (ए) का हिस्सा हैं। मैंने सोचा कि सी ++ मानकों में कक्षा को घेरने के लिए नेस्टेड क्लास मीबर के लिए एक्सेसिबिलिटी समस्या हल हो गई थी।

बी के लिए एक ही विधि (foo()) को फिर से लिखने के बिना मैं क्या करने की कोशिश कर रहा हूं, जो बी को ए के भीतर घोंसला रखता है?

मैं वीसी ++ कंपाइलर वर्-9 (विजुअल स्टूडियो 2008) का उपयोग कर रहा हूं। आपके सहयोग के लिए धन्यवाद।

उत्तर

14

foo()A का एक गैर स्थैतिक सदस्य फ़ंक्शन है और आप इसे बिना किसी उदाहरण के कॉल करने का प्रयास कर रहे हैं।
नेस्टेड क्लास B एक अलग वर्ग है जिसमें केवल कुछ एक्सेस विशेषाधिकार हैं और A के मौजूदा उदाहरणों के बारे में कोई विशेष ज्ञान नहीं है।

B जरूरतों एक A आप इसे इसे करने के लिए एक संदर्भ देना है, उदा .:

class A { 
    class B { 
     A& parent_; 
    public: 
     B(A& parent) : parent_(parent) {} 
     void foobar() { parent_.foo(); } 
    }; 
    B b_; 
public: 
    A() : b_(*this) {} 
}; 
+3

+1 के उपयोगकर्ताओं से छिपा रखना चाहता हूं, बस एक नाइटपिक - 'पैरेंट' शायद सदस्य चर के लिए सबसे अच्छा नाम नहीं है - विरासत के साथ आसान भ्रम। –

+1

मैं बस उल्लेख करना चाहता था कि नेस्टेड कक्षा बी के लिए कक्षा ए – manifest

+0

का संदर्भ रखने के लिए बहुत अच्छा डिजाइन कारण था उदाहरण के साथ स्पष्टीकरण के लिए धन्यवाद। सी ++ मानक 11.8, जिसे मैं अनुमान लगा रहा था कि यह बदल गया है, कक्षा के सदस्य द्वारा नेस्टेड कक्षा तक पहुंच के बारे में बात करता है। मुझे पता है कि जीसीसी नेस्टेड क्लास द्वारा एक्सेस की अनुमति देता है (मुझे इसके बारे में निश्चित है) लेकिन एमएस वीसी कंपाइलर नहीं करता है। हां दिलचस्प। – Rahul

0

यदि आप ए से कार्यक्षमता का पुन: उपयोग करना चाहते हैं तो आपको इसके अंदर ए नस्ट बी के उत्तराधिकारी होना चाहिए।

+1

मैं बी में एक की fucntionality का विस्तार नहीं कर रहा हूँ कोई त्रुटि मिलती है, इसलिए, कोई आवश्यकता नहीं है ए से विरासत में बी के लिए भी। मैं कक्षा ए – Rahul

1

लिए पहुंचते हैं तो यह एक automagic संभवतः nonportable चाल यद्यपि (++ हालांकि कुलपति पर काम किया 6.0 के बाद से) है। काम करने के लिए कक्षा बी को कक्षा ए का सदस्य होना चाहिए।

#ifndef OUTERCLASS 
#define OUTERCLASS(className, memberName) \ 
    reinterpret_cast<className*>(reinterpret_cast<unsigned char*>(this) - offsetof(className, memberName)) 
#endif 

class A 
{ 
private: 
    class B 
    { 
    public: 
     void foobar() { 
      A* pA = OUTERCLASS(A, m_classB); 
      pA->foo(); 
     } 
    } m_classB; 
public: 
    foo(); 
    bar(); 
}; 
+0

धन्यवाद, इगोर मेरे प्रश्न पर सांस लेने और उदाहरण प्रदान करने के लिए। आप और जॉर्ज के पास बाहरी वर्ग के संदर्भ के साथ लगभग समान कार्यान्वयन है, हालांकि, मैंने जॉर्ज की प्रतिक्रिया का चयन किया है क्योंकि यह क्लीनर है। – Rahul

+0

कोई चिंता नहीं, यह सब एक सुंदर बुरा लग रहा हैक के बाद है। ऐसा कहकर, यह बहुत विश्वसनीय रहा है और यह बहुत मजेदार है :) –

0

असल में क्या जोर्ज Fritzsche कहा

#include <iostream> 
#include <cstring> 
using namespace std; 

class A 
{ 
private: 
    class B 
    { 
    A& parent_; 
    public: 
     //B(); //uncommenting gives error 
     ~B(); 
     B(A& parent) : parent_(parent) {} 

     void foobar() 
     { 
     parent_.foo(); 
     cout << "A::B::foo()" <<endl; 
     } 

     const std::string& foobarstring(const std::string& test) const 
     { 
     parent_.foostring(test); cout << "A::B::foostring()" <<endl; 
     } 
    }; 
public: 
    void foo(); 
    void bar(); 
    const std::string& foostring(const std::string& test) const; 
    A(); 
    ~A(){}; 
    B b_; 
}; 

//A::B::B() {}; //uncommenting gives error 
A::B::~B(){}; 

A::A():b_(*this) {} 


void A::foo() 
{ 
    cout << "A::foo()" <<endl; 
} 

const std::string& A::foostring(const std::string& test) const 
{ 
    cout << test <<endl; 
    return test; 
} 

void A::bar() 
{ 
    //some code 
    cout << "A::bar()" <<endl; 
    foo(); 
    //more code 
} 

int main(int argc, char* argv[]) 
{ 
A a; 
a.b_.foobar(); 
a.b_.foobarstring("hello"); 

return 0; 
} 

आप डिफ़ॉल्ट बी निर्माता uncomment यदि आप

+0

मुझे त्रुटि नहीं मिली। – cbinder

+0

@cbinder 'ए :: बी :: बी() {};' भी असम्बद्ध करने का प्रयास करें – enthusiasticgeek

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

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