虚拟决赛和非虚拟决赛有什么区别?

Pet*_*ter 6 c++ virtual-functions final

virtual final声明新的(非重写)成员函数与仅声明非虚拟成员函数之间有什么区别?

我猜virtual final编译器无论如何都会将成员函数(不覆盖任何内容)优化为非虚拟函数,但也许我在这里错了。

Yak*_*ont 6

拥有虚拟方法意味着您是动态转换的合法目标,并且您不能成为标准布局。

从 ABI 角度来看,我怀疑编译器不会做额外的工作来消除final方法,因此带有条目的 vtable 仍然存在,除非整个类在“as-if”下被消除。

但在每个调用点,他们都可以绕过 vtable 并直接调用该方法(假设编译器在调用站点知道该方法的地址;某些动态加载设置可能会使 vtable 在调用站点已知) ,但方法地址不是)。

这还可以防止派生类覆盖这个确切的签名。IE:

struct Parent {
  void foo();
};
struct Child:Parent {
  void foo();
};
Run Code Online (Sandbox Code Playgroud)

这是合法的,同时

struct Parent {
  virtual void foo() final;
};
struct Child:Parent {
  void foo();
};
Run Code Online (Sandbox Code Playgroud)

不是。依赖于此是脆弱的,因为

struct Parent {
  virtual void foo() final;
};
struct Child:Parent {
  void foo() const;
};
Run Code Online (Sandbox Code Playgroud)

又是合法的。

  • @Peter我没有说“它在运行时方面没有任何成本”。我说它可能会改变 ABI 并阻止它成为标准布局,并且 vtable 可能存在。所有这些都会在运行时产生影响。“不需要任何成本”是一个非常强烈的要求,因为即使是微不足道的成本也会使其失败。 (3认同)
  • “_ABI 方面,我怀疑编译器不会做额外的工作来消除最终方法_”:即使他们这样做了,也不会改变该类是多态的,因此 `dynamic_cast` 和 `typeid` 的行为多态类型仍然需要起作用。所以消除 vptr 对我来说无论如何都是不可能的。 (2认同)