2010-12-19 14 views
5

मेरा वर्तमान असाइनमेंट इटरेटर के साथ एक सूची लिख रहा है। यह सूची एक समस्या नहीं है क्योंकि इटरेटर वर्ग बनाना है।अर्थात् सूची में ऑपरेटर (और सामान्य सी ++ में)

कुछ स्रोतों से मैंने देखा है कि मेरे दो ऑपरेटर मेरे इटरेटर वर्ग में परिभाषित करने के लिए हैं: operator* और operator->

अब तक बहुत बढ़िया! मेरी इटरेटर संरचना मान तो

// Nested class of List 
class _Iter 
{ 
private: 
    ListElem *pCurr; 
    const List *pList; 

public: 
    _Iter(ListElem *pCurr, const List *list) 
     : pCurr_(pCurr), pList(list) 
    {} 

    T& operator*() { return pCurr_->data; } 
    T* operator->() { return &**this; } 
}; 

ListElem जा रहा है

// Nested struct of List 
struct ListElem 
{ 
    T data; 

    ListElem *next; 
    ListElem *prev; 
}; 

साथ है मैं देख सकता हूँ मैं कुछ बड़े पैमाने पर गलत कर रहा हूँ (इस के दोहरे dereferencing के रूप में एक & (* pCurr _-> डेटा तक ले जाएगा), जो dereferencable नहीं है।

मेरी मुख्य समस्या यह समझ में नहीं आ रही है कि -> वास्तव में इस मामले में क्या करना चाहिए। क्या इसे उपयोगकर्ता को ListElem कक्षा तक पहुंच प्रदान करनी चाहिए? यदि ऐसा है, तो मैं क्यों नहीं कर सकता बस

लिखें
ListElem *operator->() { return pCurr_; } 

एक सूचक वापस करने के बजाय?

operator*() // Return data pointed to by iterator; pCurr_->data; 
operator->() // Grant access to data-holding structure; pCurr; 

यह सही है, या मैं क्या नहीं मिल रहा है: के रूप में मेरी सूची (और उम्मीद है कि एसटीएल सूचियों) में इस्तेमाल इन दोनों ऑपरेटरों की मेरी समझ है? (और -> का उचित नाम है?)

उत्तर

5

जो कुछ भी आप करते हैं, (*something).somethingElsesomething->somethingElse के बराबर होना चाहिए। उत्तरार्द्ध पूर्व के लिए सिर्फ एक छोटा वाक्यविन्यास है। इसलिए,

T& operator*() { return pCurr_->data; } 
T* operator->() { return &**this; } 

ठीक क्योंकि *this सिर्फ this किस प्रकार _Iter*, नहीं _Iter, इसलिए कोई operator*() कॉल किया जाता है है dereferences है।फिर आप *this को अस्वीकार करते हैं, इसलिए आपको pCurr->data मिलता है, तो आप उसका पता लेते हैं, इसलिए आपको & pCurr-> डेटा मिलता है। लेकिन यह अधिक स्पष्ट होगा सिर्फ लिखने के लिए:

T& operator*() { return pCurr_->data; } 
T* operator->() { return &pCurr->data; } 

अब, यह

ListElem *operator->() { return pCurr_; } 

गलत है अगर operator*() रिटर्न T&, operator->()T* लौटना चाहिए, कि क्या इसके लिए डिजाइन किया गया था क्योंकि। यदि आप वास्तव में अपने डेटा के बजाय ListItem तक पहुंच देना चाहते हैं (जो डिज़ाइन के आधार पर समझ में आ सकता है या नहीं, लेकिन आपके मामले में ऐसा लगता है कि यह नहीं करता है), तो आपको यह प्राप्त करने के लिए operator*() को फिर से परिभाषित करना चाहिए:

ListElem& operator*() { return *pCurr_; } 
ListElem *operator->() { return pCurr_; } 

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

+0

दरअसल, मैं अक्सर भूल जाता हूं कि 'यह वास्तव में एक सूचक है। बहुत परेशान: डी – IAE

1

operator-> इस मामले में (स्पष्ट रूप से) pCurr_->data में ऑटरेटर द्वारा इंगित ऑब्जेक्ट को पॉइंटर देता है।

T *operator->() { return &(pCurr_->data); } 

यह वस्तु एक मूल्य या संदर्भ के रूप में operator*() द्वारा वापस की पता लौटना चाहिए।

T &operator*() { return pCurr_->data; } 
// or 
T &operator*() { return *operator->(); } 

operator->() iterators साथ -> लागू करने के लिए और आवश्यक है, क्योंकि operator* मूल्य के बजाय संदर्भ द्वारा एक वस्तु वापस आ सकते हैं (व्यवहार यह संकेत के लिए है) के साथ मौजूद है।

ध्यान दें कि आपको आवश्यक कार्यक्षमता प्राप्त करने के लिए इटरेटर में List पर पॉइंटर स्टोर करने की आवश्यकता नहीं है।

+1

मैंने संरचना प्रश्न सूची के साथ अपना प्रश्न अपडेट किया है। और aaaah, फू को एक सूचक प्रदान करके हम अब सभी Foos विधियों का उपयोग कर सकते हैं! तो मैं ListElem खुद को वापस नहीं कर रहा हूं, लेकिन उपयोगकर्ता को Foo डेटा सदस्य की कार्यक्षमता को पारित कर रहा हूं! यह समझ आता है। – IAE

+0

@SoulBeaver: मेरा उत्तर अपडेट किया गया। –

+0

हाँ, आप ग्राहक के उपयोग के लिए अंतर्निहित डेटा आइटम वापस कर रहे हैं। याद रखें कि इटेटरेटर पॉइंटर्स का एक सामान्यीकरण हैं और इसी प्रकार डेटा आइटम को इंगित करते हैं (कभी-कभी बहुत अप्रत्यक्ष रूप से; मैंने अभी एक इटरेटर तैयार किया है जो पॉलीमॉर्फिक ऑब्जेक्ट्स के पॉइंटर्स रखता है जो बदले में विभिन्न प्रकार के इटरेटर रखता है)। –

1

आपका मुख्य दिशानिर्देश होना चाहिए कि

(*iter).hello(); 
iter->hello(); 

दोनों एक ही बात करना चाहिए। उपयोगकर्ता यही उम्मीद करता है। रिटर्निंग ListElem उपयोगकर्ता को कुछ भी नहीं देता है। उपयोगकर्ता को ListElem के कार्यान्वयन के विवरण भी नहीं जानना चाहिए।

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