2010-04-22 14 views
19
using namespace boost; 

class A {}; 
class B : public A {}; 

class X { 
    virtual shared_ptr<A> foo(); 
}; 

class Y : public X { 
    virtual shared_ptr<B> foo(); 
}; 

रिटर्न प्रकार कॉन्वर्सेंट नहीं हैं (न ही वे कानूनी हैं), लेकिन वे होंगे यदि मैं इसके बजाय कच्चे पॉइंटर्स का उपयोग कर रहा था। यदि कोई है तो इसके आसपास काम करने के लिए आम तौर पर स्वीकार्य मुहावरे क्या है?एक साझा_ptr लौटने पर कॉन्वेंट रिटर्न प्रकार कैसे पूरा करें?

+1

http://stackoverflow.com/questions/196733/how-can-i-use-covariant-return-types-with-smart-pointers –

उत्तर

11

मुझे लगता है कि एक समाधान मौलिक रूप से असंभव है क्योंकि कॉन्वर्सिस पॉइंटर अंकगणित पर निर्भर करता है जो स्मार्ट पॉइंटर्स के साथ असंगत है।

जब Y::foo एक गतिशील फोन करने वाले को shared_ptr<B> देता है, यह उपयोग करने से पहले shared_ptr<A> लिए डाली जानी चाहिए। आपके मामले में, B* (शायद) को A* के रूप में पुनः परिभाषित किया जा सकता है, लेकिन एकाधिक विरासत के लिए, आपको C12+ को static_cast<A*>(shared_ptr<B>::get()) के बारे में बताने के लिए कुछ जादू की आवश्यकता होगी।

+0

हम्म के संभावित डुप्लिकेट, "मूल रूप से" कॉन्वर्सिस रूपांतरण पर निर्भर करता है, और शायद निहित रूप से परिवर्तनीय प्रकार के साथ काम करना चाहिए। लेकिन वह अभी भी 'shared_ptr' पर लागू नहीं होगा। – Potatoswatter

+0

"_But अभी भी 'shared_ptr'_' पर लागू नहीं होगा" मुझे यह नहीं मिला: क्या 'shared_ptr' परिवर्तनीय नहीं है? – curiousguy

+0

@curiousguy ओह, ओह, यह है। हालांकि अभी भी एक काल्पनिक है। – Potatoswatter

4

सीधे नहीं, लेकिन आप वास्तविक वर्चुअल फ़ंक्शंस को कक्षा के बाहर से पहुंचने और वर्चुअल फ़ंक्शन कॉल को गैर-वर्चुअल फ़ंक्शन में लपेटकर नकली बना सकते हैं। नकारात्मकता यह है कि आपको प्रत्येक व्युत्पन्न वर्ग पर इस रैपर फ़ंक्शन को लागू करना याद रखना होगा। लेकिन आप वर्चुअल फ़ंक्शन घोषणा और मैक्रो में रैपर दोनों डालकर इसे प्राप्त कर सकते हैं।

using namespace boost; // for shared_ptr, make_shared and static_pointer_cast. 

// "Fake" implementation of the clone() function. 
#define CLONE(MyType) \ 
    shared_ptr<MyType> clone() \ 
    { \ 
     shared_ptr<Base> res = clone_impl(); \ 
     assert(dynamic_cast<MyType*>(res.get()) != 0); \ 
     return static_pointer_cast<MyType>(res); \ 
    } 

class Base 
{ 
protected: 
    // The actual implementation of the clone() function. 
    virtual shared_ptr<Base> clone_impl() { return make_shared<Base>(*this); } 

public: 
    // non-virtual shared_ptr<Base> clone(); 
    CLONE(Base) 
}; 

class Derived : public Base 
{ 
protected: 
    virtual shared_ptr<Base> clone_impl() { return make_shared<Derived>(*this); } 

public: 
    // non-virtual shared_ptr<Derived> clone(); 
    CLONE(Derived) 
}; 


int main() 
{ 
    shared_ptr<Derived> p = make_shared<Derived>(); 
    shared_ptr<Derived> clone = p->clone(); 

    return 0; 
} 
+0

यह थोड़ी देर हो गया है क्योंकि इसका उत्तर दिया गया था। अब सी ++ 11 बाहर है, क्या कोई बेहतर तरीका है? –

+0

@CoryBeutler। नहीं, अगर आप shared_ptr का उपयोग करना चाहते हैं। यदि आप shared_ptr को छोड़ने के इच्छुक हैं और घुसपैठ संदर्भ गणना का उपयोग करने के इच्छुक हैं, तो हां। इस मामले में फ़ंक्शन कच्चे पॉइंटर्स लौटाएंगे और स्वचालित रीफ्रैंटिंग प्राप्त करने के लिए आपको केवल एक स्मार्ट पॉइंटर (जैसे boost :: intrusive_ptr) को परिणाम असाइन करने की आवश्यकता होगी। – lego

-1

मैं सिर्फ एक नंगे सूचक लौटाता हूं और इसे तुरंत साझा सूचक में लपेटता हूं।

+0

आप लगभग किसी और के बेयर पॉइंटर को shared_ptr पर लपेटना नहीं चाहते हैं। – ShitalShah

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