2011-12-23 6 views
8

कृपया my first attempt at answering this देखते हैं। चीजों को सरल बनाने के प्रयास में मैंने पूरी कहानी बताने के लिए उपेक्षित किया। मेरा उदाहरण काम करता है! माफ़ कीजिये।मैं कैसे एक पुस्तकालय के भीतर से मेरी कक्षा का मुख्य एक दोस्त कैसे करूं?

पूरी कहानी है कि यह एक पुस्तकालय एक फ़ाइल में एक वर्ग और एक अन्य फ़ाइल में मुख्य, सभी मेरे पुस्तकालय में जुड़ा हुआ होता है है। पुस्तकालय एक प्रक्रिया ढांचे के लिए आधार प्रदान कर रहा है, यही कारण है कि मुख्य पुस्तकालय में है, न कि प्रक्रिया।

नीचे मैं क्या है के नीचे छीन संस्करण है।

pf.hpp

using namespace std; 

namespace MyNamespace 
{ 
    class ProcessManager 
    { 
    public: 
    friend int main(int argc, char** argv); 
    private: 
    void test(); 
    }; 
}; 

pf.cpp

#include "pf.h" 

namespace MyNamespace 
{ 
    ProcessManager::test() 
    { 
    cout << "My friend has accessed my member" << endl; 
    } 
}; 

pfmain.cpp

#include "pf.hpp" 

int main(int argc, char** argv) 
{ 
    ProcessManager pm; 

    pm.test(); 
} 

ध्यान दें कि यह पुस्तकालय

के संकलन पर विफल रहता है क्या मैं कोशिश की है:

  • सभी जगह
  • मुख्य उपयोग वैश्विक विस्तार करने के लिए दोस्त संदर्भ बनाना अधिक दोस्त बढ़ते (जैसे :: मुख्य)
  • मेकिंग दोस्त और मुख्य घोषणाओं वैश्विक क्षेत्र

मैं क्या याद आ रही है का उपयोग करें?

धन्यवाद!

+1

यह थोड़ा सा विषय है, लेकिन बहुत से लोग कहेंगे कि 'मित्र' कीवर्ड कभी भी एक अच्छा समाधान नहीं है। – asveikau

+0

यह आदर्श नहीं है मैं सहमत हूं, लेकिन कभी-कभी आपके पास कोई अन्य अच्छा विकल्प नहीं है – Jaime

+0

'मुख्य() 'के अन्य रूपों को फेंकने पर विचार करना चाहता हूं। यकीन नहीं है कि वे फेसबुक पर हैं या नहीं। –

उत्तर

9

बस MyNamespace बाहर मुख्य घोषित करने और दोस्त बयान में वैश्विक नामस्थान :: निर्दिष्ट

//in header file of ProcessManager 
//your pf.h 

int main(int argc, char** argv); 

namespace MyNamespace 
{ 
    class ProcessManager 
    { 
    public: 
    friend int ::main(int argc, char** argv); 
    private: 
    void test(); 
    }; 
}; 
+0

मुझे नहीं पता कि संकलक मेरे मामले में pfmain.cpp से मुख्य क्यों नहीं देख पाएगा, लेकिन यह काम करता है। धन्यवाद! – Jaime

+0

पिछले प्रयासों में त्रुटि दिखाई देगी "त्रुटि: 'int main (int, char **)' को '::' के अंदर घोषित किया जाना चाहिए था, जो पर्याप्त कह रहा था, लेकिन मुझे कभी उम्मीद नहीं थी कि संकलक जांच न करे प्रतीक के लिए अन्य .o फाइलें हैंडर हेडर कैसे सेट हैं .. – Jaime

+0

@ सीए ++ मुख्य() में जैम वैश्विक नामस्थान में घोषित किया जाना चाहिए। हालांकि नाम आरक्षित नहीं है और अन्य कार्यों के बीच सदस्य कार्यों और नामस्थानों के लिए उपयोग किया जा सकता है। –

0

एक आम जवाब है, "एप्लिकेशन" सिंगलटन वर्ग प्रदान करने के लिए जैसे जैसे हो सकता है क्यूटी में QApplication, एक तरह

