2012-08-15 18 views
8

मैं एक सी ++ प्रश्नोत्तरी के माध्यम से जा रहा हूं। और निम्नलिखित कोड में आया - यह अवैध है, लेकिन मुझे समझ में नहीं आता क्यों। किसी को भी व्याख्या कर सकते हैं क्यों इस लाइन:विरासत - यह अवैध क्यों है?

Box* b1 = s1->duplicate(); 

संकलक त्रुटि, "आकार * से बॉक्स को परिवर्तित नहीं कर सकते" उत्पन्न करता है? मुझे लगता है कि s1->duplicate()Box::duplicate() पर कॉल कर रहा है क्योंकि s1 वास्तव में Box पर इंगित करता है - लेकिन संकलक त्रुटि से ऐसा लगता है कि यह Shape::duplicate() पर कॉल कर रहा है।

#include <iostream> 

struct Shape 
{ 
    virtual Shape* duplicate() 
    { 
    return new Shape; 
    } 

    virtual ~Shape() {} 
}; 

struct Box : public Shape 
{ 
    virtual Box* duplicate() 
    { 
    return new Box; 
    } 

}; 

int main(int argc, char** argv) 
{ 
    Shape* s1 = new Box; 

    Box* b1 = s1->duplicate(); 

    delete s1; 
    delete b1; 
    return 0; 
} 
+1

[टी की वजह से उसकी] (http://stackoverflow.com/questions/4665117/c-virtual-function-return-type)। –

उत्तर

8

Shape::duplicates()Shape* देता है, जो Box* नहीं है। आपके द्वारा वास्तव में लौटाए जाने वाले रनटाइम प्रकार के साथ कुछ लेना देना नहीं है। संकलक कैसे पता लगा सकता है कि Shape* वास्तव में Box पर इंगित करता है?

संपादित करें: इस बारे में सोचें:

struct Shape 
{ 
    virtual Shape* duplicate() 
    { 
    return new Shape; 
    } 

    virtual ~Shape() {} 
}; 

struct Box : public Shape 
{ 
    virtual Box* duplicate() 
    { 
    return new Box; 
    } 

}; 

struct Sphere : public Shape 
{ 
    virtual Sphere* duplicate() 
    { 
    return new Sphere; 
    } 

}; 

Shape* giveMeABoxOrASpehere() 
{ 
    if (rand() % 2) 
     return new Box; 
    else 
     return new Sphere; 
} 

// 
Shape* shape = giveMeABoxOrASphere(); 
// What does shape->duplicate() return? 

Box* shape = giveMeABoxOrASphere(); 
// shoud this compile? 
+0

हम्म। खैर - मुझे लगता है कि मैं लाइनों के साथ सोच रहा था, कि अगर कंपाइलर 'आकार * एस' = नया बॉक्स' स्वीकार कर सकता है तो यह किसी भी तरह * पता * होगा कि 's1' अब बॉक्स के लिए एक सूचक है। देर हो चुकी है, मुझे लगता है कि मेरा दिमाग तला हुआ है। । । – BeeBand

+2

@BeeBand: 'आकार * एस = नया बॉक्स; 'और' बॉक्स * बी = नया आकार; 'के बीच एक महत्वपूर्ण अंतर है। – aschepler

+1

@BeeBand इस मामले में आप 'dynamic_cast' के साथ पता लगा सकते हैं, इसलिए प्रकार की जानकारी पूरी तरह से खो नहीं जाती है। यह संकलक के लिए अभी अनुपलब्ध है। –

15

सी ++ भाषा स्थाई रूप से टाइप की गई है। आपके कॉल की वैधता के बारे में निर्णय संकलन समय पर किए जाते हैं। स्पष्ट रूप से, संकलक यह नहीं जानता कि s1->duplicate()Box ऑब्जेक्ट पर पॉइंटर लौटाता है। इन परिस्थितियों में, यह आपके कोड को स्वीकार करने की अपेक्षा करना अजीब होगा।

हां, s1->duplicate() वास्तव में आपके उदाहरण में Box::duplicate पर कॉल करता है, लेकिन आप संकलक को यह कैसे जानते हैं? कोई कह सकता है कि यह आपके विशिष्ट उदाहरण से "स्पष्ट" है, लेकिन इस भाषा सुविधा का विनिर्देश इस तरह के "स्पष्ट" मामलों के लिए अपवाद नहीं करता है।

1

ठीक उसी कारण

Shape* s1 = new Box; 
Box* b1 = s1; 

संकलन नहीं करता। कंपाइलर परवाह नहीं है कि s1Box को संदर्भित करता है, न ही इसे ध्यान में रखना चाहिए।

आप जानते हैं कि s1 एक Box को संदर्भित करता है, तो बस यह कहना:

Box *s1 = new Box; 

सिंटैक्स के बारे में एक नोट: Box * s1; के लिए पार्स नियम (बहुत सरल) कर रहे हैं:

declaration := type-name declarator ; 
declarator := name 
      | * declarator 
तो

पार्सिंग है:

Box  *  s1  ; 
        ^^^^^^^^ 
        declarator 
^^^^^^^^^ ^^^^^^^^^^^^^^^^^^ 
type-name   declarator 

और समूहांकन है Box (* (s1))

यह Box *s1; लिखने के लिए है क्योंकि यह Box* s1; से पार्स आप एक घोषणा में एक से अधिक चर घोषित हैं के साथ और अधिक संगत है सबसे अच्छा शैली माना जाता है, Box* वाक्य रचना भ्रामक हो सकते हैं:

Box* x, y; 

x है Box, लेकिन y के लिए सूचक, एक Box है के रूप में पार्स है:

Box (*x), y; 
+0

ठीक है टिप के लिए धन्यवाद। पार्सिंग । । – BeeBand

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