ऑपरेटर ओवरलोडिंग: सदस्य फ़ंक्शन बनाम गैर-सदस्य फ़ंक्शन?


121

मैंने पढ़ा है कि सदस्य फ़ंक्शन के रूप में घोषित एक अतिभारित ऑपरेटर असममित है क्योंकि इसमें केवल एक पैरामीटर हो सकता है और अन्य पैरामीटर स्वचालित रूप से पास किया गया thisसूचक है। इसलिए उनकी तुलना करने के लिए कोई मानक मौजूद नहीं है। दूसरी ओर, अतिभारित ऑपरेटर को एक सममित घोषित किया friendजाता है क्योंकि हम एक ही प्रकार के दो तर्क पास करते हैं और इसलिए, उनकी तुलना की जा सकती है।

मेरा सवाल यह है कि जब मैं अभी भी एक सूचक के अंतराल की तुलना एक संदर्भ से कर सकता हूं, तो दोस्तों को क्यों पसंद किया जाता है? (एक असममित संस्करण का उपयोग करना सममित के समान परिणाम देता है) एसटीएल एल्गोरिदम केवल सममित संस्करणों का उपयोग क्यों करते हैं?


11
आपका प्रश्न वास्तव में केवल बाइनरी ऑपरेटरों के बारे में है। सभी ओवरलोडेड ऑपरेटर एक ही पैरामीटर तक सीमित नहीं हैं। () ऑपरेटर किसी भी संख्या में पैरामीटर ले सकता है। दूसरी ओर, यूनियनों के संचालकों के पास कोई पैरामीटर नहीं हो सकता है।
चार्ल्स साल्विया


जवाबों:


148

यदि आप अपने ऑपरेटर को फ़ंक्शन फ़ंक्शन के सदस्य फ़ंक्शन के रूप में परिभाषित करते हैं, तो कंपाइलर जैसे भावों का अनुवाद करता s1 + s2है s1.operator+(s2)इसका मतलब है, ऑपरेटर द्वारा ओवरलोड किए गए सदस्य फ़ंक्शन को पहले ऑपरेंड पर लागू किया जाता है। इस प्रकार सदस्य कार्य करता है!

लेकिन क्या होगा यदि पहला ऑपरेंड एक वर्ग नहीं है? एक बड़ी समस्या है अगर हम एक ऑपरेटर को ओवरलोड करना चाहते हैं जहां पहला ऑपरेंड एक क्लास प्रकार नहीं है, बल्कि कहें doubleतो आप इस तरह नहीं लिख सकते 10.0 + s2। हालाँकि, आप जैसे भावों के लिए ऑपरेटर अधिभार सदस्य फ़ंक्शन लिख सकते हैं s1 + 10.0

आदेश देने की इस समस्या को हल करने के लिए , हम ऑपरेटर को अधिभारित फ़ंक्शन को परिभाषित करते हैं क्योंकि friendIF को privateसदस्यों तक पहुंचने की आवश्यकता है । इसे friendतभी बनाएं जब इसे निजी सदस्यों तक पहुंचने की आवश्यकता हो। अन्यथा केवल एनकैप्सुलेशन में सुधार करने के लिए इसे गैर-मित्र गैर-सदस्यीय फ़ंक्शन करें !

class Sample
{
 public:
    Sample operator + (const Sample& op2); //works with s1 + s2
    Sample operator + (double op2); //works with s1 + 10.0

   //Make it `friend` only when it needs to access private members. 
   //Otherwise simply make it **non-friend non-member** function.
    friend Sample operator + (double op1, const Sample& op2); //works with 10.0 + s2
}

इन्हें पढ़ें:
ऑपरेंड्स में ऑर्डर करने की थोड़ी समस्या कि
कैसे नॉन-मेंबर फंक्शन्स इंप्रूवमेंट को बेहतर बनाते हैं


2
"इसे friendकेवल तभी करें जब इसे निजी सदस्यों तक पहुंचने की आवश्यकता
हो..और

4
@ आभा: अपनी पिक चुनें: बेहतर लेखन बनाम आलसी लेखन की आदत!
नवाज

6
@matthias, सभी ऑपरेटर सराहनीय नहीं हैं। सरल उदाहरण है a/b
edA-qa मोर्ट-ओरा-वाई

3
अपने गैर-सदस्य ऑपरेटरों को बनाने से बचने का एक सामान्य तरीका friendउन्हें संचालन-असाइनमेंट ऑपरेटरों (जो लगभग निश्चित रूप से सार्वजनिक सदस्य होंगे) के संदर्भ में लागू करना है। उदाहरण के लिए, आप T T::operator+=(const T &rhs)एक सदस्य के रूप में परिभाषित कर सकते हैं और फिर गैर-सदस्य के T operator(T lhs, const T &rhs)रूप में परिभाषित कर सकते हैं return lhs += rhs;। गैर-सदस्य फ़ंक्शन को क्लास के समान नामस्थान में परिभाषित किया जाना चाहिए।
एड्रियन मैक्कार्थी

2
@ricky: लेकिन अगर lhs एक कॉपी है (जैसा कि मेरी टिप्पणी में है), तो यह तथ्य कि lhs परिवर्तन कोई फर्क नहीं पड़ता।
एड्रियन मैक्कार्थी

20

यह आवश्यक रूप से friendऑपरेटर अधिभार और सदस्य फ़ंक्शन ऑपरेटर अधिभार के बीच अंतर नहीं है क्योंकि यह वैश्विक ऑपरेटर अधिभार और सदस्य फ़ंक्शन ऑपरेटर अधिभार के बीच है।

एक वैश्विक ऑपरेटर अधिभार को पसंद करने का एक कारण यह है कि यदि आप उन अभिव्यक्तियों को अनुमति देना चाहते हैं जहां एक बाइनरी ऑपरेटर के दाहिने हाथ की तरफ वर्ग प्रकार प्रकट होता है । उदाहरण के लिए:

Foo f = 100;
int x = 10;
cout << x + f;

यह तभी काम करता है जब इसके लिए कोई ग्लोबल ऑपरेटर ओवरलोड हो

फू ऑपरेटर + (int x, const Foo & f);

ध्यान दें कि वैश्विक ऑपरेटर अधिभार को एक friendफ़ंक्शन होने की आवश्यकता नहीं है । यह केवल तभी आवश्यक है जब इसे निजी सदस्यों तक पहुंच की आवश्यकता हो Foo, लेकिन यह हमेशा ऐसा नहीं होता है।

भले ही, यदि Fooकेवल एक सदस्य फ़ंक्शन ऑपरेटर अधिभार था, जैसे:

class Foo
{
  ...
  Foo operator + (int x);
  ...
};

... तो हम केवल वही भाव Fooरख पाएँगे जहाँ एक उदाहरण प्लस ऑपरेटर के बाईं ओर दिखाई देता है ।


3
सदस्य और मित्र कार्यों के बजाय सदस्य कार्यों और गैर-सदस्य कार्यों के बीच अंतर करने के लिए +1। मुझे लगता है कि आज हम कहेंगे "वैश्विक या नाम स्थान का दायरा।"
एड्रियन मैकार्थी
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.