开发者

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.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