2010-06-03 7 views
10

क्या इंटरफेस को आभासी विनाशक की आवश्यकता है, या ऑटो-जनरेटेड एक जुर्माना है? उदाहरण के लिए, निम्नलिखित दो कोड स्निपेट्स में से कौन सा सर्वोत्तम है, और क्यों? कृपया ध्यान दें कि ये पूरी कक्षा है। जावा-स्पीच में कोई अन्य विधियां, चर, इत्यादि नहीं हैं, यह एक "इंटरफ़ेस" है।इंटरफेस के लिए वर्चुअल विनाशक

class Base 
{ 
public: 
    virtual void foo() = 0; 
    virtual ~Base() {} 
}; 

या ...

class Base 
{ 
public: 
    virtual void foo() = 0; 
    ~Base() {} // This line can be omitted, but included for clarity. 
}; 

संपादित कारण जवाब "नहीं हैं कि क्या मैं तलाश कर रहा हूँ" के लिए:

प्रत्येक मार्ग के परिणाम हैं वास्तव में क्या। कृपया अस्पष्ट उत्तर न दें जैसे "यह ठीक से नष्ट नहीं किया जाएगा"। कृपया मुझे बताएं कि वास्तव में क्या होगा। मैं एक असेंबली बेवकूफ हूँ।

संपादित करें 2:

मुझे अच्छी तरह पता है कि "आभासी" टैग का मतलब है कि नाशक अगर व्युत्पन्न के सूचक के माध्यम से नष्ट कर दिया बुलाया नहीं होता है, लेकिन (मुझे लगता है कि) इस सवाल अंततः नीचे फोड़े हूँ "क्या यह विनाशक को छोड़ना सुरक्षित है, क्योंकि यह वास्तव में तुच्छ है?"

संपादित करें 3:

मेरी दूसरी संपादित सिर्फ सादा गलत और दुष्प्रचार है। अधिक जानकारी के लिए कृपया वास्तविक स्मार्ट लोगों द्वारा टिप्पणियां पढ़ें।

+3

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

+1

@ जोर्डन: हे भगवान, मुझे लगता है कि आप सही हैं। –

+4

"मैं एक असेंबली बेवकूफ हूँ"। यह दुर्भाग्यपूर्ण है, क्योंकि सी ++ असेंबली पैदा करने के बारे में कुछ भी नहीं कहता है। यदि आप देखना चाहते हैं कि एक विशेष कंपाइलर इसे कैसे संभालता है, तो कुछ कोड संकलित करें और आउटपुट देखें। और -1 बस अपने दृष्टिकोण के लिए; एक प्रश्न मत पूछें और सभी उत्तरदाताओं को बताएं कि "आपको इसे पीछे की ओर मिला है" और उन्हें कम करें। आप किसी कारण से एक प्रश्न पूछ रहे हैं, है ना? – GManNickG

उत्तर

13

पर विचार करें निम्नलिखित मामला:

Base *Var = new Derived(); 
    delete Var; 

आप आभासी नाशक की जरूरत है, नहीं तो जब आप Var हटाने के लिए, व्युत्पन्न वर्ग 'नाशक कभी नहीं बुलाया जाएगा।

+0

इसका उल्लेख करने योग्य कोई विनाशक नहीं है। –

+2

@ वाह: * बेस * का उल्लेख करने योग्य कोई विनाशक नहीं है। आप नहीं जानते कि व्युत्पन्न विनाशक क्या करता है। –

+2

आप यहां मुख्य बिंदु खो रहे हैं। 'व्युत्पन्न :: ~ व्युत्पन्न 'तब तक नहीं बुलाया जा रहा है जब तक कि आप आधार :: ~ बेस को वर्चुअल के रूप में घोषित न करें। –

0

नहीं ... आभासी विनाशक ऑटो उत्पन्न नहीं होते हैं। आपको उन्हें अपनी बेस क्लास में स्पष्ट रूप से घोषित करना होगा। लेकिन आपको आधार के बाल वर्गों के लिए अपने विनाशकों को आभासी घोषित करने की आवश्यकता नहीं होगी। यह संकलक द्वारा किया जाता है। संकलक यह भी सुनिश्चित करेगा कि विनाशकों को निर्माण के उलट क्रम (व्युत्पन्न से आधार तक) कहा जाता है।

