2012-10-21 10 views
12

मुझे निम्न त्रुटि मिल रही है जब मैं किसी तृतीय-पक्ष SDK से कुछ कोड संकलित करने का प्रयास करता हूं।कोई पॉलिमॉर्फिक क्लास प्रकार की ऑब्जेक्ट को कैसे हटाएं जिसमें कोई आभासी विनाशक नहीं है

*Description Resource Path Location Type 
deleting object of polymorphic class type ‘Vendor_sys::VendorCode’ which has non-virtual destructor might cause undefined behaviour [-Werror=delete-non-virtual-dtor] PnServer.cpp /PCounter line 467 C/C++ Problem* 

मैं अपनी यदि संभव हो तो जहां भारी उठाने के सबसे एक dll या लायब्रेरी वस्तु में किया जाता है विक्रेता के एसडीके का केवल आंशिक ज्ञान, के साथ इस शर्त को पूरा करने के पता नहीं है।

मेरा निर्माण पर्यावरण ग्रहण जूनो जीपीपी के साथ है।

मैंने त्रुटि संदेश के लिए Google में खोज की और इस त्रुटि के कोई भी उदाहरण नहीं मिला।

तो, अगर मैं विक्रेता कोड के काले बॉक्स हिस्से को संशोधित नहीं कर सकता, तो मेरे विकल्प क्या हैं?

delete pData->unit; 
+2

तो कक्षा को विरासत में मिलाया जाना है, लेकिन वर्चुअल विनाशक नहीं है? मैं शिकायत करता हूं कि जिसने पुस्तकालय बनाया है। – chris

+1

चेतावनी थोड़ा हल्का है। किसी व्युत्पन्न प्रकार के ऑब्जेक्ट को किसी मूल प्रकार से एक पॉइंटर के माध्यम से हटाना जिसमें वर्चुअल विनाशक परिणाम अनिर्धारित व्यवहार में नहीं हैं। इसके बारे में कोई "शायद" नहीं। –

+0

@PeteBecker कम से कम g ++ 4.8 इस चेतावनी को जारी करता है, भले ही मैं व्युत्पन्न कक्षा में एक सूचक के माध्यम से हटा देता हूं। यह सुरक्षित होगा (AFAIK), इसलिए "शायद" यहां भी गलत है (चेतावनी बिल्कुल उत्पन्न नहीं की जानी चाहिए)। मुझे लगता है कि जी ++ दो मामलों में अंतर नहीं कर सकता है। – sstn

उत्तर

-2

असल में, मैंने संकलन से वायरर स्विच हटा दिया और कार्यक्रम संकलित किया।

अब, संदेश केवल चेतावनियां हैं।

मैं विक्रेता को एक बग रिपोर्ट भेजूंगा।

+1

मेरे अनुसार सही तरीका नहीं है, आपको बस अपने संकलन झंडे को नहीं बदलना चाहिए ताकि आपका कोड संकलित न हो जब तक कि कोई अन्य तरीका न हो – spt025

6

खैर यह तीसरे पक्ष के SDK में एक बग है:

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

इसके आस-पास एक तरीका आधार पर पॉइंटर्स को हटाना नहीं है। इसके बजाय, व्युत्पन्न वर्ग में पॉइंटर प्राप्त करने के लिए गतिशील_कास्ट का उपयोग करें (यदि उस आधार से प्राप्त कई वर्ग हैं तो यह असुविधाजनक हो सकता है)।

2

यह चेतावनी तब उत्पन्न होती है जब बेस क्लास में वर्चुअल सदस्य फ़ंक्शन होते हैं लेकिन कोई वर्चुअल डॉटर नहीं होता है। यह एक बग है। यदि आपके पास कोड नहीं है, तो यह सुनिश्चित करने के अलावा आप कुछ भी नहीं कर सकते हैं कि आप अपने उप-वर्ग में किसी भी संसाधन को मैन्युअल रूप से डी-आवंटित कर रहे हैं। एक कस्टम cleanup() सदस्य फ़ंक्शन की तरह आप ऑब्जेक्ट को हटाने से पहले मैन्युअल रूप से कॉल करना सुनिश्चित करते हैं।

एक और विकल्प static_cast सही वर्ग पर है। ध्यान दें कि dynamic_cast (जो रनटाइम ओवरहेड लेता है और आरटीटीआई की आवश्यकता होती है) की आवश्यकता नहीं है। कंपाइलर इस मामले में संकलन समय पर बस रिश्ते को ठीक कर सकता है।

बेशक, यदि ऑब्जेक्ट कहीं और हटा दिया गया है जो आपके कोड का हिस्सा नहीं है, तो आप भाग्य से बाहर हैं। उस स्थिति में, सुनिश्चित करें कि आपका सबक्लास कुछ भी आवंटित नहीं करता है। इस तरह विनाशक को बुलाया जाने पर भी रिसाव करना संभव नहीं है।

