为什么 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 中的错误吗?
根据 MSDN,NULL
被定义为足够接近 0
的东西,以便 MSVC++ 接受。就是这样。
尝试在该代码之前执行 #undef NULL
,它应该会正确中断编译。
NULL
被指定为实现定义的 C++ 空指针常量,它是一个整型常量表达式,计算结果为零或 std::nullptr_t
类型的纯右值。因此,0
、0L
或 nullptr
都是 NULL
的有效实现。
您的 Clang 和 GCC 版本可能将其定义为 0L
或 nullptr
,而您的 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 在最新版本中修复了这个问题。
考虑以下程序:
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 中的错误吗?
根据 MSDN,NULL
被定义为足够接近 0
的东西,以便 MSVC++ 接受。就是这样。
尝试在该代码之前执行 #undef NULL
,它应该会正确中断编译。
NULL
被指定为实现定义的 C++ 空指针常量,它是一个整型常量表达式,计算结果为零或 std::nullptr_t
类型的纯右值。因此,0
、0L
或 nullptr
都是 NULL
的有效实现。
您的 Clang 和 GCC 版本可能将其定义为 0L
或 nullptr
,而您的 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 在最新版本中修复了这个问题。