2009-08-04 9 views
7

मैं यह नहीं समझ सकता कि इसके साथ क्या हो रहा है।सी ++ ओवरराइडिंग विधियां

मैं एक दृश्य वर्ग संस्थाओं का एक वेक्टर है और आप दृश्य से जोड़ सकते हैं और प्राप्त करने के लिए संस्थाओं की अनुमति देता है कि है:

class Scene { 
    private: 
     // -- PRIVATE DATA ------ 
     vector<Entity> entityList; 
    public: 
     // -- STRUCTORS --------- 
     Scene(); 
     // -- PUBLIC METHODS ---- 
     void addEntity(Entity); // Add entity to list 
     Entity getEntity(int); // Get entity from list 
     int entityCount(); 
}; 

मेरे इकाई वर्ग इस प्रकार है (उत्पादन परीक्षण के लिए है):

आप के रूप में

class Polygon: public Entity 
{ 
    private: 
     // -- PRIVATE DATA ------ 
     vector<Point2D> vertexList; // List of vertices 
    public: 
     // -- STRUCTORS --------- 
     Polygon() {}; // Default constructor 
     Polygon(vector<Point2D>); // Declare polygon by points 
     // -- PUBLIC METHODS ---- 
     int vertexCount(); // Return number of vertices 
     void addVertex(Point2D); // Add vertex 
     void draw() { cout << "Yes" << endl; }; // Draw polygon 
     // -- ACCESSORS --------- 
     Point2D getVertex(int); // Return vertex 
}; 

:

class Entity { 
    public: 
     virtual void draw() { cout << "No" << endl; }; 
}; 

और फिर मैं एक बहुभुज वर्ग इकाई से विरासत है देख सकते हैं, इसमें एक ड्रॉ() विधि है जो कि एंटिटी क्लास से प्राप्त ड्रा() विधि को ओवरराइड करनी चाहिए।

लेकिन ऐसा नहीं है। निम्नलिखित कोड का उपयोग करते समय:

scene->getEntity(0).draw(); 

जहां इकाई 0 एक बहुभुज है (या कम से कम होना चाहिए), यह "नहीं" माता-पिता विधि से प्रिंट (जैसे कि यह एक बहुभुज, बस एक इकाई नहीं है)। वास्तव में, यह मुझे प्राप्त किए बिना बहुभुज के लिए अद्वितीय किसी भी तरीकों कॉल नहीं लगती:

'कुछ विधि नाम': 'इकाई'

इसलिए किसी भी क्या हो रहा है विचार का सदस्य नहीं है?

सहायता के लिए धन्यवाद।

अद्यतन:

तो मैं पहले उत्तर में दिए गए कोड को क्रियान्वित किया है, लेकिन मैं सूची में मेरी बहुभुज जोड़ने के बारे में यकीन नहीं है। कुछ इस तरह?

const tr1::shared_ptr<Entity>& poly = new Polygon; 
poly->addVertex(Point2D(100,100)); 
poly->addVertex(Point2D(100,200)); 
poly->addVertex(Point2D(200,200)); 
poly->addVertex(Point2D(200,100)); 
scene->addEntity(poly); 

मुझे अभी इस साझा_प्टर व्यवसाय में उपयोग नहीं किया जा रहा है।

+1

अपनी दृश्य कक्षा में इकाई वस्तुओं की प्रतियों की बजाय इकाइयों को पॉइंटर्स संग्रहीत करने का प्रयास करें। – chollida

उत्तर

14

मुझे लगता है कि आपको अपना कॉलिंग कोड पोस्ट करना होगा, लेकिन अनिवार्य रूप से समस्या यह है।

आपके पास एक ठोस वर्ग Polygon है जो एक और ठोस वर्ग Entity से प्राप्त होता है। आपकी addEntity और getEntity फ़ंक्शंस Entityमान द्वारा मानते हैं और यदि आप Entity को पास करने या पुनर्प्राप्त करने का प्रयास करते हैं, तो आप उस ऑब्जेक्ट के केवल Entity भाग (इसे स्लाइसिंग) और ऑब्जेक्ट के व्युत्पन्न हिस्से के बारे में जानकारी कॉपी करेंगे खो जाएगा।

इसके अतिरिक्त आपके पास vectorEntity है, जो बेस क्लास ऑब्जेक्ट्स का वेक्टर है, इसलिए आपके पास मूल प्रकार के ऑब्जेक्ट के अलावा कुछ भी स्टोर करने का कोई तरीका नहीं है।

आप वस्तुओं की एक मिश्रित प्रकार का एक संग्रह की आवश्यकता है, लेकिन सभी Entity से ली गई हैं, तो आप डायनामिक रूप से तैयार वस्तुओं और इस तरह के एक tr1::shared_ptr या एक boost::shared_ptr के रूप में स्मार्ट सूचक किसी प्रकार का उपयोग करने की आवश्यकता हो सकती है।

