2011-09-05 16 views
8

मैंने इंटरनेट पर देखा है और यह थ्रेड इस स्थिति का पूरा उत्तर ढूंढ रहा है। मैंने पढ़ा है कि वस्तुओं को स्मार्ट पॉइंटर्स फेंकना बहुत चालाक नहीं है। मैं सिर्फ यह समझना चाहता हूं कि ऐसा क्यों हो रहा है। मैं स्थिति की व्याख्या करूंगा। चलो इस सरल पदानुक्रम की कल्पना करते हैं:स्मार्ट प्वाइंटर्स और अपवाद हैंडलिंग

class Foo 
{ 
public: virtual ~Foo() {} 
}; 

typedef tr1::shared_ptr<Foo> SPFoo; 

class FooInherited: public Foo { }; 

typedef tr1::shared_ptr<FooInherited> SPFooInherited; 

और के इस परीक्षण कोड की जांच करते हैं:

int main(int argc, char** argv) 
{ 
    try 
    { 
    throw FooInherited(); 
    } 
    catch(const Foo& f) 
    { 
    cout << "Foo& caught!" << endl; 
    } 
    try 
    { 
    throw SPFooInherited(new FooInherited()); 
    } 
    catch(const SPFoo& f) 
    { 
    cout << "SPFoo& caught!" << endl; 
    } 
    return 0; 
} 

सब कुछ संकलित लेकिन क्रम में दूसरा कोशिश पकड़ निष्पादित नहीं किया जाएगा। क्या कोई मुझे समझा सकता है क्यों? विशेष रूप से यदि जैसे कोड की रेखाएं रनटाइम में यह काम बिल्कुल ठीक है।

void function(const SPFoo& f) 
{ 
} 

... 

SPFooInherited fi(new FooInherited()); 
function(fi); 

मुझे समझ नहीं समस्या यह है कि SPFooInherited SPFoo (भले ही FooInherited फू से विरासत) से विरासत नहीं है, लेकिन यह गहराई से पता करने के लिए संकलक/क्या चाहते हैं आरटीई समारोह कॉल उदाहरण से अलग ढंग से कर रही है अपवाद को पकड़ते समय स्थिति को हल करने में सक्षम नहीं होना चाहिए। क्या ऐसा इसलिए है क्योंकि कैच पैरामीटर फ़ंक्शन कॉल पैरामीटर के समान नहीं है? क्यों Foo & काम करता है और एसपीएफयू नहीं करता है?

अग्रिम में बहुत बहुत धन्यवाद।

सम्मान, आईकर।

उत्तर

13

जैसा कि आपने अपने प्रश्न में कहा था, SPFooInheritedSPFoo का उप-वर्ग नहीं है। इसका मतलब है कि catch(SPFoo const&)SPFooInherited के उदाहरण नहीं पकड़ेगा। दूसरी तरफ, FooInheritedFoo से विरासत में मिला है, और इसलिए catch(Foo const&)FooInherited के उदाहरण प्राप्त करेगा।

इसे समझने के लिए आपको कंपाइलर या रन-टाइम-पर्यावरण की किसी भी विशेष समझ की आवश्यकता नहीं है। यह सिर्फ भाषा का हिस्सा है।

कारण यह है कि फ़ंक्शन पर कॉल करने का कारण यह है कि tr1::shared_ptr में एक टेम्पलेट गैर-स्पष्ट कन्स्ट्रक्टर है जो फ़ंक्शन कॉल साइटों पर एक अंतर्निहित रूपांतरण की अनुमति देता है।

है:

//Note the lack of explicit 
template<class Y> shared_ptr(shared_ptr<Y> const & r); 

यह एक shared_ptr एक अलग साझा सूचक प्रकार से निर्माण किया जा करने के लिए अनुमति देता है: tr1::shared_ptr निम्नलिखित निर्माता है। SPFoo में SPFooInherited में पॉइंटर को वास्तव में संग्रहीत करने के लिए इस कन्स्ट्रक्टर का कार्यान्वयन FooInherited* से Foo* पर अंतर्निहित रूपांतरण पर निर्भर करता है। यदि यह निहित रूपांतरण मौजूद नहीं है तो कोड संकलित नहीं होगा, और असंबद्ध प्रकारों के लिए shared_ptr एस के बीच असुरक्षित रूपांतरण नहीं होंगे।

समारोह कॉल और पकड़ के बीच मौलिक अंतर (FooInherited है-एक Foo, तो यह से मेल खाएगी) है कि निहित रूपांतरण समारोह तर्कों के प्रारंभ में नहीं होगा, लेकिन एक कैच केवल एक ही प्रकार से मेल कर सकते हैं।

3

क्योंकि SPFooSPFooInherited का एक उपवर्ग नहीं है।catch ब्लॉक केवल उन चीज़ों को पकड़ेंगे जो उनकी पकड़ सूची में हैं, या उनकी कैच सूची में मौजूद सार्वजनिक बाल वर्ग। FooInheritedFoo से विरासत प्राप्त करता है, इसलिए Foo को पकड़ने से आपको FooInherited पकड़ने की सुविधा मिल जाएगी। SPFoo और SPFooInherited पूरी तरह से अलग और असंबंधित वर्ग हैं।

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