2015-07-25 9 views
5

ऑटो और गतिशील_कास्ट का उपयोग करते समय मुझे एक बहुत अजीब व्यवहार का सामना करना पड़ा है।गतिशील कास्ट एक संदर्भ और ऑटो

class BaseInterface { 
public: 
    virtual void someMethod()=0; 
}; 

class Derived:public BaseInterface { 
public: 
    virtual void someMethod1()=0; 
    void someMethod()override; 
}; 

और निश्चित रूप से वहाँ कुछ वर्गों है कि सभी व्युत्पन्न तरीकों को लागू कर रहे हैं: यह पदानुक्रम मैं वर्ग है।

class ThirdClass { 
public: 
    void demoMethod(BaseInterface&); 
    void anotherMethod(Derived&); 
}; 

void ThirdClass::demoMethod(BaseInterface& obj) { 
    auto buffer=dynamic_cast<Derived&>(obj); 
    anotherMethod(buffer); 
} 

जब मैं इस जीसीसी के साथ संकलन मैं एक "सार प्रकार का ऑब्जेक्ट आवंटित नहीं कर सकता" त्रुटि मिलती है:

तो फिर वहाँ एक तृतीय श्रेणी के जो इस तरह दिखता है। जबकि जब मैं

auto buffer=... 

की जगह के साथ

Derived& buffer=... 

सब कुछ ठीक संकलित करता है। वह मामला क्या है? क्या ऑटो सही प्रकार या कुछ कम नहीं कर रहा है?

इसके अलावा मैं एक गंदा चाल पाया अभी भी ऑटो उपयोग करने के लिए: auto से

void ThirdClass::demoMethod(Base& obj) { 
    auto buffer=dynamic_cast<Derived*>(&obj); 
    anotherMethod(*buffer); 
} 
+4

मैं अनुमान लगा रहा हूं कि 'ऑटो' प्रकार 'व्युत्पन्न बफर' टाइप करता है, न कि 'व्युत्पन्न और बफर'। – melpomene

+0

क्या आप g ++ का संस्करण उपयोग कर रहे हैं? अपने कोड को संकलित करने के लिए ठीक काम करता है [छोटे टाइपो को ठीक करने के बाद 'डेमो मोड' पर कोई रिटर्न टाइप नहीं है और 'व्युत्पन्न' पर कोई विरासत नहीं है - दोनों क्लैंग ++ 3.7 (लगभग दो सप्ताह पुराना) और g ++ 4.9.2। –

+0

@ मैट्स पीटरसन: यदि लापता रिटर्न प्रकार तय किया गया है, तो जो भी संकलक विचारक उपयोग करता है, उसके साथ रिपोर्ट किए गए तरीके में विफल रहता है: http://ideone.com/UEtfui –

उत्तर

6

आप हो रही है Derived। बजाय इस का उपयोग करें:

auto & buffer = dynamic_cast<Derived&>(obj); 
5

§7.1.6.4/7:

एक चर एक प्लेसहोल्डर प्रकार का उपयोग घोषित जब आरंभ नहीं हो जाता [...] निष्कर्ष निकाला वापसी प्रकार या वैरिएबल प्रकार प्रकार से निर्धारित किया जाता है इसके प्रारंभकर्ता के । [...] T को या फ़ंक्शन के प्रकार का घोषित प्रकार घोषित करें। यदि प्लेसहोल्डर auto टाइप-विनिर्देशक है, तो घटाया गया प्रकार टेम्पलेट तर्क कटौती के नियमों का उपयोग करके निर्धारित किया जाता है। [...] PT से या तो एक नया आविष्कार प्रकार टेम्पलेट पैरामीटर U साथ auto की घटनाओं की जगह प्राप्त [...]। U के लिए एक मूल्य के एक समारोह कॉल (14.8.2.1), जहां P एक समारोह टेम्पलेट पैरामीटर प्रकार है और इसी तर्क प्रारंभकर्ता है से टेम्पलेट तर्क कटौती के नियमों का उपयोग कर परिणाम निकालना।

तो, आदेश की प्रक्रिया के साथ खुद को परिचित करने के लिए, वास्तविक buffer के प्रकार बात का अनुमान लगाना के लिए इस्तेमाल शासन पर एक नज़र डालें: क्या होगा यदि आप बदलना होता है

template <typename U> 
void f(U); 

को

void f(Derived&); 

f को Derived के प्रकार के साथ कॉल करते समय? जाहिर है, फ़ंक्शन टेम्पलेट के लिए, U को Derived के रूप में घटाया जाएगा, जो तब कटौती विफलता उत्पन्न करता है।
यह सीधे आपके उदाहरण में प्लेसहोल्डर प्रकार की कटौती से मेल खाता है - autoDerived द्वारा प्रतिस्थापित किया जाएगा, और यह विफल रहता है, क्योंकि Derived सार है।

सामान्य शब्दों में, यदि आप लिखना

auto obj = …; 

obj एक संदर्भ कभी नहीं होगा, बस के रूप में U एक संदर्भ प्रकार के रूप में जब ऊपर समारोह टेम्पलेट बुला कभी नहीं निष्कर्ष निकाला की जाएगी।


इसके बजाय, auto& का उपयोग करें:

auto& buffer = dynamic_cast<Derived&>(obj); 

अब, PU& है:

template <typename U> 
void f(U&); 

U ज़ाहिर है, है, अभी भी Derived के रूप में निष्कर्ष निकाला है, लेकिन P के प्रकार - जो प्रभावी रूप से buffer का प्रकार है - Derived& है।

+2

लॉल, "स्पष्ट रूप से" –

+0

@ लाइटनेसरेसेसिन ऑर्बिट वेल, मुझे लगा कि पूछताछ टेम्पलेट तर्क कटौती के लिए उपयोग की जाती है :) – Columbo

+0

@ कोल्मुबो ईमानदार नहीं है। मैंने अभी 3 महीने पहले सी ++ के साथ शुरुआत की थी और अभी तक टेम्पलेट्स पर ठोकर खाई है। – SuppenGeist

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