2017-01-26 7 views
19

मैं अपने नवीनतम जीसीसी जी ++ compilers, (संस्करण> 6)जांच करें कि धारा संदर्भ शून्य संकलन नहीं है अब और

वहाँ एक वर्ग CodeWriter एक ostream संदर्भ चर के साथ है के साथ एक पुरानी परियोजना संकलन कर रहा हूँ।

class CodeWriter 
{ 
    //private: 
protected: 
    ostream &m_stream; 
public: 
    CodeWriter(ostream &stream):m_stream(stream){} 
    ~CodeWriter(){ 
    if(m_stream != NULL){ 
     m_stream.flush(); 
    } 
    } 
}; 

कक्षा काफी बड़ी है इसलिए मैंने केवल प्रासंगिक चर और कार्यों को शामिल किया।

जैसा कि आप देख सकते हैं कि विनाशक NULL के संदर्भ की तुलना कर रहा है। इस प्रोजेक्ट ने ठीक संकलित किया जब मैंने पुराने gnu टूलचेन के साथ इसे लंबे समय तक उपयोग किया।

लेकिन अब यह एक त्रुटि फेंक रहा है कि से ostream और long int की तुलना करने के लिए कोई मिलान नहीं है।

कोई भी बदलाव के पीछे तर्क को समझा सकता है, और मैं इसे कैसे ठीक कर सकता हूं?

मुझे अतिरिक्त जानकारी प्रदान करने में खुशी होगी/यदि आवश्यक हो तो पूरी कक्षा शामिल करें।

+9

आप कोड गलत - यह NULL के खिलाफ धारा वस्तु (जो किसी प्रकार का या किसी अन्य के एक अतिभारित ऑपरेटर लागू करेगा) तुलना करती है। शून्य संदर्भ के रूप में ऐसी कोई चीज़ नहीं है (और इसलिए, एक की जांच करना संभव नहीं है) –

+1

पुन: "मैंने केवल प्रासंगिक चर और फ़ंक्शंस को शामिल किया" हां! धन्यवाद! बिल्कुल सही! –

+2

यह भी ध्यान दें कि _pointers_ को शून्य करने के लिए तुलना करने के लिए आपको अब 'nullptr' का उपयोग C++ 11 या बाद में मैक्रो 'NULL' के बजाय करना चाहिए। (हाँ मुझे पता है कि आपके पास कोई सूचक नहीं है लेकिन मैं आपकी शून्य जांच के इरादे से बात कर रहा हूं)। –

उत्तर

32

कोड संदर्भ को स्वयं को NULL के साथ तुलना नहीं कर रहा है, लेकिन NULL के साथ संदर्भित ऑब्जेक्ट की तुलना कर रहा है। संदर्भ NULL नहीं हो सकते हैं, और NULL के साथ संदर्भ की तुलना करना असंभव है।

और

इस परियोजना मैं संकलित जब मैं यह लंबे समय से पुराने जीएनयू toolchain के साथ वापस किया करते थे।

क्योंकि व्यवहार C++ 11 के बाद बदल गया है।

से पहले सी ++ 11, std::ostream परोक्ष void* को operator void*() है, जो एक नल पॉइंटर लौटाता है यदि त्रुटि धारा पर आ गई है के माध्यम से परिवर्तित किया जा सकता है। तो कोड का मूल उद्देश्य यह जांचना है कि स्ट्रीम में कोई त्रुटि नहीं है या नहीं।

चूंकि सी ++ 11 रूपांतरण फ़ंक्शन को explicit operator bool() में बदल दिया गया था, जो त्रुटि होने पर false लौटाता है।ध्यान दें कि फ़ंक्शन को explicit के रूप में घोषित किया गया है, जिसका अर्थ है bool पर निहित रूपांतरण की अनुमति नहीं है, इसलिए कोड फिर से C++ 11 के साथ संकलित नहीं होगा क्योंकि std::ostream को bool में स्पष्ट रूप से परिवर्तित नहीं किया जा सकता है (और फिर NULL के साथ तुलना की जा सकती है (एक पूर्णांक शाब्दिक))।

एक सी ++ 11-संगत संकलक के साथ आप बस करने के लिए

if (m_stream) { 
    m_stream.flush(); 
} 

ध्यान दें कि contextual conversions के लिए भी स्पष्ट रूपांतरण कार्यों माना जाता है कोड बदल सकते हैं। ऊपर दिए गए कोड के लिए, m_streamexplicit operator bool() के माध्यम से bool में परिवर्तित हो जाएगा, तो मूल्य if की हालत के लिए इस्तेमाल किया जाएगा।

14

स्ट्रीम हमेशा एक बूलियन संदर्भ में मूल्यांकन किया जा सकता है, तो बस के लिए इसे बदल:

if (m_stream) { 
    m_stream.flush(); 
} 

सी ++ 11 explicit bool करने के लिए रूपांतरण कर दिया। यह if (!m_stream.fail()) के बराबर है। सी ++ 11 से पहले, इस शॉर्ट-हाथ की जांच void* पर एक (अंतर्निहित!) रूपांतरण प्रदान करके हासिल की गई थी, यही कारण है कि आपका पुराना कोड काम करता था। लेकिन, के रूप में @Arne ने कहा, flush ही:

कारण कोड इस के लिए जाँच कर रहा है, के बजाय सिर्फ सीधे m_stream.flush(); बुला, धारा अपवाद विफलता के लिए सक्षम हो सकता है और यह कि, फेंक सकती है [अद्यतन] कि शायद है असफल हो सकता है और फेंक भी सकता है। यदि कोई अपवाद नहीं है, तो आप केवल बूलियन चेक को पूरी तरह से छोड़ सकते हैं। [/ अपडेट]

+1

'अगर (m_stream)' बराबर if (! M_stream.fail()) '(जो' की अनुमति देता है EOF() ') है', 'अगर (m_stream.good())', हालांकि इस के लिए अप्रासंगिक है "शुद्ध नहीं "उत्पादन धाराएं क्योंकि वे' eof() 'नहीं हैं। इसके अलावा, यदि इरादा फेंकना नहीं है, तो समाधान अपर्याप्त है क्योंकि फ्लश स्वयं 'badbit' सेट हो सकता है और' badbit' के लिए अपवाद सक्षम किए जा सकते हैं। –

+0

@AneneVogel: तुम सही हो, धन्यवाद! फिक्स्ड। –

+2

मैं शर्त लगा सकता हूँ कि परीक्षण है कि क्या धारा यह निस्तब्धता से पहले वैध है के लिए कारण का परीक्षण एक सूचक को हटाने से पहले रिक्त है कि क्या के लिए कारण के रूप में ही है: "सुरक्षित" पुस्तकालय विनिर्देश समझे बिना होना चाहते हैं। –

6

धारा कक्षाएं पूर्व सी ++ 11 में आधार वर्गों में से एक में एक operator void*() था। बेशक void* मूल्य की तुलना NULL से की जा सकती है।

वर्तमान सी ++ में यह explicit operator bool() है जो if कथन के संदर्भ में काम करता है, लेकिन सामान्य अभिव्यक्ति में नहीं।

एक void* के उपयोग bool कि क्या हुआ से कुछ अवांछित रूपांतरण से बचने के लिए हम explicit ऑपरेटरों नहीं था जब था।

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