2011-02-04 19 views
17

यहाँ मेरी कोड उदाहरण है:ओवरलोडिंग ऑपरेटर>

class X 
{ 
public: 
     void f() {} 
}; 

class Y : public X 
{ 
public: 
     X& operator->() { return *this; } 
     void f() {} 
}; 

int main() 
{ 
     Y t; 
     t.operator->().f(); // OK 
     t->f(); // error C2819: type 'X' does not have an overloaded member 'operator ->' 
       // error C2232: '->Y::f' : left operand has 'class' type, use '.' 
} 

क्यों संकलक एक्स वाई से ऑपरेटर> के लिए "जिम्मेदारी ले जाएँ" करने की कोशिश कर रहा है? जब मैं एक्स :: ओप-> को कार्यान्वित करता हूं तो मैं एक्स को वापस नहीं कर सकता - संकलन त्रुटि कहता है कि "अनंत रिकर्सन" कहता है कि एक्स :: ओप-> से कुछ ज़ेड लौटने पर फिर से कहते हैं कि ज़ेड में ऑपरेटर नहीं है->, इस प्रकार उच्च हो रहा है और पदानुक्रम में उच्च।

क्या कोई इस दिलचस्प व्यवहार को समझा सकता है? :)

उत्तर

18

समस्या यह है कि operator -> एक सूचक वापस जाने के लिए माना जाता है, न कि एक संदर्भ। विचार यह है कि operator -> को वास्तविक ऑब्जेक्ट पर पॉइंटर वापस करना चाहिए जिसमें पॉइंटर को लागू होना चाहिए। उदाहरण के लिए, एक ओवरलोड operator -> साथ एक वर्ग है, कोड

(myClass.operator->())->myValue; 

अपने कोड के साथ समस्या यह है कि operator -> एक संदर्भ देता है, तो

myClass.operator->().f(); 

लेखन है में

myClass->myValue; 

तब्दील हो के लिए पूरी तरह से कानूनी है क्योंकि आप स्पष्ट रूप से ऑपरेटर का आह्वान कर रहे हैं, लेकिन

लिख रहे हैं क्योंकि संकलक

myClass.operator->()->f(); 

को विस्तृत करने के लिए कोशिश कर रहा है और operator-> की वापसी प्रकार एक सूचक नहीं है

myClass->f(); 

, गैर कानूनी है।

इसे ठीक करने के लिए, अपना कोड बदलें ताकि आप operator -> में एक पॉइंटर वापस कर सकें। यदि आप एक संदर्भ वापस करने के लिए ऑपरेटर को अधिभारित करना चाहते हैं, तो operator * ओवरलोड करें; पॉइंटर अवधारणाओं को वास्तव में संदर्भ प्रस्तुत करना चाहिए।

+9

मैं सिर्फ इतना है कि जो कुछ भी यह की जरूरत है देता है समर्थन करने के लिए यह नहीं कहूंगा कि यह एक सूचक वापस जाने के लिए लगता है है, 'ऑपरेटर>'। – GManNickG

+1

@ जीएमएन- अच्छा बिंदु। मैं यहां सादगी के लिए जा रहा था, लेकिन आप सही हैं। कुछ वाकई मजेदार चाल हैं जो आप स्मार्ट पॉइंटर्स के साथ खींच सकते हैं जो इस तकनीक पर भरोसा करते हैं। – templatetypedef

+0

@GMan: चूंकि इस तरह के प्रकार सामूहिक रूप से * स्मार्ट पॉइंटर्स * कहा जाता है, मुझे नहीं लगता कि templatetypedef शब्द * सूचक * शब्द का उपयोग करने में गलत है, वह बस इसे सामान्य अर्थ में उपयोग कर रहा है। –

2

वाक्य रचना गलत है, होना चाहिए:

टी> टी 2

T2* T::operator ->();​ 

विकिपीडिया के लेख पर देखो: Operators in C and C++

आप ओवरलोड करना चाहते हैं, तो आप का उपयोग करना चाहिए ओवरलोडेड ऑपरेटर के लिए सही वाक्यविन्यास

19

क्योंकि यह कैसे ओवरलो है विज्ञापन -> सी ++ में काम करता है।

जब आप अधिभारित -> का उपयोग करते हैं, अभिव्यक्ति a->b का अनुवाद a.operator->()->b में किया गया है। इसका मतलब है कि आपके अधिभारित ऑपरेटर -> को कुछ ऐसा वापस करना होगा जो ऑपरेटर -> के दूसरे एप्लिकेशन का समर्थन करेगा। इस कारण से अधिभारित -> ओवरलोडेड -> एस के आविष्कार की एक लंबी श्रृंखला में बदल सकता है जब तक कि यह अंततः निर्मित -> के अनुप्रयोग तक पहुंच जाता है, जो श्रृंखला को समाप्त करता है।

अपने मामले में आपको को अपने अधिभारित -> से X& पर वापस करने की आवश्यकता है।

1

आप शायद चाहते हैं:

class Y : public X 
{ 
public: 
     X* operator->() { return this; } 
     void f() {} 
}; 
संबंधित मुद्दे