int main (int argc, char** argv) { 
    YourApplication app (argc, argv); 
    return app.execute(); 
} 

कुछ करने के लिए अपने main को कम तो फिर तुम class YourApplication अपने अन्य वर्गों बनाम करने के लिए अपने friendness चिंता को कम करने, और आप देखेंगे कि कैसे करना है पता है।

+0

कक्षा वास्तव में पहले से ही एक सिंगलटन है, मैंने अभी उस भाग को नहीं दिखाया। एक सिंगलटन होने से इस मुद्दे को हल नहीं किया जाता है .. – Jaime

0

मुझे नहीं लगता कि आप वास्तव में आप क्या कर रहे क्या करना चाहते हैं। यह वास्तव में एक हैक और एक डिजाइन समस्या की तरह लगता है। क्या तुम सच में कुछ विशेष परिस्थिति में अपने वर्ग के आंतरिक बेनकाब करने के लिए चाहते हैं, आप एक्सेसर वर्ग जो भी अपने पुस्तकालय के अंदर परिभाषित किया गया है बना सकते हैं।

कुछ इस तरह काम कर सकते हैं (उचित आगे घोषणाओं, आदि पड़े - यह सिर्फ एक प्रारंभिक बिंदु है):

class ProcessManagerAccessor 
{ 
public: 
    ProcessManagerAccessor(ProcessManager & pm) : pm_(pm) { } 

    // add public methods to expose internals 
    void test() { pm_.test(); } 

private: 
    ProcessManager & pm_; 
}; 

class ProcessManager 
{ 
public: 
    friend class ProcessManagerAccessor; 

    // ... 
}; 

// ... 

ProcessManager pm; 
ProcessManagerAccessor pma(pm); 
pma.test(); 
+0

"आम तौर पर, आप परीक्षण के लिए किसी भी encapsulation को तोड़ना नहीं चाहते हैं (या जैसे माँ कहती थी," अपने निजी लोगों का पर्दाफाश न करें! ")। अधिकांश समय, आप अपनी सार्वजनिक विधियों का उपयोग करके कक्षा का परीक्षण करने में सक्षम होना चाहिए। यदि निजी या संरक्षित पहुंच के पीछे छिपी हुई महत्वपूर्ण कार्यक्षमता है, तो यह चेतावनी संकेत हो सकता है कि बाहर निकलने के लिए संघर्ष करने वाली एक और कक्षा है। " – bobbymcr

+0

मुझे इसे मुख्य पहुंच देने से अलग नहीं दिखता है। मुद्दा यह है कि मेरी कक्षा एक सिंगलटन है, बिना पैरा के तत्काल, लेकिन मुझे प्रोसेस मैनेजर के व्युत्पन्न वर्ग पर नियंत्रण देने से पहले मुझे कुछ राज्य मुख्य में सेट करने की आवश्यकता है। मैं नहीं चाहता कि इन विधियों को व्युत्पन्न वर्ग द्वारा पहुंचा जा सके। – Jaime

+0

"टेस्ट" विधि सिर्फ एक उदाहरण है ... इसका उपयोग वास्तव में – Jaime

2

@parapura एक समाधान प्रदान की है, लेकिन यह स्पष्ट नहीं करता क्यों आप पहले वैश्विक दायरे में main घोषित करना होगा।

§7.3.1.2 [namespace.memdef] p3

[...] If a friend declaration in a nonlocal class first declares a class or function the friend class or function is a member of the innermost enclosing namespace. [...]

तो उस के साथ दिमाग में, अपने कोड कुछ इस तरह दिखेगा:

namespace MyNamespace 
{ // MyNamespace is the innermost enclosing namespace 
    // 'main' from the friend declaration is treated 
    // as if it was a member of 'MyNamespace' 
    int main(int argc, char** argv); 

    class ProcessManager 
    { 
    public: 
    friend int main(int argc, char** argv); 
    private: 
    void test(); 
    }; 
}; 

अब यह स्पष्ट किया जाना चाहिए क्यों वैश्विक main समारोह अपने दोस्त नहीं था।

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