2011-08-25 48 views
5

下面的代碼位編譯沒有用於Windows,Mac和iOS警告:爲什麼將成員函數指針與NULL比較會生成警告?

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'與事物。切換順序:'if(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(); 
    } 
} 

而且,對於加分,INT構造函數執行此測試。

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

爲什麼要進行測試呢?只需使用'&SomeOtherClass :: DoNormalCallback'作爲默認值而不是'NULL'。 – Nemo

+0

您可以將空指針常量轉換爲指向成員類型的指針,請參閱當前標準的#4.11(不確定C++ 03,但它應該與此相同)。 –

4

如果NULL定義爲((void*)0),您可能會收到警告。對象指針與函數指針不是類型兼容的。使用普通的0而不是NULL0是一個兼容函數指針和對象指針類型的空指針常量。

編輯對不起,我沒有給予適當的關注。這裏有一個成員函數指針,不只是一個函數指針。與((void*)0)比較也違反規則,許多編譯器會在此發出錯誤,而不僅僅是警告。

編輯2致所有人評論:我知道符合C++編譯器不會將NULL定義爲((void*)0)。問題是有不合格的編譯器和破碎的第三方庫(我見過)。

+0

根據[海灣合作委員會網站上的一個頁面](http://gcc.gnu.org/onlinedocs/libstdc++/manual/bk01pt02ch04s03.html),它說'NULL'被定義爲'__null',一個關鍵字gcc。 –

+0

在C++中,'NULL'永遠不會被定義爲'((void *)0)'。 –

+0

在C++中'NULL'不能被定義爲'((void *)0)'。如果是這樣,上面的代碼將不會編譯。 – ymett

0

if (m_callback)由安德烈·卡倫所建議的工作,但我從來沒有隱式轉換的風扇的bool和喜歡使用計算結果爲bool的操作。這有點冗長,但是這個工作:

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

仍然不知道爲什麼NDK版本的GCC需要演員。

1

嘗試關閉-Wno-conversion-null的警告。

0

在C++ 11之前,比較指向成員的指針對'0'的結果是未定義的。

在C++ 11,它是合法的,比較指針到成員反對新的C++ 11的關鍵字「nullptr」