2011-08-25 17 views
5

विंडोज़, मैक और आईओएस के लिए बिना किसी चेतावनी के कोड कोड का निम्नलिखित बिट:एक सदस्य फ़ंक्शन पॉइंटर की तुलना एनयूएलएल की तुलना में एक चेतावनी उत्पन्न क्यों करती है?

class MyClass { 
    SomeOtherClass * m_object; 
    void (SomeOtherClass::*m_callback)(); 
public: 
    MyClass(SomeOtherClass * _object,void (SomeOtherClass::*_callback)()=NULL) : 
     m_object(_object),m_callback(_callback) {} 

    void DoStuff() { 
     //generates warning: NULL used in arithmetic when compiling with the Android NDK 
     if (NULL==m_callback) { 
      m_object->DoNormalCallback(); 
     } else { 
      (m_object->*m_callback)(); 
     } 
    } 
}; 

यह चेतावनी क्यों उत्पन्न हुई है और मैं इसके बारे में क्या कर सकता हूं?

+0

यह 'NULL' साथ चीजों की तुलना करने के लिए अच्छा शैली के खिलाफ तुलना करने के लिए, नहीं की तुलना' NULL' वैध है चीजों के साथ। ऑर्डर स्विच करें: 'अगर (m_callback == NULL) ' –

+6

' if (0 == x) 'लिखने के लिए यह अच्छी तरह से ज्ञात चाल है ताकि यदि आप' == '' = 'के साथ भ्रमित हो जाएं, तो आप संकलन तोड़ देंगे, नहीं बस एक चेतावनी (या कुछ नहीं) प्राप्त करें। – hamstergene

+0

कुछ दिशानिर्देश गलती से असाइनमेंट से बचने के लिए तुलना के बाईं तरफ स्थिर रखने के लिए कह रहे हैं। मुझे लगता है कि यह लायक नहीं है लेकिन अन्य राय भी हैं। – Simon

उत्तर

2

मैं तुम्हें सदस्य समारोह संकेत के साथ 0 (या NULL) की तुलना करने की अनुमति हो नहीं लगता कि, खासकर जब से वे वास्तव में संकेत नहीं हो सकता है (समारोह virtual है जब, उदाहरण के लिए)।

व्यक्तिगत रूप से, मैं, बोनस अंक के लिए तुलना के बिना if परीक्षण, उदा .:

void DoStuff() { 
    if (m_callback) { 
     (m_object->*m_callback)(); 
    } else { 
     m_object->DoNormalCallback(); 
    } 
} 

पुनर्लेखन था और, निर्माता पूर्णांक इस परीक्षण प्रदर्शन करते हैं।

class MyClass { 
    SomeOtherClass * m_object; 
    void (SomeOtherClass::*m_callback)(); 
public: 
    MyClass(SomeOtherClass * _object,void (SomeOtherClass::*_callback)()=NULL) : 
     m_object(_object),m_callback(_callback) 
    { 
     // Use "DoNormalCallback" unless some other method is requested. 
     if (!m_callback) { 
      m_callback = &SomeOtherClass::DoNormalCallback; 
     } 
    } 

    void DoStuff() { 
     (m_object->*m_callback)(); 
    } 
}; 
+0

परीक्षण क्यों करें? 'NULL' की बजाय डिफ़ॉल्ट मान के रूप में बस '& SomeOtherClass :: DoNormalCallback' का उपयोग करें। – Nemo

+0

आप एक पॉइंटर-टू-सदस्य प्रकार के लिए एक शून्य सूचक स्थिरांक को परिवर्तित कर सकते हैं, वर्तमान मानक के # 4.11 देखें (सी ++ 03 के बारे में निश्चित नहीं है लेकिन यह वही होना चाहिए)। –

4

यदि NULL को ((void*)0) के रूप में परिभाषित किया गया है, तो आपको चेतावनी मिल सकती है। ऑब्जेक्ट पॉइंटर्स फ़ंक्शन पॉइंटर्स के साथ टाइप-संगत नहीं हैं। NULL के बजाय एक सादा 0 का उपयोग करें। 0 एक शून्य पॉइंटर निरंतर फ़ंक्शन पॉइंटर और ऑब्जेक्ट पॉइंटर प्रकार दोनों के साथ संगत है।

EDIT क्षमा करें, मैं उचित ध्यान नहीं दे रहा था। यहां एक सदस्य फ़ंक्शन पॉइंटर है, न केवल फ़ंक्शन पॉइंटर। ((void*)0) के साथ तुलना करने के नियमों के मुकाबले भी है, और कई कंपाइलर्स त्रुटियों जारी करेंगे, केवल चेतावनी नहीं।

संपादित 2 सब जो टिप्पणी की है: मुझे पता है कि एक अनुरूप सी ++ संकलक ((void*)0) के रूप में शून्य को परिभाषित नहीं होंगे। समस्या यह है कि वहां गैर-अनुरूप कंपिलर और टूटी हुई तीसरे पक्ष के पुस्तकालय हैं (मैंने दोनों को देखा है)।

+0

[जीसीसी वेबसाइट पर एक पृष्ठ] के अनुसार (http://gcc.gnu.org/onlinedocs/libstdc++/manual/bk01pt02ch04s03.html) यह कहता है कि 'एनयूएलएल' को जीसीसी का एक कीवर्ड '__null'' के रूप में परिभाषित किया गया है। –

+0

सी ++ में, 'न्यूल' को कभी भी परिभाषित नहीं किया जाएगा ((शून्य *) 0) '। –

+0

सी ++ 'न्यूल' में '((शून्य *) 0 के रूप में परिभाषित नहीं किया जा सकता है। यदि यह था, उपरोक्त कोड संकलित नहीं होगा। – ymett

0

if (m_callback) के रूप में आंद्रे कैरोन ने सुझाव दिया काम करता है, लेकिन मैं bools के लिए निहित डाले के एक प्रशंसक कभी नहीं गया और एक ऑपरेटर bool का आकलन करती है कि का उपयोग करना पसंद है। यह थोड़ा वर्बोज़ है, लेकिन यह काम करता है:

if (static_cast<void (SomeOtherClass::*)()>(NULL)==m_callback) 
    m_object->DoNormalCallback(); 
} else { 
    (m_object->*m_callback)(); 
} 

अभी भी सुनिश्चित नहीं है कि जीसीसी के एनडीके संस्करण को कास्ट क्यों चाहिए।

1

-Wno-conversion-null के साथ चेतावनी बंद करने का प्रयास करें।

0

सी ++ 11 से पहले, '0' के खिलाफ पॉइंटर-टू-सदस्य की तुलना करने का नतीजा अनिर्धारित है।

सी ++ 11 में, यह सूचक करने वाली सदस्य नई सी ++ 11 कीवर्ड 'nullptr'

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