为什么 MSVS 允许 NULL 作为纯虚函数说明符?

why MSVS allows NULL as pure virtual function specifier?

考虑以下程序:

struct Test
{
    virtual void foo()=NULL;
};
int main()
{ }

g++ 4.8.1 给出如下预期错误:

[Error] invalid pure specifier (only '= 0' is allowed) before ';' token

Clang 给出以下错误:

error: initializer on function does not look like a pure-specifier

但是当我在 MSVS 2010 上尝试它时,它编译并运行良好。我认为 g++ & clang 在这种情况下是正确的。标准对此有何规定?我也使用 \Za 命令行选项禁用了编译器扩展,但 MSVS 仍然接受该代码。为什么它没有给出任何错误?

我也在在线 VC++ 编译器 here 上试过了,最后更新时间是 2015 年 7 月 8 日。这真的是 MSVS 2010 和 2015 中的错误吗?

根据 MSDNNULL 被定义为足够接近 0 的东西,以便 MSVC++ 接受。就是这样。

尝试在该代码之前执行 #undef NULL,它应该会正确中断编译。

NULL 被指定为实现定义的 C++ 空指针常量,它是一个整型常量表达式,计算结果为零或 std::nullptr_t 类型的纯右值。因此,00Lnullptr 都是 NULL 的有效实现。

您的 Clang 和 GCC 版本可能将其定义为 0Lnullptr,而您的 MSVC 版本将其定义为 0。在这种情况下,预处理器会将 NULL 替换为 0,从而使您的程序合式。

9.2 Class members 部分的语法如下:

[...]
member-declarator:
 declarator virt-specifier-seqopt pure-specifieropt
[...]
pure-specifier:
  = 0
  ^^^

所以纯说明符必须是文字 0。对于 MSVC,最有可能的 NULL 被定义为 0 但它不必被定义为 0,另一种可能性是 0L,这是语法不允许的,这是可能是 gcc 和 clang 使用的。

我们可以从 18.2 部分看到这一点:

The macro NULL is an implementation-defined C++ null pointer constant in this International Standard 194

脚注说:

Possible definitions include 0 and 0L, but not (void*)0.

部分 4.10 说:

A null pointer constant is an integer literal (2.14.2) with value zero

这排除了 (void*)0.

早期版本的 clang 和 MSVC accepted other integer literals 但看起来 clang 在最新版本中修复了这个问题。