c++ - प्रतिरूपण वेक्टर्स




C++ में क्लोन() के लिए सबसे अच्छा हस्ताक्षर क्या है? (6)

जैसा कि स्कॉट मायर्स ने लिखा था, आप एक प्रकार के संकेतक को घोषित करने के लिए क्लोन () को घोषित करने के लिए C ++ के प्रकार-प्रणाली में छूट का लाभ ले सकते हैं:

class Base
{
    virtual Base* clone() const = 0;
};

class Derived : public Base
{
    virtual Derived* clone() const
};

कंपाइलर का पता लगाता है कि क्लोन () ऑब्जेक्ट के प्रकार के लिए एक सूचक देता है, और प्राप्त करने के लिए इसे प्राप्त करने के लिए एक सूचक को वापस लाने के लिए अनुमति देता है।

यह क्लोन () करने के लिए एक स्मार्ट पॉइंटर वापस आना चाहता है जिसका मतलब है कि स्वामित्व सिमेंटिक का स्थानांतरण, जैसे निम्नलिखित:

class Base
{
   virtual std::auto_ptr<Base> clone() const = 0;
};

class Derived : public Base
{
    virtual std::auto_ptr<Derived> clone() const;
};

दुर्भाग्य से, सम्मेलनों में छूट templated स्मार्ट पॉइंटर्स पर लागू नहीं होती है, और संकलक ओवरराइड की अनुमति नहीं देगा।

तो, ऐसा लगता है कि मैं दो विकल्पों के साथ रह गया हूं:

  1. क्लोन () एक "गूंगा" सूचक, और दस्तावेज लौटाते हैं कि ग्राहक इसका निपटान करने के लिए जिम्मेदार हैं।
  2. क्लोन () एक स्मार्ट बेस पॉइंटर को वापस लाएं, और ग्राहकों को गतिशील_कास्ट का उपयोग करने के लिए उन्हें एक व्युत्पन्न पॉइंटर से बचाने के लिए उपयोग करें,

क्या इनमें से एक दृष्टिकोण पसंदीदा है? या क्या मेरे लिए स्वामित्व शब्दार्थों का मेरा स्थानान्तरण करना और मेरा मजबूत प्रकार सुरक्षा भी है?


आपके पास दो तरीके हो सकते हैं, आभासी क्लोन () जो आधार प्रकार के चारों ओर एक स्मार्ट पॉइंटर आवरण देता है, और एक गैर-आभासी क्लोन 2 () जो सही प्रकार के स्मार्ट पॉइंटर को देता है

क्लोन 2 स्पष्ट रूप से क्लोन के अनुसार कार्यान्वित किया जाएगा और कलाकारों को समझाया जाएगा।

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

एक और विकल्प क्लोन का टेम्पलेट वर्जन तैयार करना होगा जो आपके द्वारा अपेक्षित प्रकार को स्वीकार करता है, लेकिन यह कॉलर पर अधिक बोझ डालता है।


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


यह एक कारण है कि auto/unique_ptr या auto/unique_ptr बजाय boost::intrusive_ptr का shared_ptr कच्चे पॉइंटर में संदर्भ गणना होती है और इस तरह की परिस्थितियों में अधिक सहज उपयोग किया जा सकता है।


वाक्यविन्यास काफी अच्छा नहीं है, लेकिन यदि आप इसे अपने ऊपर कोड में जोड़ते हैं, तो क्या यह आपकी सभी समस्याओं का समाधान नहीं करता है?

template <typename T>
std::auto_ptr<T> clone(T const* t)
{
    return t->clone();
}

Tr1::shared_ptr<> को Tr1::shared_ptr<> किया जा सकता है क्योंकि यह एक कच्चे पॉइंटर है

मुझे लगता है कि क्लोन () एक shared_ptr<Base> पॉइंटर वापस एक बहुत साफ समाधान है यदि आप tr1::static_pointer_cast<Derived> समय पर क्लोन ऑब्जेक्ट की तरह निर्धारित करने के लिए संभव नहीं है, तो आप tr1::static_pointer_cast<Derived> या tr1::dynamic_pointer_cast<Derived> माध्यम से tr1::static_pointer_cast<Derived> को संकेतक डाल सकते हैं।

यह सुनिश्चित करने के लिए कि वस्तु का प्रकार अनुमान लगाया जा सकता है, आप इसे साझा किए गए एक साझा आईपीटीआर के लिए एक बहुरूपृत कलाकार का उपयोग कर सकते हैं:

template <typename R, typename T>
inline std::tr1::shared_ptr<R> polymorphic_pointer_downcast(T &p)
{
    assert( std::tr1::dynamic_pointer_cast<R>(p) );
    return std::tr1::static_pointer_cast<R>(p);
}

ज़िम्मेदारी से जोड़ा गया ओवरहेड रिलीज़ संस्करण में फेंक दिया जाएगा।


सी ++ 14 के लिए मास्टोलट्स को अपडेट करना:

#include <memory>

class Base
{
public:
    std::unique_ptr<Base> clone() const
    {
        return do_clone();
    }
private:
    virtual std::unique_ptr<Base> do_clone() const
    {
        return std::make_unique<Base>(*this);
    }
};

class Derived : public Base
{
private:
    virtual std::unique_ptr<Base> do_clone() const override
    {
        return std::make_unique<Derived>(*this);
    }
}




covariant-return-types