2011-11-29 8 views
6

के साथ कन्स्ट्रक्टर कॉपी करें मेरे पास क्लास सदस्य के रूप में एक std::unique_ptr वाला क्लास है। मैं सोच रहा था, कॉपी कन्स्ट्रक्टर को सही तरीके से परिभाषित करने के लिए, क्योंकि मुझे निम्न कंपाइलर त्रुटि संदेश मिल रहा है: error C2248: std::unique_ptr<_Ty>::unique_ptr : cannot access private member declared in class 'std::unique_ptr<_Ty>। मेरी कक्षा डिजाइन लग रहा है कि:स्मार्ट पॉइंटर

template <typename T> 
class Foo{ 
    public: 
     Foo(){}; 
     Foo(Bar<T> *, int); 
     Foo(const Foo<T> &); 
     ~Foo(){}; 

     void swap(Foo<T> &); 
     Foo<T> operator = (Foo<T>); 

    private: 
     std::unique_ptr<Bar> m_ptrBar; 
     int m_Param1; 

}; 

template < typename T > 
Foo<T>::Foo(const Foo<T> & refFoo) 
:m_ptrBar(refFoo.m_ptrBar), 
m_Param1(refFoo.m_Param1) 
{ 
    // error here! 
} 

template < typename T > 
void Foo<T>::swap(Foo<T> & refFoo){ 
    using std::swap; 
    swap(m_ptrBar, refFoo.m_ptrBar); 
    swap(m_Param1, refFoo.m_Param1); 
} 

template < typename T > 
Foo<T> Foo<T>::operator = (Foo<T> Elem){ 
    Elem.swap(*this); 
    return (*this); 
} 

उत्तर

5

लक्ष्य मान लिया जाये कि विशिष्ट स्वामित्व वाली बार कॉपी-निर्माण करने के लिए है,

template < typename T > 
Foo<T>::Foo(const Foo<T> & refFoo) 
: m_ptrBar(refFoo.m_ptrBar ? new Bar(*refFoo.m_ptrBar) : nullptr), 
    m_Param1(refFoo.m_Param1) 
{ 
} 
+0

@ कब्बी, धन्यवाद। अब मुझे एक और समस्या है। 'बार' वर्ग वास्तव में एक सार आधार वर्ग है, और इसलिए मुझे एक नया त्रुटि संदेश मिल रहा है: 'त्रुटि C2259:' बार ': अमूर्त वर्ग को तत्काल नहीं कर सकता है, क्या कोई समाधान है, सार सारणी वर्ग को बदलने के अलावा, एक साधारण आधार वर्ग? – Tin

+2

@ टिन: उस स्थिति में, आपको बेस क्लास में शुद्ध आभासी 'क्लोन() 'फ़ंक्शन जोड़ने की आवश्यकता होगी, प्रत्येक व्युत्पन्न कक्षा में ओवरराइड किया जाएगा ताकि' नया 'का उपयोग करके प्रतिलिपि बनाई जा सके। फिर प्रारंभकर्ता 'बार (foo.bar? Foo.bar-> क्लोन(): nullptr) बन जाता है। –

+0

@ टिन द सी ++ एफएक्यू ने कहा कि ["आभासी कन्स्ट्रक्टर"] (http://www.parashift.com/c++-faq-lite/virtual-functions.html#faq-20.8) – Cubbi

2

Unique_ptr प्रलेखन:

Stores a pointer to an owned object. The object is owned by no other unique_ptr. 
The object is destroyed when the unique_ptr is destroyed. 

आप नहीं कर सकते इसे कॉपी क्योंकि दो वस्तुओं का स्वामित्व नहीं हो सकता है।

एक std :: shared_ptr पर स्विच करने का प्रयास करें।

EDIT मुझे यह इंगित करना चाहिए कि इससे दोनों ऑब्जेक्ट्स को उसी ऑब्जेक्ट में पॉइंटर होगा। यदि आप विशिष्ट स्वामित्व वाली वस्तु को कॉपी करना चाहते हैं तो कबी का समाधान सही है।

+0

@ w00te, धन्यवाद। एक और प्रश्न। क्या होगा यदि बार वर्ग वास्तव में एक सार आधार वर्ग है? मुझे एक नया त्रुटि संदेश मिल रहा है: 'त्रुटि C2259:' बार ': अमूर्त वर्ग को तत्काल नहीं कर सकता है।क्या सार आधार वर्ग को एक साधारण आधार वर्ग में बदलने के अलावा कोई समाधान है? – Tin

+0

कब्बी का समाधान नई कक्षा में अद्वितीय_ptr के भीतर एक नया बार ऑब्जेक्ट बनाता है। यदि बार सार है तो वह काम नहीं कर सकता - इसे इसके बजाय लागू व्युत्पन्न वर्ग का एक नया ऑब्जेक्ट बनाना होगा। इसे प्राप्त करने के लिए आपको तर्क जोड़ना होगा। –

2

इस के लिए एक नया clone_ptr प्रकार बनाने की संभावना है।

नीचे clone_ptr का एक प्राथमिक उदाहरण है जो व्युत्पन्न वस्तु के सही प्रतिलिपि निर्माता (और विनाशक) को आमंत्रित करता है। clone_ptr बनाया गया है जब यह "टाइप एरर" सहायक बनाकर किया जाता है।

अन्य कार्यान्वयन इंटरनेट पर मिल सकते हैं।

#include <memory> 

namespace clone_ptr_detail 
{ 
template <class T> 
class clone_ptr_helper_base 
{ 
public: 
    virtual ~clone_ptr_helper_base() {} 
    virtual T* clone(const T* source) const = 0; 
    virtual void destroy(const T* p) const = 0; 
}; 

template <class T, class U> 
class clone_ptr_helper: public clone_ptr_helper_base<T> 
{ 
public: 
    virtual T* clone(const T* source) const 
    { 
     return new U(static_cast<const U&>(*source)); 
    } 
    virtual void destroy(const T* p) const 
    { 
     delete static_cast<const U*>(p); 
    } 
}; 
} 

template <class T> 
class clone_ptr 
{ 
    T* ptr; 
    std::shared_ptr<clone_ptr_detail::clone_ptr_helper_base<T>> ptr_helper; 
public: 
    template <class U> 
    explicit clone_ptr(U* p): ptr(p), ptr_helper(new clone_ptr_detail::clone_ptr_helper<T, U>()) {} 

    clone_ptr(const clone_ptr& other): ptr(other.ptr_helper->clone(other.ptr)), ptr_helper(other.ptr_helper) {} 

    clone_ptr& operator=(clone_ptr rhv) 
    { 
     swap(rhv); 
     return *this; 
    } 
    ~clone_ptr() 
    { 
     ptr_helper->destroy(ptr); 
    } 

    T* get() const { /*error checking here*/ return ptr; } 
    T& operator*() const { return *get(); } 
    T* operator->() const { return get(); } 

    void swap(clone_ptr& other) 
    { 
     std::swap(ptr, other.ptr); 
     ptr_helper.swap(other.ptr_helper); 
    } 
}; 

उपयोग उदाहरण देखें: http://ideone.com/LnWa3

(लेकिन शायद तुम सच में की जरूरत नहीं है प्रतिलिपि अपने वस्तुओं के लिए , और नहीं बल्कि इस कदम अर्थ विज्ञान की संभावनाओं का पता लगाने सकता है उदाहरण के लिए, यदि आप एक vector<unique_ptr<T>> हो सकता है। , जब तक आप सामग्री का प्रतिलिपि बनाने वाले फ़ंक्शंस का उपयोग नहीं करते हैं।)