Why does comparing a member function pointer to NULL generate a warning?
The following bit of code compiles without warning for Windows, Mac and iOS:
class MyClass {
SomeOtherClass * m_object;
void (SomeOtherClass::*m_callback)();
public:
MyClass(SomeOtherClass * _object,void (SomeOtherClass::*_callback)()=NULL) :
m_object(_object开发者_C百科),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)();
}
}
};
Why is that warning generated and what can I do about it?
If NULL
is defined as ((void*)0)
, you may get a warning. Object pointers are not type-compatible with function pointers. Use a plain 0
instead of NULL
. 0
is a null pointer constant compatible with both function pointer and object pointer types.
EDIT Sorry, I was not paying proper attention. There's a member function pointer here, not just a function pointer. Comparing one with ((void*)0)
is also against the rules, and many compilers will issue errors, not just warnings, on this.
EDIT 2 To all who commented: I know that a conforming C++ compiler will not define NULL as ((void*)0)
. The problem is that there are non-conforming compilers and broken third-party libraries out there (I've seen both).
I don't think you're allowed to compare 0
(or NULL
) with member function pointers, especially since they might not be actually pointers (when the function is virtual
, for instance).
Personally, I'd rewrite the if
test without the comparison, e.g.:
void DoStuff() {
if (m_callback) {
(m_object->*m_callback)();
} else {
m_object->DoNormalCallback();
}
}
And, for bonus points, perform this test int the constructor.
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)();
}
};
Try turning off the warning with -Wno-conversion-null
.
if (m_callback)
as suggested by André Caron works, but I've never been a fan of implicit casts to bools and prefer to use an operator that evaluates to bool. It's a bit verbose, but this works:
if (static_cast<void (SomeOtherClass::*)()>(NULL)==m_callback)
m_object->DoNormalCallback();
} else {
(m_object->*m_callback)();
}
Still not sure why the NDK version of GCC needs the cast.
精彩评论