为什么需要虚拟关键字?

5
换句话说,为什么编译器不能“知道”如果在派生类中更改了函数的定义,并且指向该派生类的动态分配内存的指针调用了更改后的函数,则应调用该特定函数而不是基类的函数?
在哪些情况下,没有使用virtual关键字对程序员有利?

4
不使用virtual的好处是什么?没有额外开销! - Mark Garcia
我不确定是否有确切的答案,但任何虚拟关键字的存在意味着在运行时将建立一个虚拟指针表,这可能会对性能产生一些小的影响。 - ScoPi
http://en.wikipedia.org/wiki/Virtual_method_table - Hans Passant
1
注意:在堆栈上分配的派生类仍将正常调用“虚拟”函数,动态或自动分配是与动态分派无关的概念。 - Matthieu M.
4个回答

6
"virtual"关键字告诉编译器实现动态分派。这就是语言设计的方式。 如果没有这个关键字,编译器就不知道是否要实现动态分派。
虚拟或动态分派的缺点在于: - 它有轻微的性能惩罚。大多数编译器会使用vtable和vptr机制来实现动态分派,在动态分派的情况下需要额外的间接寻址才能决定调用哪个适当的函数。 - 它使你的类非POD。

3
与非虚拟函数相比,虚拟函数有一定的“开销”,这类似于二分查找比快速排序更快。但这种比较是没有意义的,因为它们做不同的事情。如果你需要动态分派,你可以使用虚拟函数,或者你可以实现自己的动态分派机制,这将与虚拟函数一样“慢”。 - fredoverflow
@FredOverflow:我同意这个观点,因地制宜。如果你需要动态分派功能,相比于普通的静态绑定函数,你需要为此付出一些性能代价。同意,这有点像比较苹果和梨。 - Alok Save
顺便说一下,我更喜欢苹果 ;) - fredoverflow

2

一个原因:

考虑基类位于不同模块(如库)中,而派生类则位于您的应用程序中。

编译器在编译库时如何知道给定函数是/必须是虚拟的呢?


我认为这是最符合OP问题的答案。编译器无法在编译类时“猜测”方法是否会被“虚拟”使用。 - Matthieu M.

2
C++的主要设计原则之一是“零开销原则”,即不会为未使用的功能产生额外的开销。这是因为它注重高性能。
这就是为什么在C++中需要选择使用虚函数等功能,而在Java等语言中,默认情况下函数是虚拟的。

0
编译器不知道,因为它无法知道。也许你的意图是不使用虚函数,因为每个功能都会带来一定的成本。

你真的必须为自己想要的付出一些代价。总有些东西必须妥协。 - Mark Garcia

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接