2012-01-15 22 views
6

मेरे पास पॉलिमॉर्फिक कक्षाओं का पदानुक्रम है, Shape अमूर्त बेस क्लास को इसके व्युत्पन्न कक्षाओं के साथ एक साथ कहें, उदा। Rectangle, Circle, आदि Virtual Constructor Idiom के बाद, मैं सोच रहा था कि हमें क्यों चाहिए कि व्युत्पन्न कक्षाओं में वर्चुअल कन्स्ट्रक्टर फ़ंक्शंस के रिटर्न प्रकारों को स्मार्ट पॉइंटर्स का उपयोग करते समय अपने मूल वर्ग में उसी प्रकार की वापसी करनी चाहिए?
उदाहरण के लिए, नीचे दिए गए कोड को देखें, जहां clone() और create() सदस्य फ़ंक्शंस को smart_pointersShape कक्षा में वापस करने की आवश्यकता है। हालांकि, simple pointers का उपयोग करते समय, रिटर्न प्रकार व्युत्पन्न कक्षाओं में से एक के समान प्रकार के हो सकते हैं।
क्या कोई यह समझा सकता है कि हमें उन कार्यों को संदर्भित तरीके से क्यों संभालना है?स्मार्ट पॉइंटर्स के साथ आभासी कन्स्ट्रक्टर मुहावरे

class Shape; 

typedef std::unique_ptr<Shape> shape_ptr; 

class Shape{ 

    public: 

     //typedef std::unique_ptr<Shape> shape_ptr; 

     Shape(){}; 
     virtual ~Shape(){}; 

     virtual void draw() const = 0; 
     virtual float area() const = 0; 

     virtual shape_ptr clone() const = 0; 
     virtual shape_ptr create() const = 0; 
     //virtual Shape*clone() const = 0; 
     //virtual Shape*create() const = 0; 
}; 

class Rectangle:public Shape{ 
    public: 

     typedef std::unique_ptr<Rectangle> rectangle_SmartPtr; 

     Rectangle(int height=0, int width=0):m_Height(height),m_Width(width){}; 
     Rectangle(const Rectangle & rect):m_Height(rect.m_Height),m_Width(rect.m_Width){}; 
     ~Rectangle(){}; 

     virtual void draw() const; 
     virtual float area() const; 

     //virtual rectangle_SmartPtr clone() const{ return rectangle_SmartPtr(new Rectangle(*this)); }; 
     // error C2555: 'Rectangle::clone': overriding virtual function return type differs and is not covariant from 'Shape::clone' 
     //virtual rectangle_SmartPtr create() const{ return rectangle_SmartPtr(new Rectangle()); }; 
     // error C2555: 'Rectangle::create': overriding virtual function return type differs and is not covariant from 'Shape::create' 

     virtual shape_ptr clone() const{ return shape_ptr(new Rectangle(*this)); }; //OK 
     virtual shape_ptr create() const{ return shape_ptr(new Rectangle()); }; //OK 

     //virtual Rectangle* clone() const{ return new Rectangle(*this); }; //OK 
     //virtual Rectangle* create() const{ return new Rectangle(); }; //OK 

    private: 
     int m_Height; 
     int m_Width; 
}; 


class Circle:public Shape{ 
    public: 

     typedef std::unique_ptr<Circle> circle_SmartPtr; 

     Circle(float radius=0):m_Radius(radius){}; 
     Circle(const Circle & other):m_Radius(other.m_Radius){}; 
     ~Circle(){std::cout << "Circle destructor: " << this << std::endl; }; 

     virtual void draw() const; 
     virtual float area() const; 

     //virtual circle_SmartPtr clone() const{ return circle_SmartPtr(new Circle(*this)); }; 
     // error C2555: 'Circle::clone': overriding virtual function return type differs and is not covariant from 'Shape::clone' 
     //virtual circle_SmartPtr create() const{ return circle_SmartPtr(new Circle()); }; 
     // error C2555: 'Circle::create': overriding virtual function return type differs and is not covariant from 'Shape::create' 

     virtual shape_ptr clone() const{ return shape_ptr(new Circle(*this)); }; //OK 
     virtual shape_ptr create() const{ return shape_ptr(new Circle()); }; //OK 

     //virtual Circle* clone() const{ return new Circle(*this); }; //OK 
     //virtual Circle* create() const{ return new Circle(); }; //OK 

    private: 

     float m_Radius; 
}; 
+0

मुझे लगता है कि ऐसा इसलिए है क्योंकि unique_ptr और unique_ptr के बीच कोई अंतर्निहित रूपांतरण नहीं है, लेकिन मुझे यकीन नहीं है, क्योंकि मुझे लगता है कि आप C++ 11 का उपयोग कर रहे हैं, जिसे मैं परिचित नहीं हूं। –

उत्तर

6

कच्चे संकेत का उपयोग करते समय संकलक covariant वापसी प्रकार के लिए अनुमति देता है, लेकिन यह संभव है जब unique_ptr<Rectangle> के बाद से स्मार्ट संकेत का उपयोग कर unique_ptr<Shape> से निकाले जाते हैं नहीं है नहीं है। दो वर्ग संकलक के परिप्रेक्ष्य से पूरी तरह से असंबंधित हैं।

+0

"_since unique_ptr < Rectangle > अद्वितीय_ptr < Shape > _" अप्रासंगिक से प्राप्त नहीं होता है। यहां तक ​​कि अगर यह प्राप्त हुआ, तो सी ++ कॉन्वर्सिस में ओवरराइड फ़ंक्शन के रिटर्न प्रकार से प्राप्त कक्षा को वापस करने के लिए ओवरराइडिंग फ़ंक्शन को अनुमति नहीं दी जाती है। "_ दो वर्ग कंपाइलर के परिप्रेक्ष्य से पूरी तरह से असंबंधित हैं" बिल्कुल नहीं: "कंपाइलर के परिप्रेक्ष्य से", 'unique_ptr < Rectangle >' परिवर्तनीय 'unique_ptr < Shape >' में परिवर्तनीय है। – curiousguy

5

इसे कोविरिएन्स कहा जाता है।

एक वर्ग पदानुक्रम में, जब आधार वर्ग एक आभासी विधि है कि वापसी निर्दिष्ट करता है या तो एक T* या एक T&, तो व्युत्पन्न वर्ग में क्रमश: U* या U&, वापस जाने के लिए, उपलब्ध कराने कि UT (नोट से निकला अनुमति दी जाती है: और जाहिर है const और volatile संयोजन)।

यह एक विशेष नियम है, संकलक द्वारा जाँच की है, और यह काम करता है क्योंकि अगर UT से निकला तो एक U* एक T* लिए डाली जा सकती है। दुर्भाग्य से नियम सीमित है कि यह किसी भी रूपांतरण के लिए काम नहीं करता है, और इसलिए आप आमतौर पर unique_ptr<Rectangle> से बना सकते हैं ... कॉन्वर्सिस काम नहीं करता है।

यही कारण है कि, इसकी क्लोनेबल अवधारणा में, बूस्ट को नंगे सूचक प्रकार वापस करने के लिए जनादेश देता है। यह शर्म की बात है, लेकिन कॉन्वर्सिस पाने का एकमात्र तरीका है।

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