【问题标题】:Virtual methods whose type is known at compile-time类型在编译时已知的虚拟方法
【发布时间】:2011-09-07 07:36:21
【问题描述】:

如果我这样做:

Dog dog; //class with virtual methods
Cat cat; //class from same base as Dog

dog.eat(); //call virtual method
cat.eat(); //call virtual method

那么eat()s 将是正常的方法调用并且不需要v-table - 对吗? 我可以假设它的运行方式与非虚拟方法相同?

(是的,我知道编译器如何处理虚函数不在标准中——我想知道大多数编译器是做什么的)

【问题讨论】:

  • 如果对您很重要,请检查编译器的汇编器输出。
  • birryree:我是这么想的,但我想确认一下。 Neil Butterworth:很好,虽然我希望我能在这里得到答案......

标签: c++ inheritance methods virtual


【解决方案1】:

当您使用object.member 时,您不会取消对指针的引用,因此virtual 方法无效。 Virtual 只有当你有一个可以多态的指针并且使用动态调度时才会生效。

例如:

Cat cat;
Animal *cat2 = &cat;
cat.eat(); // direct call
//... a lot of other code and function calls that pass cat2 around, to avoid optimization
cat2->eat(); // dynamic dispatch

编辑按 cmets 更正

【讨论】:

  • 编译器可以推断 cat2 在这里指向一只猫,并使用直接调用。这是一种常见的优化。
  • Dog *cat2 = &cat; 这没有意义,Dog 不是Cat 的基数,但它们的基数相同。
【解决方案2】:

如果静态类型在编译时已知,则无需使用 vtable,因为无论如何调用的函数都是已知的。

大多数编译器都会看到这一点。

【讨论】:

    【解决方案3】:

    我会说是的,大多数编译器都会进行这种优化。如果您已经进行了分析并且它确实很重要,那么确定的唯一方法是检查生成的反汇编。

    【讨论】:

    • 这不是优化,它是标准定义的行为——当在对象而不是指针或引用上调用时,给定的成员函数是虚拟的这一事实将被忽略。
    【解决方案4】:

    如果分析显示大多数时间使用某种类型,Visual Studio 能够将虚拟调用优化为直接调用。

    虚拟通话推测 – 如果 虚拟通话,或其他通过 函数指针,经常针对 某些功能,配置文件引导 优化可以插入一个 有条件执行的直接调用 经常针对的功能,以及 直接调用可以内联。

    请参阅 MSDN 上的 Profile Guided Optimization

    常规的“去虚拟化”(即其他答案所暗示的)可以在不分析应用程序的情况下完成,并且很常见。

    GCC 自动启用此优化,但具体标志为 -fdevirtualize

    尝试将调用转换为虚拟调用 直接调用的功能。这是 在一个程序内完成,并且 在程序间作为间接的一部分 内联(-findirect-inlining)和 过程间常数传播 (-fipa-cp)。在 -O2 级别启用, -O3,-Os。

    来自GCC Optimize Options

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-03-08
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多