उदा।

class Scene { 
    private: 
     // -- PRIVATE DATA ------ 
     vector< std::tr1::shared_ptr<Entity> > entityList; 
    public: 
     // -- STRUCTORS --------- 
     Scene(); 
     // -- PUBLIC METHODS ---- 
     void addEntity(const std::tr1::shared_ptr<Entity>&); // Add entity to list 
     const std::tr1::shared_ptr<Entity> getEntity(int); // Get entity from list 
     int entityCount(); 
}; 

संपादित

आपका अपडेट किया गया बुला कोड, अनिवार्य रूप से सही है, हालांकि एक साझा सूचक के लिए एक स्थानीय स्थिरांक संदर्भ का उपयोग करते हुए एक सा अस्पष्ट है।

मैं शायद की तरह कुछ के साथ जाना चाहते हैं:

std::tr1::shared_ptr<Polygon> poly(new Polygon); 
poly->addVertex(Point2D(100,100)); 
poly->addVertex(Point2D(100,200)); 
poly->addVertex(Point2D(200,200)); 
poly->addVertex(Point2D(200,100)); 
scene->addEntity(poly); 
+3

या इसे अधिक ग्राफिक रूप से रखने के लिए, पोस्ट कोड पॉलीगॉन ले रहा है और इसे एक इकाई आकार के बॉक्स में डाल रहा है, और यह सभी फिट नहीं है। –

+0

इस नए कोड के बारे में एक प्रश्न के साथ ओपी अपडेट किया गया। –

+0

अब समस्या यह है कि addVertex() पॉलीगॉन के लिए अद्वितीय है: त्रुटि C2039: 'addVertex': 'Entity' का सदस्य नहीं है, जो बहुत मदद के लिए धन्यवाद। (क्षमा करें, मुझे यकीन नहीं है कि मुझे टिप्पणियों में इन अतिरिक्त प्रश्नों को पोस्ट करना चाहिए) –

1

chollida की टिप्पणी सही है: यदि आप एक स्मृति स्थान प्रकार इकाई के लिए में प्रकार बहुभुज का एक उद्देश्य को आगे बढ़ाने रहे हैं और किन कहा जाता है में चल रहा है टुकड़ा। अतिरिक्त 'बहुभुज' जानकारी काट दिया जाता है और आपके द्वारा छोड़ा गया सब कुछ इकाई है।

आपको इन स्थितियों में आधार कक्षाओं के लिए पॉइंटर्स (या संदर्भ, यदि संभव हो) स्टोर करना चाहिए।

0

आपको पहले स्थान पर पॉइंटर्स (स्मार्ट पॉइंटर्स :) अधिमानतः) स्टोर करना चाहिए। गेटटर विधि को कॉल करने से पहले भी आपकी ऑब्जेक्ट्स को कटाई के दौरान वेक्टर पुन: आवंटित कर रहा है।

गेटर विधि के लिए वापसी प्रकार भी एक सूचक या संदर्भ होना चाहिए ताकि आप उस polimorphic कॉल करने में सक्षम हो।

1

आपको इसके लिए एक शुद्ध वर्चुअल फ़ंक्शन का उपयोग करना चाहिए।

class Entity 
{ 
public: 
    virtual void draw() = 0; 
}; 

फिर अपने ऑब्जेक्ट से ड्रॉ फ़ंक्शन को कॉल करें, और आपको अपनी ऑब्जेक्ट्स पर पॉइंटर्स का भी उपयोग करना चाहिए।

+0

> इसके लिए आपको शुद्ध वर्चुअल फ़ंक्शन का उपयोग करना चाहिए। जरूरी नहीं है। एंटिटी क्लास में निश्चित रूप से एक ठोस ड्रॉ विधि हो सकती है। – chollida

0

अंगूठे के नियम के रूप में, आपको पॉलीमोर्फिक रूप से उपयोग करने के इरादे से ऑब्जेक्ट्स से निपटने के दौरान हमेशा मूल्य अर्थशास्त्र के बजाय संदर्भ अर्थशास्त्र (यानी पॉइंटर्स या संदर्भों के माध्यम से एक्सेस ऑब्जेक्ट्स) का उपयोग करना चाहिए।

इस तरीके से सुरक्षा सुनिश्चित करने के लिए, निजी कॉपी कन्स्ट्रक्टर और असाइनमेंट ऑपरेटर बनाकर अपने सभी पॉलिमॉर्फिक प्रकार noncopyable की बेस क्लास बनाना बुद्धिमानी है। यह प्रभावी रूप से स्लाइसिंग को रोक देगा क्योंकि गलती से मूल्य अर्थशास्त्र का उपयोग करने पर कोड केवल जटिल होने में असफल हो जाएगा।