Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/164.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 为什么不在C+中将所有函数都作为虚拟函数+;?_Java_C++_Virtual Functions - Fatal编程技术网

Java 为什么不在C+中将所有函数都作为虚拟函数+;?

Java 为什么不在C+中将所有函数都作为虚拟函数+;?,java,c++,virtual-functions,Java,C++,Virtual Functions,我知道虚拟函数在调用方法时会产生去引用的开销。但我想,以现代建筑的速度,它几乎可以忽略不计 为什么C++中的所有函数都不是虚拟的,如java?< /LI>,有什么特别的原因吗? 据我所知,在基类中定义虚函数是足够/必要的。现在,当我编写父类时,我可能不知道哪些方法会被忽略。那么这是否意味着在编写子类时,必须有人编辑父类。这听起来很不方便,有时甚至不可能 更新: Jon Skeet的回答总结如下: 这是一种在明确让某人意识到他们继承了功能[这本身有潜在的风险[(检查Jon的回答)][和潜在的小的性

我知道虚拟函数在调用方法时会产生去引用的开销。但我想,以现代建筑的速度,它几乎可以忽略不计

为什么C++中的所有函数都不是虚拟的,如java?< /LI>,有什么特别的原因吗?
  • 据我所知,在基类中定义虚函数是足够/必要的。现在,当我编写父类时,我可能不知道哪些方法会被忽略。那么这是否意味着在编写子类时,必须有人编辑父类。这听起来很不方便,有时甚至不可能
  • 更新:
    Jon Skeet的回答总结如下:

    这是一种在明确让某人意识到他们继承了功能[这本身有潜在的风险[(检查Jon的回答)][和潜在的小的性能提升]之间的折衷,折衷是灵活性更低、代码更改更多和学习曲线更陡

    来自不同答案的其他原因:

    虚拟函数不能内联,因为内联必须在运行时发生。当您希望函数从内联中受益时,这会影响性能

    可能还有其他原因,我想知道并总结一下

    主要的C++原理之一是:你只需支付你所使用的(“零开销原则”)。如果不需要动态调度机制,就不应该为其开销付费。

  • 作为基类的作者,您应该决定应该允许重写哪些方法。如果您同时编写这两种方法,请继续并重构您需要的。但它是这样工作的,因为基类的作者必须有一种方法来控制它的使用


  • 控制哪些方法是超越性能的虚拟方法是有充分理由的。虽然我实际上并没有将我的大多数方法最终用Java实现,但我可能应该……除非一个方法被设计为被重写,否则它可能不应该是虚拟的

    为继承而设计可能会很棘手,特别是这意味着您需要更多地记录可能调用它的内容和它可能调用的内容。想象一下,如果您有两个虚拟方法,其中一个调用另一个,则必须记录这些内容,否则有人可能会用一个调用“调用”的实现覆盖“调用”的方法方法,无意中创建了堆栈溢出(如果存在尾部调用优化,则为无限循环)。此时,您的实现灵活性就会降低—您无法在以后切换它

    请注意,C#在许多方面与Java类似,但在默认情况下选择将方法设置为非虚拟的。其他一些人对此并不感兴趣,但我当然欢迎它——实际上,我更希望类在默认情况下也是不可继承的


    基本上,这可以归结为Josh Bloch的建议:设计继承还是禁止继承。

    似乎这个问题可能有一些答案。在我看来,最突出的一点是,它只是增加了了解继承可以做什么的复杂性。

    (用比亚恩·斯特劳斯特鲁普的话说)是的,这是因为性能开销。使用虚拟表和间接寻址调用虚拟方法


    所有的方法都是虚拟的,开销也存在。但是,与C++不同,java编译器在运行时对代码进行了配置,并且可以将那些不使用此属性的方法进行在线化。因此,JVM知道它真正需要的地方和哪里,从而使您不必自行作出决定。MPELASE代码是在虚拟机上运行的,对于C++来说,同样的保证是不可实现的。它通常使用C++作为一个更有组织的C替换,C对汇编有1:1的转换。 如果你认为世界上10个微处理器中的9个不在个人计算机或智能手机中,当你进一步考虑到有很多处理器需要这个低级别的访问时,你会看到这个问题。

    C++是为了避免隐藏的延迟,如果不需要,那么保持第一个性质。一些C++代码在运行一个C到汇编编译器之前实际上有一个中间步骤被翻译成C。 但我想,以现代建筑的速度,它几乎可以忽略不计

    这一假设是错误的,我想这也是做出这一决定的主要原因

    <> P>考虑内联的情况。在某些情况下,C++(代码)>排序< /COD>函数比C的其他代码类似于<代码> qStase<代码>要快得多,因为它可以内嵌比较器参数,而C不能(由于使用函数指针)。在极端情况下,这可能意味着性能差异多达700%。(斯科特·迈尔斯,有效STL)


    虚拟函数的情况也是如此。我们以前也有过类似的讨论,例如,

    < P> java方法调用比运行时优化C++更有效。

    我们需要将C++编译成字节码,并在JVM上运行。

    < P>大多数的答案都是处理虚函数的开销,但是还有其他原因,不需要在类虚拟中实现任何功能,因为它会把类从标准布局转换成非标准布局,如果需要串行化,这可能是个问题。二进制数据。这在C#中以不同的方式解决,例如,
    struct
    s是与
    class
    es不同的类型族

    从设计的角度来看,每个公共函数都在您的类型和该类型的用户以及每个虚拟函数(公共或非公共)之间建立契约与扩展您的类型的类建立不同的契约。您签署的此类契约的数量越多,更改的空间就越小。事实上,f