【问题标题】:Why does comparing a member function pointer to NULL generate a warning?为什么将成员函数指针与 NULL 进行比较会产生警告?
【发布时间】:2011-08-25 14:38:23
【问题描述】:

以下代码在 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)();
        }
    }
};

为什么会生成该警告,我该怎么办?

【问题讨论】:

  • 将事物与NULL 进行比较是一种很好的风格,而不是将NULL 与事物进行比较。切换顺序:if (m_callback == NULL)
  • 编写if (0==x) 是众所周知的技巧,因此如果您将=== 混淆,您将破坏编译,而不仅仅是收到警告(或什么都没有)。
  • 一些指导方针说将常量放在比较的左侧以避免错误分配。我认为它不值得,但还有其他意见。
  • @Seth 将其更改为 if (m_callback==NULL) 仍然会产生警告,我只是列出了我通常编写的代码。
  • 我发现 if (0==x) 的技巧非常丑陋,但它是完全有效的代码,我不知道有任何编译器会警告它。

标签: c++ android-ndk


【解决方案1】:

如果NULL 定义为((void*)0),您可能会收到警告。对象指针与函数指针类型不兼容。使用普通的0 而不是NULL0 是一个空指针常量,兼容函数指针和对象指针类型。

编辑对不起,我没有注意。这里有一个 member 函数指针,而不仅仅是一个函数指针。与((void*)0) 比较也是违反规则的,许多编译器会发出错误,而不仅仅是警告。

编辑 2 致所有评论的人:我知道符合标准的 C++ 编译器不会将 NULL 定义为 ((void*)0)。问题是那里有不合格的编译器和损坏的第三方库(我都见过)。

【讨论】:

  • 根据a page on the gcc website它说NULL被定义为__null,一个gcc的关键字。
  • 在 C++ 中,NULL 永远不会被定义为 ((void*)0)
  • 在 C++ 中,NULL 不能定义为 ((void*)0)。如果是这样,上面的代码将无法编译。
【解决方案2】:

我认为您不允许将 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)();
    }
};

【讨论】:

  • 为什么要进行测试?只需使用&SomeOtherClass::DoNormalCallback 作为默认值,而不是NULL
  • 您可以将空指针常量转换为指向成员的类型,请参阅当前标准的#4.11(不确定 C++03,但那里应该是一样的)。跨度>
【解决方案3】:

尝试使用-Wno-conversion-null 关闭警告。

【讨论】:

    【解决方案4】:

    if (m_callback) 正如 André Caron 所建议的那样工作,但我从来都不喜欢隐式转换为 bool,而是更喜欢使用计算结果为 bool 的运算符。这有点冗长,但这有效:

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

    仍然不确定为什么 GCC 的 NDK 版本需要演员表。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2018-07-07
      • 1970-01-01
      • 2012-10-14
      • 1970-01-01
      • 1970-01-01
      • 2013-07-05
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多