2010-04-22 15 views
19

मौजूदा कोड बेस (डर और भयावहता) पर पीसी-लिंट का उपयोग शुरू करना।सी ++ इंटरफेस जैसी कक्षाओं के लिए विनाशक

class IBatch 
{ 
public: 
    virtual void StartBatch() =0; 
    virtual int CommitBatch() =0; 
}; 

कौन सा है जब एक और वर्ग इस से निकला एक इंटरफेस की तरह इसका इस्तेमाल करने

base class 'IBatch' has no destructor 

तो, सवाल:

एक बात है कि इसके बारे में शिकायत निम्नलिखित है जब आप बनाने इंटरफ़ेस उपरोक्त की तरह कक्षाएं, क्या आप हमेशा वर्चुअल विनाशक शामिल करते हैं? क्यूं कर? (यह एक शैली या एक कोडिंग त्रुटि है?)

संपादित करें: ने कहा है चाहिए कि मैं उम्मीद या उपयोगकर्ता IBatch की संहार करना चाहते हैं नहीं है, वे एक सेवा के एक उपभोक्ता केवल कुछ करने के लिए इस इंटरफेस के माध्यम से कर रहे हैं, बाहरी कार्यान्वयन वर्ग (यदि इससे कोई फर्क पड़ता है)

+1

जैसा कि अन्य ने कहा, आपको वर्चुअल डीटीओआर की आवश्यकता है। जैसे ही साइड नोट: COM इंटरफेस इसके बजाय 'रिलीज़()' पर भरोसा करते हैं, जो एक वर्चुअल विधि है जो "उचित" व्युत्पन्न डीटीओआर पर रीडायरेक्ट कर सकती है। – peterchen

उत्तर

5

यदि वर्चुअल फ़ंक्शन हैं, तो वर्चुअल विनाशक होने की आवश्यकता है। हमेशा। इससे कोई फर्क नहीं पड़ता कि यह केवल एक इंटरफ़ेस वर्ग है - इसे अभी भी आभासी विनाशक की आवश्यकता है।

या तो, या इसे protected गैर-वर्चुअल विनाशक की आवश्यकता है। लेकिन फिर आप इंटरफ़ेस पॉइंटर का उपयोग कर ऑब्जेक्ट को हटा नहीं सकते हैं।

+1

जब तक विनाशक संरक्षित नहीं होता है (यानी, आप पॉइंटर-टू-इंटरफेस के माध्यम से हटाने को रोक रहे हैं)। –

+0

@ स्टेव: हेहे - तय। –

2

तो, सवाल: जब आप इसके बाद के संस्करण की तरह इंटरफ़ेस कक्षाएं बनाने, कर आप हमेशा एक आभासी नाशक शामिल हैं? क्यूं कर? (क्या यह एक शैली है या कोडिंग त्रुटि है?)

वैसे यह वास्तव में निर्भर करता है। यदि आप कभी भी आईबैच पॉइंटर पर डिलीट करते हैं तो संभवतः आप जो भी उम्मीद कर रहे हैं वह नहीं करेंगे। बेशक यदि आपके पास वर्चुअल इनिट/शटडाउन या एड्रफ/रिलीज जैसे कुछ हैं तो यह वास्तव में कोई समस्या नहीं है।

4

आभासी कार्यों वाला एक वर्ग लेकिन कोई वर्चुअल विनाशक संदिग्ध नहीं है, और सबसे अधिक संभावना गलत: here एक अच्छा और अधिक सटीक स्पष्टीकरण देखें।

7

कोडिंग त्रुटि - आपके व्युत्पन्न वर्ग के लिए नाशक अगर आधार वर्ग के सूचक के माध्यम से कहा जाता है कहा जाता हो कभी नहीं होगा।

जब आप IBatch को लागू करने और आप (IBatch सूचक) एक आधार वर्ग के सूचक के द्वारा अपने व्युत्पन्न वर्ग को देखें और आप आधार वर्ग के लिए है कि सूचक पर delete फोन आप स्मृति रिसाव के साथ खत्म हो सकता है, क्योंकि के लिए नाशक अपने व्युत्पन्न वर्ग कभी नहीं बुलाया जाएगा।

मूल नियम तब होता है जब कक्षा में कम से कम एक virtual विधि होती है, जिसके लिए virtual विनाशक होना आवश्यक है।

class IBatch 
{ 
    public: 
     virtual void f() = 0; 
}; 

class A : public IBatch 
{ 
    public: 
     void f() {} 
     ~A() {} 
}; 

IBatch * a = new A(); 
a->f(); // calls A::f() 
delete a; // calls IBatch::~IBatch() not A::~A() 
+2

क्या होगा यदि मैं आईबैच इंटरफ़ेस के उपयोगकर्ताओं को मुझे हटाने के लिए नहीं चाहता हूं - क्या वह है जहां @ जेम्स से सुरक्षित और गैर-आभासी उत्तर आता है? – sdg

+0

'me'' से आपका क्या मतलब है? – stefanB

+1

@ एसडीजी: हां। एक संरक्षित विनाशक * अन्य * कक्षाओं (उस वर्ग पदानुक्रम के बाहर) को हटाने पर कॉल करने से रोकता है। – Kissaki

0

संकलक डिफ़ॉल्ट नाशक कि आभासी नहीं है, जिसका मतलब है कि एक आभासी आधार वर्ग के लिए सूचक पर 'नष्ट' एक परिणामस्वरूप स्मृति रिसाव के साथ सफल होगा डालता है। इसलिए, यह एक कार्यान्वयन दोष है, न तो शैली या कोडिंग त्रुटि।

+0

दरअसल, वर्चुअल फ़ंक्शंस के साथ किसी व्युत्पन्न ऑब्जेक्ट को वर्चुअल फ़ंक्शंस के बिना किसी वर्चुअल डिस्ट्रक्टर के बिना बेस क्लास में हटा देना अपरिभाषित व्यवहार है। तो यह एक कोडिंग त्रुटि है, और कुछ भी हो सकता है जिसमें स्मृति रिसाव, प्रोग्राम क्रैश, या नाक राक्षसों का मामला शामिल हो सकता है। – KeithB

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