2013-08-24 15 views
10

निम्न प्रोग्राम g ++ 4.4 में संकलित नहीं होता है यदि line 8 टिप्पणी की गई है। क्यूं कर? ऐसा लगता है कि जब मैं std::exception कन्स्ट्रक्टर ओवरराइड करता हूं, तो मुझे इसके विनाशक को भी ओवरराइड करना होगा। इसके लिए क्या कारण है?std के विनाशक ओवरराइडिंग: अपवाद

#include<iostream> 
#include<exception> 
using namespace std; 

class A : public exception { 
public: 
    A(string msg) : _msg(msg) {} 
    //~A() throw(){};      // line 8 
    const char* what() const throw() { return _msg.c_str();}  
private: 
    string _msg; 
}; 

int main() 
{ 
} 

संकलन त्रुटि है:

error: looser throw specifier for ‘virtual A::~A()’ 
+2

क्या संकलक एक त्रुटि संदेश रिपोर्ट करता है? और यदि हां, तो सवाल में क्यों नहीं है? –

+0

@ डेविड हेफरन, थेंक्स, निश्चित – cpp

+1

यह नीचे अपने प्रश्न में है (हालांकि संपादन के बाद हो सकता है)।यह निश्चित रूप से 4.8.1 के साथ समान है क्योंकि डिफ़ॉल्ट विनाशक को फेंक विनिर्देशक नहीं होगा जिसमें अनुरोध किया गया है। – lpapp

उत्तर

8

इसका कारण यह है नाशक थ्रो() विनिर्देशक की आवश्यकता है। यदि आप इसे अपनी कक्षा में निर्दिष्ट नहीं करते हैं तो संकलक आपके वर्ग के लिए यह स्वयं का डिफ़ॉल्ट विनाशक लिखता है, और डिफ़ॉल्ट विनाशक यह निर्दिष्ट नहीं करता है कि आप अपवाद नहीं फेंकते हैं।

यह सही है, के बाद से std :: अपवाद के सार्वजनिक नाशक भी निर्दिष्ट throw()

~A() throw(){}; 

मानक (N3225) 12.4.4 से: एक वर्ग के कोई उपयोगकर्ता- है

हैं घोषित विनाशक, एक विनाशक को निश्चित रूप से घोषित किया गया है> डिफ़ॉल्ट (8.4)। एक अंतर्निहित- घोषित विनाशक अपनी कक्षा का एक इनलाइन सार्वजनिक सदस्य है।

इसलिए, यदि आप स्वयं विनाशक घोषित नहीं करते हैं तो संकलक अगले विनाशक बनाता है। यदि आपके सभी अपवाद सदस्य विध्वंसक जहां nothrow योग्य हैं, तो संकलक शायद throw() निर्दिष्ट के साथ एक विनाशक उत्पन्न करेगा।

~A(){}; 

और तकनीकी रूप से एक इस नाशक से एक अपवाद फेंक सकता है, लेकिन है कि, बहुत बुरा प्रोग्रामिंग शैली होगा इसलिए एक अपवाद std::exception गारंटी से पाने है कि आप एक std::exception व्युत्पन्न वर्ग का नाशक में किसी भी अपवाद फेंक नहीं है ।

संपादित नई compilers एक नाशक अगर std :: स्ट्रिंग के नाशक noexcept निर्दिष्ट है एक noexcept विनिर्देशक है कि प्रदान करेगा। और अन्य कंपाइलर्स भी noexcept विनाशक उत्पन्न करेंगे यदि सभी सदस्य के विनाशक अपवाद नहीं फेंकते हैं (योग्यता योग्य नहीं हैं)। यह अध्याय 15.4 में सी ++ 11 मानक द्वारा अनिवार्य है। [वगैरह.spec]

14 एक स्पष्ट रूप से घोषित विशेष सदस्य समारोह (खंड 12) में एक अपवाद-विशिष्टता होगी। तो च है एक परोक्ष घोषित डिफ़ॉल्ट निर्माता, कॉपी निर्माता,, ले जाने के निर्माता, नाशक कॉपी काम ऑपरेटर, या असाइनमेंट ऑपरेटर ले जाते हैं, अपनी अंतर्निहित अपवाद-विशिष्ट कटियन विशिष्ट प्रकार आईडी टी es तभी टी द्वारा अनुमति दी है अगर एफ के निहित डीफिशन द्वारा सीधे लागू किए गए फ़ंक्शन का अपवाद-विशिष्टता; एफ सभी अपवादों को अनुमति देता है यदि कोई भी फ़ंक्शन सीधे इनकार करता है, तो सभी अपवादों को अनुमति देता है, और f कोई अपवाद की अनुमति नहीं देगा यदि प्रत्येक फ़ंक्शन इसे सीधे आमंत्रित करता है तो कोई अपवाद नहीं देता है। [...]

+4

जोड़ा गया यह पूरी कहानी नहीं बता रहा है। कंपाइलर उत्पन्न विनाशक के पास 'नोट्रो' विनिर्देश होगा यदि यह सीधे किए गए सभी कार्यों में कोई अपवाद नहीं है (गैर स्थैतिक डेटा सदस्यों के विनाशक और आधार वर्गों के विनाशक)। उदाहरण संकलित करने में विफल रहता है क्योंकि 'std :: string' सदस्य का विनाशक 'throw()' चिह्नित नहीं है। इसे 'कॉन्स्ट चार *' के साथ बदलने का प्रयास करें और अंतर देखें। – jrok

+1

दोनों [जीसीसी 4.8.1] (http://coliru.stacked-crooked.com/view?id=0717ca903ccad574b2dea253a7ad316c-f674c1a6d04c632b71a62362c0ccfc51) और [क्लैंग 3.4] (http://coliru.stacked-crooked.com/view?id = 0717ca903ccad574b2dea253a7ad316c-9f343bb235880f7057c63e887501d7f0) ओपी के कोड को संकलित करें ठीक है। वह है, सी ++ 11 में। मुझे नहीं पता कि यह C++ 03 के बाद बदला गया है या नहीं। – jrok

+0

@jrok उपयोगी उपयोगी टिप्पणी के लिए धन्यवाद, मैंने अपना उत्तर – hetepeperfan

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