为什么纯虚函数初始化为0?

我们总是将一个纯虚函数声明为:

virtual void fun () = 0 ;

也就是说,它总是被赋值为0。

我的理解是,这是为了将这个函数的 vtable 条目初始化为 NULL,这里的任何其他值都会导致编译时错误。这种理解是否正确?

56853 次浏览

我不确定这背后是否有任何意义,这只是语言的语法。

我假设这只是 C + + 语法的一部分。我认为对于编译器实际上如何为给定的特定二进制格式实现这一点没有任何限制。您的假设对于早期的 C + + 编译器可能是正确的。

C + + 必须有办法区分纯虚函数和普通虚函数的声明。他们选择使用 = 0语法。他们可以通过添加一个纯关键字轻松地完成同样的操作。但是 C + + 非常不愿意添加新的关键字,并且更愿意使用其他机制来引入特性。

在这种情况下,没有“初始化”或“分配”零。= 0只是一个由 =0令牌组成的语法结构,它与初始化或赋值完全没有关系。

它与“ vtable”中的任何实际值都没有关系。C + + 语言没有“ vtable”之类的概念。各种“ vtables”只不过是特定实现的细节。

使用 =0的原因是,比雅尼·斯特劳斯特鲁普认为他不可能得到另一个关键字,比如在实现这个功能时,“纯粹”已经超过了 C + + 社区。这在他的书 C + + 的设计与演进第13.2.3节中有描述:

选择了奇怪的 = 0语法..。 因为当时我觉得 接受一个新的关键字。

他还明确指出,这不需要将 vtable 条目设置为 NULL,这样做并不是实现纯虚函数的最佳方式。

我记得曾经读到过,这种有趣语法的理由是,它比引入另一个关键字来做同样的事情更容易(就标准接受程度而言)。

我相信这个比雅尼·斯特劳斯特鲁普在《 C + + 的设计与发展》一书中已经提到过了。

= 0声明一个 纯虚拟函数纯虚拟函数

我们理解的是,这是为了将这个函数的 vtable 条目初始化为 NULL,这里的任何其他值都会导致编译时错误

我不这么认为。只是特殊的语法。Vtable 是实现定义的。没有人说纯成员的 vtable 条目必须在构造时实际上归零(尽管大多数编译器处理 vtables 时都是类似的)。

你也可以初始化 vtable 条目来指向一个实际的函数

 virtual void fun()
{
//dostuff()
}

似乎直观的是,vtable 条目可以定义为指向某个位置(0)或指向一个函数。让您为它指定自己的值可能会导致它指向垃圾而不是函数。但这就是允许“ = 0”而不允许“ = 1”的原因。我怀疑 Neil Butterworth 关于为什么使用“ = 0”的说法是正确的

C + + 标准的9.2部分给出了类成员的语法,包括以下产品:

pure-specifier:
= 0

这种价值没有什么特别之处。”“ = 0”只是表示“这个函数是纯虚函数”的语法它与初始化、空指针或数值0没有任何关系,尽管与这些东西的相似性可能有助记忆的价值。

C + + 总是回避引入新的关键字,因为新的保留字打破了使用这些字作为标识符的旧程序。尽可能尊重旧代码通常被视为该语言的优势之一。

= 0语法可能确实被选中了,因为它类似于将 vtable 条目设置为 0,但这纯粹是符号性的。(大多数编译器将这样的 vtable 条目分配给存根,存根在中止程序之前会发出错误。)之所以选择这种语法,主要是因为它以前没有用到任何东西,而且它节省了引入新关键字的时间。

和大多数关于 C + + 设计的“为什么”问题一样,首先要看的是 C + + 的设计与演进,作者: Bjarne Stroustrup1:

选择了奇特的 =0语法 明显的替代选择 引入一个新的关键字 pure或 因为当时我看到 不可能得到新的关键字 接受。如果我建议 pure, 发行版2.0可能没有 抽象类,给你一个选择 在更好的语法和抽象之间 类,我选择了抽象类。 而不是冒险拖延时间 引起某些争斗 pure,我使用了传统的 C 和 C + + 使用0表示的约定 “ not there.”=0语法符合 我认为函数体是 函数的初始值设定项 (过于简单,但通常足够) 虚函数集的视图 作为病媒推行 函数指针

1 13.2.3语法