41

在 C++98 中,空指针由字面量表示0(或者实际上是任何值为 0 的常量表达式)。在 C++11 中,我们更喜欢nullptr。但这不适用于纯虚函数:

struct X
{
    virtual void foo() = nullptr;
};

为什么这不起作用?这不是完全有道理吗?这仅仅是一个疏忽吗?会修复吗?

4

8 回答 8

46

因为语法说0,不是表达式或其他一些非终端匹配nullptr

因为0一直都有效。Even0L格式不正确,因为它与语法不匹配。

编辑

Clang 允许= 0x0,= 0b0= 00(31.12.2013)。这是不正确的,当然应该在编译器中修复。

于 2013-12-31T17:52:31.423 回答
30

函数的= 0符号virtual并不是字面上的“赋值 null”,而是一种实际上具有欺骗性的特殊符号:也可以实现纯虚函数。

abstract使用各种上下文关键字,允许而不是= nullptr成为上下文关键字会更有意义abstract

于 2013-12-31T17:54:10.587 回答
17

语法就是这样定义的,如果我们看一下C++标准草案9.2 Class members,相关语法如下:

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

语法特别指出纯说明符= 0而不是整数文字表达式,这似乎没有留下任何回旋余地。如果我尝试这样的事情:

virtual void foo() = 0L;

或者:

virtual void foo() = NULL ;

gcc告诉我:

错误:';'之前的纯说明符无效(只允许'= 0')令牌

clang说:

错误:函数的初始化器看起来不像纯说明符

尽管以下内容在两者中都有效:

#define bar 0
//...
virtual void foo() = bar;

似乎也clang允许八进制文字、十六进制文字二进制文字零,这是不正确的行为。

更新

显然Visual Studio接受NULL和任何零整数文字,包括0L,等......虽然它不接受.0x000nullptr

于 2013-12-31T17:57:10.380 回答
10

= 0那里有固定的含义。它不是真正的整数零。因此,您不能像那样简单地替换它。

于 2013-12-31T17:52:54.597 回答
6

= 0语法不用于初始化指针,它只是在语法上表明提供的virtual是纯的。

因此= 0,声明 pure virtuals 的语法没有改变。

于 2013-12-31T17:53:17.647 回答
6

的全部nullptr(或无论如何大部分)是只能分配给(或用于初始化)指针。

在这种情况下,您没有初始化或分配给指针,因此在这种情况下您能够使用它甚至没有意义。

于 2013-12-31T17:56:58.800 回答
2

这并不意味着它是一个指针,或者它必须等于nullptr.

= 0是足够的并且意味着虚函数是纯的。

于 2013-12-31T18:08:03.200 回答
1

C++11 语法只允许0在这里(并不意味着指针)。nullptr不是0,它失败了。NULL仅在NULL定义为时才有效0(有时是这种情况,但并非总是如此)。只需0在此处使用,或使用以下定义(如果您真的想使用空值,当它不是指针时)。

#define VIRTUAL_NULL 0
struct X
{
    virtual void foo() = VIRTUAL_NULL;
};
于 2013-12-31T20:04:57.460 回答