2011-08-25 49 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”