我们总是将纯虚函数声明为:
virtual void fun () = 0 ;
即,它总是被赋值为0。
我的理解是,这是将此函数的vtable条目初始化为NULL,此处的任何其他值都会导致编译时错误。这种理解是否正确?
答案 0 :(得分:157)
使用=0
的原因是Bjarne Stroustrup不认为他可以获得另一个关键字,例如在实现该功能时通过C ++社区的“纯粹”。这在他的书The Design & Evolution of C++,第13.2.3节:
选择了好奇的= 0语法...... 因为当时我没有看到任何机会 获得新关键字。
他还明确指出,这不需要将vtable条目设置为NULL,这样做并不是实现纯虚函数的最佳方法。
答案 1 :(得分:76)
与大多数关于C ++设计的“为什么”问题一样,首先要看的是 C ++的设计和演变,作者:Bjarne Stroustrup 1 :
选择了好奇的
=0
语法 在明显的替代方案 引入新关键字pure
或abstract
因为在我看到的时候 没有机会获得新的关键字 公认。如果我建议pure
, 版本2.0将没有发货 抽象类。给出了一个选择 在更好的语法和抽象之间 我选择了抽象类。 而不是冒险延迟和 引发某些争斗pure
,我使用了传统的C和C ++ 使用0表示的惯例 “不在那里。”=0
语法符合 我认为一个功能体是 函数的初始化器也用 (简单但通常足够) 视图的虚拟功能集 被实现为一个向量 函数指针。 [...]
1 §13.2.3语法
答案 2 :(得分:29)
C ++标准的9.2节给出了类成员的语法。它包括这个产品:
pure-specifier:
= 0
价值没什么特别之处。 “= 0”只是说“此函数是纯虚拟”的语法。它与初始化或空指针或数值零无关,尽管与这些事物的相似性可能具有助记值。
答案 3 :(得分:19)
我不确定这背后是否有任何意义。它只是语言的语法。
答案 4 :(得分:15)
C ++总是避免引入新的关键词,因为新的保留词会破坏使用这些词作为标识符的旧程序。它通常被视为语言的优势之一,它尽可能地尊重旧代码。
可能确实选择了= 0
语法,因为它类似于将vtable条目设置为0
,但这纯粹是象征性的。 (大多数编译器将这样的vtable条目分配给存根,该存根在中止程序之前发出错误。)语法主要被选择,因为它之前没有用于任何东西,它保存了引入新关键字。
答案 5 :(得分:11)
C ++必须有办法区分纯虚函数和普通虚函数的声明。他们选择使用= 0
语法。他们可以通过添加纯关键字轻松完成相同的操作。但是C ++非常不愿意添加新的关键字,而更喜欢使用其他机制来引入功能。
答案 6 :(得分:7)
在这种情况下,没有任何东西被“初始化”或“分配”为零。 = 0
只是一个由=
和0
令牌组成的句法结构,与初始化或赋值完全无关。
它与“vtable”中的任何实际值无关。 C ++语言没有“vtable”或类似的任何概念。各种“vtable”只不过是具体实现的细节。
答案 7 :(得分:3)
我记得读过这个有趣语法的理由是,它比引入另一个可以做同样事情的关键字更容易(在标准接受方面)。
我相信Bjarne Stroustrup在C ++的设计和演变中提到了这一点。
答案 8 :(得分:2)
我认为这只是C ++语法的一部分。我认为对于给定的特定二进制格式,编译器如何实际实现这一点并不存在任何限制。你可能认为早期的C ++编译器是正确的。
答案 9 :(得分:2)
= 0
声明纯虚函数。
可以理解的是,这是将此函数的vtable条目初始化为NULL,此处的任何其他值都会导致编译时错误
我认为这不是真的。这只是特殊的语法。 vtable是实现定义的。没有人说纯粹成员的vtable条目必须在构造时实际归零(尽管大多数编译器处理类似的vtable)。
答案 10 :(得分:1)
那么,您也可以初始化vtable条目以指向实际的函数“
virtual void fun()
{
//dostuff()
}
直观地说,vtable条目可以定义为指向任何地方(0)或函数。让你为它指定自己的值可能会导致它指向垃圾而不是函数。但这就是为什么“= 0”被允许而“= 1”不被允许的原因。我怀疑Neil Butterworth对于为什么“= 0”被使用是正确的