C++ C+中的纯虚函数+;11
在C++98中,空指针由文本C++ C+中的纯虚函数+;11,c++,c++11,virtual,pure-virtual,nullptr,C++,C++11,Virtual,Pure Virtual,Nullptr,在C++98中,空指针由文本0(或者实际上是任何值为零的常量表达式)表示。在C++11中,我们更喜欢nullptr。但这不适用于纯虚拟函数: struct X { virtual void foo() = nullptr; }; 为什么这不起作用?这不完全有意义吗?这仅仅是一种疏忽吗?它会被修复吗?因为语法说的是0,而不是表达式或其他一些非终端匹配nullptr 一直以来,只有0有效。即使是0L也将是格式错误的,因为它与语法不匹配 编辑 叮当声允许=0x0,=0b0和=00(31.12
0
(或者实际上是任何值为零的常量表达式)表示。在C++11中,我们更喜欢nullptr
。但这不适用于纯虚拟函数:
struct X
{
virtual void foo() = nullptr;
};
为什么这不起作用?这不完全有意义吗?这仅仅是一种疏忽吗?它会被修复吗?因为语法说的是
0
,而不是表达式或其他一些非终端匹配nullptr
一直以来,只有0
有效。即使是0L
也将是格式错误的,因为它与语法不匹配
编辑
叮当声允许
=0x0
,=0b0
和=00
(31.12.2013)。这是不正确的,当然应该在编译器中修复。=0
在这里有固定的含义。这里不是一个整数。因此,您不能简单地这样替换它。没有使用=0
语法来初始化指针,它只是从语法上指示所提供的virtual
是纯的
因此,用于声明纯
virtual
s的=0
语法保持不变。用于virtual
函数的=0
符号并不是字面上的“assign null”,而是一种实际上具有欺骗性的特殊符号:也可以实现纯虚拟函数
对于各种上下文关键字,允许
abstract
而不是=nullptr
,并将abstract
作为上下文关键字将更有意义。nullptr的全部要点(或大部分要点)是只能分配给(或用于初始化)指针
在这种情况下,您没有初始化或分配指针,因此在这种情况下您甚至无法使用它。语法就是这样定义的,如果我们查看
9.2
类成员一节,相关语法如下所示:
[...]
member-declarator:
declarator virt-specifier-seqopt pure-specifieropt
[...]
pure-specifier:
= 0
^^^
语法明确指出纯说明符是=0
,而不是整数文本或表达式,这似乎没有留下任何回旋余地。如果我尝试以下事情:
virtual void foo() = 0L;
或:
gcc
告诉我:
错误:“;”之前的纯说明符无效(只允许“=0”)代币
而且,clang
说:
错误:函数上的初始值设定项看起来不像纯说明符
尽管以下两种方法都适用:
#define bar 0
//...
virtual void foo() = bar;
似乎clang
允许八进制文字、十六进制文字和二进制文字为零,这是不正确的行为
更新
显然
Visual Studio
接受NULL
和任何零整数文本,包括0L
,0x0
,00
等。。。尽管它不接受nullptr
,但这并不意味着它是一个指针,或者它必须等于nullptr
=0
就足够了,这意味着虚拟函数是纯函数 C++11语法在这里只允许0
(它并不意味着指针)。由于nullptr
不是0
,它会失败NULL
仅在NULL
定义为0
时才起作用(有时是这样,但并不总是这样)。只需在此处使用0
,或者使用以下定义(如果您真的想使用空值,而不是指针)
老实说,即使=0有效,我还是希望
=nullptr
或=abstract
语法更好。@TemplateRex:只有NULL
被定义为单字符文字0
@stefan:很少是这样,例如一个常见的定义是(void*)C.@ MattheUM中的0 < /COD>:在C++ <代码> null <代码>必须是整数整数0,<代码>(空隙*)0 < /C> >(如C中)是不允许的。@ ZAC右,因为宏被编译器获得的时间所取代。这里用词不当(尽管已经解释过语法必须是=0
)是因为人们将NULL
与0
相关联。有人应该复制他的话:“…vtable不是语言要求,只是虚拟方法的一个实现选项…不同的实现(即,没有vtable,没有任何元素存在0)”@Nye感谢您的评论,这样我就可以消除误解了。我告诉他语法上应该是“=0”。我特别没有说“因为事情就是这样”,因为我自己会否决这些答案。为什么不呢?函数通常降级为函数指针,所以我不明白为什么这种语法没有意义。当时他们只是没有可用的nullptr
关键字。@user2345215:因为=0
在这个上下文中并不意味着“将null分配给这个指针”,它的意思完全不同。它并不是字面上的意思。但我认为这还是有道理的。它会将函数的地址设置为零指针(如果您真的可以修改它的话),就好像函数什么地方都没有带您一样。但这就是纯虚拟函数的要点。@user2345215:但这不一定是真的。正如Dietmar已经指出的,您可以将函数设为纯虚拟并实现该函数,在这种情况下,vtable中的插槽将包含实际函数的地址。@user2345215:您只知道将在某个位置分配空指针(Jerry指出的情况除外)因为您熟悉平台的虚拟现实实现。C++标准并不规定VTBL必须使用,或者任何关于虚拟如何实现的东西——只有影响应该是什么。通过合并nullptr
来表示pure
,标准将隐含地承认平台细节。@ECrownofFire:我认为GCC 4.8在诊断消息方面有了很大改进。FWIW,我们得到=0#define bar 0
//...
virtual void foo() = bar;
#define VIRTUAL_NULL 0
struct X
{
virtual void foo() = VIRTUAL_NULL;
};