2010-03-07 16 views
7

मैं एक ग्राफिक्स एप्लिकेशन पर काम कर रहा हूं जो वर्चुअल कक्षाओं का काफी व्यापक रूप से उपयोग कर रहा है। इसमें है:शुद्ध वर्चुअल क्लास और संग्रह (वेक्टर?)

  • एक चित्र वर्ग, जो अनिवार्य रूप से आकृतियों का संग्रह है।

  • एक आकार वर्ग है, जो विशुद्ध रूप से आभासी है और कुछ वर्गों है कि यह से विरासत है:

    • सर्किल
    • बहुभुज
    • आयत
  • एक चित्रा आकार है, जो कोई ग्राफिकल आकृति (वर्चुअल) है, इस से आकार प्राप्त होता है।

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

नीचे मेरे वर्तमान कोड (थोड़ा संक्षेप) का आधार है:

picture.cpp:33: instantiated from here /opt/local/bin/../lib/gcc/sparc-sun-solaris2.10/4.4.1/../../../../include/c++/4.4.1/ext/new_allocator.h:105: error: cannot allocate an object of abstract type 'Shape' shape.h:12: note: because the following virtual functions are pure within 'Shape': shape.h:58: note: virtual void Shape::get(std::istream&) shape.h:31: note: virtual void Shape::put(std::ostream&) const shape.h:36: note: virtual void Shape::scale(const Point&, double) shape.h:40: note: virtual void Shape::translate(double, double) shape.h:45: note: virtual void Shape::reflectHorizontally(double) shape.h:49: note: virtual void Shape::reflectVertically(double) shape.h:52: note: virtual RectangularArea Shape::boundingBox() const shape.h:21: note: virtual Shape* Shape::clone() const shape.h:55: note: virtual void Shape::draw(Graphics&) const

तो आदर्श तरीका क्या है: मैं हो रही है

class Figure { 
public: 
... 
    virtual ~Figure(); 
... 
}; 

class Shape: public Figure 
{ 
public: 
... 
    virtual ~Shape() {} 
    virtual Shape* clone() const = 0; 
... 
}; 

class Polygon : public Shape 
{ 
public: 
... 
virtual Shape* clone() const {return new Polygon(*this);} 
... 
private: 
std::vector<Point> points; 

}; 

class Picture: public Figure { 
public: 
... 
    Picture(Graphics& gd); 
    Picture (const Picture&); 
    ~Picture(); 
    void clear(); 
    void add (const Shape&); 
... 
private: 
std::vector<Shape> shapes; 
Graphics* gfx; 
}; 

//Picture implementation: 
... 
Picture::Picture(Graphics& gd) 
{ 
gfx = &gd; 
} 


Picture::Picture(const Picture& a) 
{ 
shapes = a.shapes; 
} 

Picture::~Picture() 
{ 
clear(); 
} 

void Picture::clear() 
{ 
shapes.clear(); 
} 

void Picture::add (const Shape& shp) 
{ 
Shape* nshp = shp.clone(); 
shapes.push_back(*nshp); 
} 
... 

त्रुटि संदेश अभी इनमें से एक गुच्छा रहे हैं इन आकृतियों को स्टोर करने के लिए। इन चीजों को स्टोर करने के लिए मुझे किस प्रकार का संग्रह उपयोग करना चाहिए?

धन्यवाद

उत्तर

14

जब आप बहुरूपता की जरूरत है, आप या तो संकेत या संदर्भ का उपयोग करने की जरूरत है। चूंकि कंटेनर (या सरणी) संदर्भों को संग्रहीत नहीं कर सकते हैं, इसलिए आपको पॉइंटर्स का उपयोग करना होगा।

अनिवार्य रूप से करने के लिए अपनी तस्वीर वर्ग के वेक्टर बदलने के लिए:

std::vector<Shape*> 

और उचित रूप से अन्य सदस्य कार्यों को संशोधित।

कारण आप उन्हें मूल्य प्रकार के रूप में स्टोर नहीं कर सकते हैं क्योंकि वेक्टर एक समरूप कंटेनर है यानी यह केवल एक प्रकार का डेटा संग्रहीत करता है (और केवल एक प्रकार - सबक्लास की अनुमति नहीं है!) । इसका कारण यह है कि वेक्टर अपने डेटा को एक सरणी में संग्रहीत करता है, जिसे इसे संग्रहीत वस्तुओं के आकार को जानने की आवश्यकता होती है। यदि इन वस्तुओं के आकार अलग हैं (जो वे विभिन्न आकारों के लिए हो सकते हैं) तो यह उन्हें एक सरणी में संग्रहीत नहीं कर सकता है।

यदि आप उन्हें पॉइंटर्स के रूप में स्टोर करते हैं तो उनके पास एक ही आकार (sizeof(Shape*)) होता है और आकार के vtable तक पहुंच भी होती है, जो पॉलिमॉर्फिक व्यवहार की अनुमति देता है।

+3

सी ++ 0x सुविधाओं के साथ बेहतर स्मार्ट पॉइंटर्स और सेमेन्टिक्स को स्थानांतरित करने के साथ, कोई भी इसका स्मृति-सुरक्षित संस्करण भी बना सकता है ('वेक्टर >')। – bobbymcr

+0

यदि आप स्मार्ट पॉइंटर्स का उपयोग नहीं करते हैं, तो याद रखें कि कंटेनर स्वचालित रूप से पॉइंट-टू डेटा को साफ़ नहीं करेगा। यह पॉइंटर्स पर विनाशकों को बुलाता है - लेकिन उन विनाशक कुछ भी नहीं करते हैं। आपको अपनी तस्वीर कक्षा में एक विनाशक जोड़ना चाहिए जो उन्हें हटाने वाले आकारों के माध्यम से पुनरावृत्त करता है। एक स्मार्ट पॉइंटर वर्ग का उपयोग करना, जैसा कि बॉबीएमसीआर सुझाव देता है, इस मुद्दे से बचाता है। – Steve314

+0

आप आदमी हैं! बहुत बहुत धन्यवाद। वह यह था। –

1

कॉन्वेंट रिटर्न प्रकार का उपयोग करें। अपने clone विधियों के लिए FAQ 20.8 देखें। आप Shape ऑब्जेक्ट्स बनाने के लिए कारखाने विधि पर भरोसा कर सकते हैं।

इसके अलावा, आप अमूर्त वर्ग वस्तुओं का कंटेनर नहीं रख सकते हैं, अमूर्त वर्गों को तत्काल नहीं किया जा सकता है। इसके बजाय, व्युत्पन्न ठोस वस्तुओं के पॉइंटर्स/संदर्भों का एक कंटेनर बनाएं। नोट, यदि आप पॉइंटर का उपयोग कर रहे हैं, तो उन्हें साफ़ करने की आपकी ज़िम्मेदारी बन जाती है। कंटेनर स्मृति को सही ढंग से आवंटित नहीं करेगा। आप इसे अधिक कुशलतापूर्वक संभालने के लिए कच्चे पॉइंटर्स के बजाय स्मार्ट पॉइंटर्स का उपयोग कर सकते हैं। बूस्ट से scoped_ptr और shared_ptr देखें।

+0

पहली स्किम पर, मैंने "कॉन्वेंट रिटर्न प्रकार" देखा और माना कि यह गलत सवाल का जवाब दे रहा था। यह बताते हुए कि मुख्य उत्तर के बाद आपको अधिक अपवर्तित अर्जित हो सकते हैं। हालांकि अब आपको मेरा +1 मिला है। – Steve314

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