2011-02-02 17 views
6

ठीक है, मैंने साझा-पॉइंटर्स का उपयोग करना शुरू किया और जितना संभव हो सके साझा पॉइंटर्स पास कर दिया। अब कच्चे पॉइंटर्स में कोई रूपांतरण नहीं है। यह अच्छा काम करता है, इस विशिष्ट मामले को छोड़कर:shared_ptr और यह पॉइंटर

मान लीजिए हम एक वर्ग भी अन्य वर्ग पर एक पर्यवेक्षक है कि, इस तरह है:

class MyClass : public IObserver 
    { 
    public: 
     MyClass (std::shared_ptr<SomeOtherClass> otherClass); 
     void DoSomethingImportant(); 
    private: 
     std::shared_ptr<SomeOtherClass> m_otherClass; 
    }; 

इस वर्ग के अपने आवेदन में इस तरह प्रयोग किया जाता है:

std::shared_ptr<MyClass> myInstance(new MyClass(otherInstance)); 
... 
myInstance->DoSomethingImportant(); 

MyClass को किसी अन्य वर्ग में साझा-पॉइंटर मिलता है और इसे अपने m_otherClass डेटा सदस्य में संग्रहीत करता है। DoSomethingImportant विधि में, MyClass उदाहरण m_otherClass पर स्वयं को एक पर्यवेक्षक के रूप में पंजीकृत करने सहित कई महत्वपूर्ण चीजें करता है, जैसे:

m_otherClass-> रजिस्टर ऑब्सर्वर (यह);

समस्या

कि registerObserver विधि इस तरह परिभाषित किया गया है है:

शून्य registerObserver (std :: shared_ptr पर्यवेक्षक);

यह एक साझा सूचक की अपेक्षा करता है, लेकिन 'यह' एक कच्चा सूचक है, साझा नहीं है।

मैं इस को हल करने के तीन तरीके देखें:

  • एक चाल एक साझा सूचक को एक सामान्य सूचक कन्वर्ट करने के लिए खोजें (देखें प्रश्न convert pointer to shared_ptr), लेकिन यह सवाल का जवाब केवल साझा-संकेत नकल करने के लिए सुझाव , पॉइंटर को साझा पॉइंटर में वास्तव में परिवर्तित करने के तरीके पर नहीं।
  • इस तरह के तरीके में साझा-पॉइंटर को पास करें, जैसे: "myInstance-> DoSomethingImportant (myInstance);" जो थोड़ा बेवकूफ लगता है।
  • पर्यवेक्षक भाग को एक अलग वर्ग में रखें। यह कुछ ओवरकिल की तरह दिखता है, और कक्षा को समझने में कठोर बना सकता है।

