Почему при сравнении указателя на функцию-член с NULL выдается предупреждение? - PullRequest
6 голосов
/ 25 августа 2011

Следующий фрагмент кода компилируется без предупреждения для Windows, Mac и iOS:

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)();
        }
    }
};

Почему генерируется это предупреждение и что я могу с этим сделать?

Ответы [ 5 ]

4 голосов
/ 25 августа 2011

Если NULL определено как ((void*)0), вы можете получить предупреждение. Указатели объектов несовместимы по типу с указателями функций. Используйте простой 0 вместо NULL. 0 - это константа нулевого указателя, совместимая как с указателем на функцию, так и с указателем на объект.

РЕДАКТИРОВАТЬ Извините, я не обращал должного внимания. Здесь указатель функции member , а не просто указатель на функцию. Сравнение с ((void*)0) также противоречит правилам, и многие компиляторы будут выдавать ошибки , а не только предупреждения.

РЕДАКТИРОВАТЬ 2 Всем, кто прокомментировал: я знаю, что соответствующий компилятор C ++ не определит NULL как ((void*)0). Проблема в том, что существуют несоответствующие компиляторы и неработающие сторонние библиотеки (я видел оба).

2 голосов
/ 25 августа 2011

Я не думаю, что вам разрешено сравнивать 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)();
    }
};
1 голос
/ 25 марта 2015

До C ++ 11 результат сравнения указателя на элемент с '0' не определен.

В C ++ 11 допустимо сравнивать указатель на элемент сновое ключевое слово C ++ 11 'nullptr'

1 голос
/ 08 декабря 2014

Попробуйте отключить предупреждение с помощью -Wno-conversion-null.

0 голосов
/ 26 августа 2011

if (m_callback), как предлагает Андре Карон, но я никогда не был фанатом неявных приведений к bool и предпочитаю использовать оператор, который оценивает bool. Это немного многословно, но это работает:

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

До сих пор не уверен, зачем нужна версия GCC для NDK.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...