public class Base 
{ 
//... 
} 

public class Derived 
{ 
    int i = 0; 
    //... 
} 

//... 

Base* b = new Derived(); 

आप एक आभासी नाशक

delete b; 

, मेमोरी लीक (पूर्णांक क्षेत्र के लिए कम से कम 4 बाइट्स) का कारण है क्योंकि यह केवल Base और नहीं Derived संहार होगा आपके पास नहीं था। गुणता सुनिश्चित करता है कि व्युत्पन्न कक्षाएं भी नष्ट हो जाती हैं। आपको Derived में वर्चुअल कंस्ट्रक्टर घोषित करने की आवश्यकता नहीं होगी, यदि आपने Base में वर्चुअल विनाशक घोषित किया है, तो यह संकलक द्वारा अनुमानित किया जाएगा।

3

यदि आप लोगों को पॉइंटर्स या अभिभावक वर्ग के संदर्भों के माध्यम से व्युत्पन्न कक्षा की वस्तुओं को हटाने का प्रयास करने की अपेक्षा करते हैं तो आपको आभासी विनाशक का उपयोग करना चाहिए। यदि यह मामला है, तो आभासी विनाशक के बिना, व्युत्पन्न वर्ग कभी भी ठीक से नष्ट नहीं किया जाएगा।

उदाहरण के लिए,

Derived::~Derived() { // important stuff } 
Base *foo = new Derived(); 
delete foo; 

बेस में एक आभासी नाशक के बिना, व्युत्पन्न नाशक कभी नहीं बुलाया जाएगा, और महत्वपूर्ण सामग्री को इसलिए ऐसा कभी नहीं होगा।

+4

असल में, इस मामले में सी ++ द्वारा अपरिभाषित क्या होता है। –

2

सामान्य तौर पर, एक नाशक होना चाहिए या तो (1) सार्वजनिक और आभासी, या (2) संरक्षित और गैर आभासी।

मान लीजिए कि आप कभी भी किसी इंटरफ़ेस पॉइंटर के माध्यम से क्लास इंस्टेंस को हटाने की उम्मीद नहीं करते हैं, संरक्षित गैर-आभासी विनाशक 100% सुरक्षित है।

अगर कोई (2) में इंटरफ़ेस पॉइंटर को हटाने का प्रयास करता है, तो उन्हें संकलन-समय त्रुटि मिल जाएगी।

+0

क्या आप अपनी पहली वाक्य में "विनाशक" कहने का मतलब रखते थे? –

+0

मैंने किया। अरे, अच्छा पकड़ो – zildjohn01

7

यदि आप सी ++ में बेस क्लास पॉइंटर के माध्यम से व्युत्पन्न क्लास ऑब्जेक्ट को हटाते हैं, तो परिणाम अपरिभाषित व्यवहार है। यूबी ऐसा कुछ है जिसे आप वास्तव में टालना चाहते हैं, इसलिए आपको बेस क्लास को आभासी विनाशक देना होगा। सी ++ स्टैंडर्ड से बोली के लिए, अनुभाग 5.3.5:

अगर संकार्य के स्थिर प्रकार की गतिशील प्रकार से अलग है, स्थिर प्रकार संकार्य की गतिशील प्रकार और का एक आधार वर्ग होगा स्थैतिक प्रकार में वर्चुअल विनाशक होगा या व्यवहार अपरिभाषित है।

3

संपादित करने के लिए ज्यादातर उत्तर दिया जा रहा:

कोई भी आपको बता सकता है कि क्या होगा क्योंकि परिणाम "अपरिभाषित व्यवहार" है। जब आप किसी ऐसे पॉइंटर के माध्यम से व्युत्पन्न वर्ग को हटाते हैं जिसमें कोई आभासी विनाशक नहीं होता है, तो कार्यान्वयन किसी भी तरीके से तोड़ने के लिए स्वतंत्र होता है।