2011-06-10 19 views
11

क्या अग्रेषित घोषित वर्ग के सदस्य फ़ंक्शन को दोस्त के रूप में घोषित करना संभव है? मैं निम्न कार्य करने की कोशिश कर रहा हूँ:एक अग्रेषित घोषित वर्ग के सदस्य-फ़ंक्शन को मित्र के रूप में घोषित करें

class BigComplicatedClass; 

class Storage { 
    int data_; 
public: 
    int data() { return data_; } 
    // OK, but provides too broad access: 
    friend class BigComplicatedClass; 
    // ERROR "invalid use of incomplete type": 
    friend void BigComplicatedClass::ModifyStorage(); 
}; 

तो लक्ष्य के लिए (i) एक एकल विधि के लिए दोस्त घोषणा प्रतिबंधित है, और (ii) जटिल वर्ग की परिभाषा शामिल करने के लिए समय संकलन कम करने के लिए नहीं।

एक दृष्टिकोण एक मध्यस्थ के रूप में एक वर्ग अभिनय जोड़ने के लिए हो सकता है:

// In Storage.h: 
class BigComplicatedClass_Helper; 
class Storage { 
    // (...) 
    friend class BigComplicatedClass_Helper; 
}; 

// In BigComplicatedClass.h: 
class BigComplicatedClass_Helper { 
    static int &AccessData(Storage &storage) { return storage.data_; } 
    friend void BigComplicatedClass::ModifyStorage(); 
}; 

बहरहाल, यह थोड़ा अनाड़ी लगता है ... इसलिए मुझे लगता है कि वहाँ एक बेहतर समाधान किया जाना चाहिए!

+0

संभावित डुप्लिकेट [कैसे एक दोस्त को घोषित करने के लिए जो सी ++ में किसी अन्य परिभाषित वर्ग का सदस्य फ़ंक्शन नहीं है?] (Http://stackoverflow.com/questions/ 4355660/कैसे-से-घोषणा-एक-दोस्त-वह-सदस्य-कार्य-एक-अभी-अभी-परिभाषित-क्लैस नहीं है) –

+0

संदर्भ के लिए धन्यवाद - मैंने यह प्रश्न देखा; हालांकि इसका स्वीकार्य उत्तर बहुत व्यापक वर्ग-स्तर का उपयोग है जिसे मैं टालना चाहता था ... – hrr

उत्तर

11

जैसा कि @ बेन कहते हैं, यह संभव नहीं है, लेकिन आप "passkey" के माध्यम से उस सदस्य फ़ंक्शन के लिए विशिष्ट पहुंच दे सकते हैं। स्पष्ट यह मध्यवर्ती सहायक वर्ग की तरह एक सा काम करता है, लेकिन imho है:

// Storage.h 
// forward declare the passkey 
class StorageDataKey; 

class Storage { 
    int data_; 
public: 
    int data() { return data_; } 
    // only functions that can pass the key to this function have access 
    // and get the data as a reference 
    int& data(StorageDataKey const&){ return data_; } 
}; 

// BigComplicatedClass.cpp 
#include "BigComplicatedClass.h" 
#include "Storage.h" 

// define the passkey 
class StorageDataKey{ 
    StorageDataKey(){} // default ctor private 
    StorageDataKey(const StorageDataKey&){} // copy ctor private 

    // grant access to one method 
    friend void BigComplicatedClass::ModifyStorage(); 
}; 

void BigComplicatedClass::ModifyStorage(){ 
    int& data = storage_.data(StorageDataKey()); 
    // ... 
} 
+0

अच्छा! माना जाता है कि मुझे यह समझने में थोड़ी देर लग गई कि कॉपी-कन्स्ट्रक्टर को निजी क्यों होना चाहिए ... – hrr

+0

@hrr: ठीक है, ऐसा नहीं होना चाहिए, क्योंकि आप अभी भी संदर्भ के रूप में कुंजी को पास कर सकते हैं यदि आप चाहते हैं। – Xeo

+0

यदि प्रति-निर्माता सार्वजनिक थे, तो अप्रतिबंधित उपयोगकर्ताओं को बहुत आसानी से कुंजी मिल सकती थी: 'StorageDataKey * key_ptr = 0; स्टोरेजडाटाकी कुंजी (* key_ptr); इस प्रकार प्रतिलिपि बनाने वाले निजी को बहुत समझदारी मिलती है। – hrr

3

नहीं, आप व्यक्तिगत सदस्य कार्यों को घोषित किए जाने तक मित्रों के रूप में घोषित नहीं कर सकते हैं। आप केवल पूरी कक्षा से मित्रता कर सकते हैं।

0

क्या अग्रेषित घोषित वर्ग के सदस्य समारोह को दोस्त के रूप में घोषित करना संभव है?

नहीं। बेशक, कंपाइलर को ऐसे सदस्य कार्यों का कोई ज्ञान नहीं है।

2

यह कर सकते हैं या यहां प्रासंगिक नहीं हो सकता है, लेकिन यह अपने आप को याद दिलाने के लिए कक्षाओं के दायरे से परे एक जंगली दुनिया है कि वहाँ उपयोगी है और ऑब्जेक्ट्स जहां फ़ंक्शंस घूम सकते हैं।

उदाहरण के लिए, मुझे हाल ही में किसी अन्य कोड के बंदरगाह के आधार पर वैश्विक अपवाद हैंडलर से एक (सिंगलटन वैश्विक स्थैतिक) सिस्टम त्रुटि लॉग बंद करने की आवश्यकता है। सामान्य रूप से अपवाद हैंडलर कोड से विवादित मेरे त्रुटि लॉग के लिए फ़ाइल शामिल है क्योंकि दोनों कारणों से "windows.h" शामिल करना चाहते थे जिनके कारण मैंने नहीं देखा था।

void WriteUrgentMessageToErrorLog(const char * message) 
{ 
    ErrorLog::LogSimpleMessage(message); 
    ErrorLog::FlushAccumulatedMessagesToDisk(); 
} 

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

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