यह समस्या यह स्पष्ट करती है कि साझा-पॉइंटर्स केवल सी ++ के लिए एक ऐड-ऑन हैं (मुझे नहीं लगता कि आपको अन्य भाषाओं/वातावरण जैसे सी # (या सामान्य रूप से .NET) और जावा में एक ही समस्या है)।

इस स्थिति को संभालने के तरीके पर कोई अन्य सुझाव या युक्तियां?

+2

क्या आप 'enable_shared_from_this' का उपयोग नहीं कर सकते? (देखें [इस से एक बूस्ट साझा_पीआर प्राप्त करना] (http://stackoverflow.com/questions/142391/getting-a-boostshared-ptr-for-this)) –

+3

इस प्रश्न और सभी उत्तरों को किसने कम किया है? क्या यह वाकई इतना बेवकूफ सवाल है? – Patrick

+0

मुझे कभी-कभी आश्चर्य होता है ... अगर कुछ लोग बस बैज प्राप्त करने की कोशिश नहीं कर रहे हैं http://stackoverflow.com/badges/7/critic?userid=147192 –

उत्तर

8

आपको जो चाहिए वह शायद enable_shared_from_this और shared_from_this सुविधाएं है। दस्तावेज़ here

ध्यान दें कि आप shared_from_this का उपयोग नहीं कर सकते हैं जब तक कि कन्स्ट्रक्टर पूरी तरह से पूरा नहीं हो जाता है और ऑब्जेक्ट पहले से ही shared_ptr के स्वामित्व में है।

struct test : boost::enabled_shared_from_this<test> 
{ 
    test() { 
     // shared_from_this(this); // error, still not owned by another shared_ptr 
    } 
    boost::shared_ptr<test> shared() { 
     return shared_from_this(this); 
    } 
}; 
int main() { 
    test * t = new test; 
    // boost::shared_ptr<test> p = t->shared(); // error, not yet owned by other shared_ptr 
    boost::shared_ptr<test> owner(t); 
    boost::shared_ptr<test> p = t->shared();  // [*] ok, "owner" owns the object 
} 

[*] उदाहरण का यह हिस्सा मूर्खतापूर्ण है, आप विधि को कॉल करने के बजाय मालिक को पी में कॉपी कर सकते हैं।यह सिर्फ test विधियों के अंदर shared_from_this कहलाता है या नहीं कहने पर यह ध्यान दिया जाता है।

+0

यह वही है जो मैं ढूंढ रहा हूं। क्या सी ++ 0x shared_ptr के लिए कोई समान समाधान है? (मैं बूस्ट का उपयोग नहीं कर रहा, विजुअल स्टूडियो 2010 का उपयोग कर रहा हूं) क्या आपको स्मृति पदचिह्न पर असर पर कोई विचार है? क्या यह अपने लिए एक साझा पॉइंटर स्टोर करता है या यह कैसे काम करता है? – Patrick

+0

पाया गया, वास्तव में विजुअल स्टूडियो 2010 में एक enable_shared_from_this है। धन्यवाद। – Patrick

+0

बूस्ट और आगामी मानक पुस्तकालय काफी समान हैं, अगर बिल्कुल वही नहीं है। यह स्मार्ट पॉइंटर्स के लिए जाता है ('scoped_ptr' बूस्ट में मौजूद है, लेकिन मानक से गिरा दिया गया है), और थ्रेडिंग (ऑपरेशंस के अर्थशास्त्र पर कुछ विवरण मूल बूस्ट :: थ्रेड से बदल दिए गए थे ...) –

0

निर्माता निजी एक स्थिर निर्माण विधि इस तरह कर रही है और होने के बारे में कैसे:

class MyClass : public IObserver 
    { 
    public: 
     static std::shared_ptr<MyClass> createObserver(std::shared_ptr<SomeOtherClass> otherClass); 
     void DoSomethingImportant(); 
    private: 
     MyClass (std::shared_ptr<SomeOtherClass> otherClass); 
     std::shared_ptr<SomeOtherClass> m_otherClass; 
    }; 

तो फिर तुम स्थिर विधि में सफाई से पर्यवेक्षक का दृष्टांत सकता है और सब पर इस सूचक के बारे में चिंता करने की जरूरत नहीं।

+1

यह मानता है कि पर्यवेक्षक (वास्तव में: सभी पर्यवेक्षकों) को निर्माण समय पर जोड़ा जाना चाहिए (जो हमेशा नहीं चाहता था)। इसके अलावा टाइपो: शायद आप createObserver विधि स्थिर बनाने का इरादा रखते हैं। – Patrick

0


क्या आप पंजीकरण चरण को एक अलग विधि में ले जा सकते हैं? :

shared_ptr<SomeOtherClass> other(new SomeOtherClass()); 
shared_ptr<MyClass> my(new MyClass()); 
// register myself to the observer 
other->registerObserver(my); 
my->DoSomethingImportant(); 

पर्यवेक्षक पैटर्न का एक अच्छा डिजाइन को बढ़ावा देने :: संकेत के साथ लागू किया जा सकता है और बढ़ावा देने :: बाँध पुस्तकालयों। मैं आपको एक नज़र रखने के लिए प्रोत्साहित करता हूं।

शुभकामनाओं सहित,
मार्सिन

3

पर्यवेक्षक पैटर्न के लिए, मनाया वस्तु प्रेक्षक के मालिकाना हक नहीं ले करता है, यही कारण है कि सिर्फ एक कच्चे सूचक का उपयोग नहीं? पर्यवेक्षक का जीवन चक्र स्वयं पर्यवेक्षक द्वारा नियंत्रित किया जाना चाहिए।

enable_shared_from_this का उपयोग करके, आप पर्यवेक्षक और इसकी मनाई गई वस्तु के लिए चक्र निर्भरता पेश करते हैं। इसका मतलब है कि अगर स्पष्ट रूप से हटाया नहीं जाता है, तो संसाधन कभी जारी नहीं किया जाएगा।

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