+1

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

+3

@PeteBecker GCC चेतावनी नहीं देता है जब कोई वर्चुअल फ़ंक्शन नहीं होता है। समस्या अभी भी है, लेकिन कोई चेतावनी नहीं है। 2011 मानक से पहले सी ++ में 'अंतिम' कीवर्ड नहीं था, इसलिए यह माना जाता है कि वर्चुअल फ़ंक्शंस के बिना कक्षाएं विरासत में नहीं मिलती हैं। अगर ऐसा होता तो वह ओपी गलती होगी। इस मामले में, यह एसडीके की गलती है। बस इस ओर ध्यान दिलाना चाहता था। –

+0

"यह माना जाता है" अस्पष्टता का एक बड़ा सौदा छुपाता है। सी ++ मानक में कई कक्षाएं हैं जिनमें वर्चुअल फ़ंक्शंस नहीं हैं लेकिन इन्हें बेस क्लास के रूप में उपयोग करने का इरादा है। उदाहरण के लिए, टेम्पलेट क्लास 'iterator', अपने व्युत्पन्न प्रकारों के लिए कुछ प्रकार के टाइपपीफ प्रदान करता है। यह तब तक कोई समस्या नहीं है जब तक आप व्युत्पन्नकर्ता के लिए पॉइंटर के माध्यम से व्युत्पन्न प्रकार की ऑब्जेक्ट को हटाने का प्रयास न करें। कुछ चेतावनियां एक कंपाइलर लेखक की धारणा के बारे में हैं कि मैं ऐसी भाषा सुविधा का उपयोग करने के लिए पर्याप्त स्मार्ट नहीं हूं जो अच्छी तरह से परिभाषित और स्पष्ट रूप से सार्थक है। –

8

बुरी खबर, मुझे डर है। आपको उस वर्ग को बेस क्लास के रूप में उपयोग नहीं करना चाहिए। बहुत अधिक बाधाएं और नुकसान। आप इससे दूर हो सकते हैं, लेकिन इसका जोखिम क्यों है? लाइब्रेरी विक्रेता के साथ एक बग रिपोर्ट दर्ज करें।

यदि आपको पॉलिमॉर्फिक पॉइंटर्स की आवश्यकता नहीं है, तो उस श्रेणी के उस ऑब्जेक्ट को अपनी कक्षा में शामिल करें, और उस सदस्य फ़ंक्शंस को शामिल करें जिसे आप उत्तराधिकारी बनाना चाहते हैं।

class my_class { 
private: 
    evil_class evil; 
public: 
    virtual ~my_class() {/* stuff */} 
    virtual int member() { return evil.member(); } 
}; 
+0

ऐसा करने का सही तरीका, इसे उत्तर – spt025

2

आप सुरक्षित रूप से, आधार वर्ग के लिए सूचक उपयोग नहीं कर सकते जब तक कि यह एक आभासी नाशक आधार वर्ग को घोषित किया है। चूंकि यह एक विक्रेता पुस्तकालय है, इसलिए आप आवश्यक वर्चुअल विनाशक को जोड़ नहीं सकते हैं।

यदि लाइब्रेरी स्वयं इस ऑब्जेक्ट के उप-वर्ग नहीं बनाती है, तो आप इस ऑब्जेक्ट के लिए सबक्लास घोषित करके उस प्रभाव को प्राप्त करने में सक्षम हो सकते हैं और उस ऑब्जेक्ट को बेस क्लास के रूप में उपयोग कर सकते हैं।

class NotGoodBase { 
~NotGoodBase(); // Non-virtual destructor. Possibly added by compiler. 
}; 

class UseThisAsBase : public NotGoodBase { 
virtual ~UseThisAsBase(); // Virtual destructor. 
}; 

आप कहीं भी प्रकार UseThisAsBase के संकेत का उपयोग करने के NotGoodBase इस्तेमाल कर सकते हैं कि, स्थानों को छोड़कर, जहां आप इस तरह के एक काम के रूप में प्रकार NotGoodBase की lvalue की आवश्यकता है या जब संदर्भ द्वारा एक चर गुजर सक्षम होना चाहिए।

+2

के रूप में चिह्नित किया जाना चाहिए वास्तव में, वह हेडर फ़ाइल में वर्चुअल विनाशक को जोड़ने में सक्षम हो सकता है। हैक, हैक, क्लाउज। इस पर निर्भर करता है कि कोई वहां घोषित किया गया है लेकिन वहां परिभाषित नहीं किया गया है। –

0

इस परिदृश्य में आपको यहां से संकलन ध्वज को हटाने के बजाय अपनी कक्षा में वर्चुअल विनाशक जोड़ने की आवश्यकता है।

उदाहरण के लिए। वर्ग Myclass के लिए इस त्रुटि तो आ रहा है जोड़ने

virtual ~Myclass(){} 

इस soultion की कोशिश करें, यह ठीक काम करेंगे।

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