提问人:Peter 提问时间:9/20/2023 最后编辑:Jan SchultkePeter 更新时间:9/20/2023 访问量:125
虚拟决赛和非虚拟决赛有什么区别?
What is the difference between virtual final and non-virtual?
问:
声明新的(非覆盖)成员函数与仅声明非虚拟函数之间有什么区别?virtual final
我猜编译器无论如何都会将成员函数(不覆盖任何内容)优化为非虚拟函数,但也许我在这里错了。virtual final
答:
6赞
Yakk - Adam Nevraumont
9/20/2023
#1
拥有虚拟方法意味着您是动态投射的合法目标,并且您不能成为标准布局。
ABI 明智的我怀疑编译器不会做额外的工作来消除方法,因此带有条目的 vtable 仍然存在,除非在“假设”下消除整个类。final
但是在每个调用点,它们都可以绕过 vtable 并直接调用方法(假设编译器在调用站点上知道该方法的地址;某些动态加载设置可能会使调用站点知道 vtable,但方法地址不是)。
这还可以防止派生类重写此确切的签名。结婚
struct Parent {
void foo();
};
struct Child:Parent {
void foo();
};
这是合法的,而
struct Parent {
virtual void foo() final;
};
struct Child:Parent {
void foo();
};
莫。依靠这一点是脆弱的,因为
struct Parent {
virtual void foo() final;
};
struct Child:Parent {
void foo() const;
};
又是合法的。
评论
0赞
Peter
9/20/2023
啊,好的,所以虚拟 final 阻止任何 Child 使用完全相同的签名,但它在运行时方面不会花费任何费用,对吧?
3赞
Yakk - Adam Nevraumont
9/20/2023
@Peter我没有说“在运行时间方面不花任何钱”。我说它可能会改变 ABI 并阻止它成为标准布局,并且 vtable 可能存在。所有这些都会在运行时产生影响。“不花任何钱”是一个非常强烈的需求,因为即使是微不足道的成本也会使它失败。
0赞
Peter
9/20/2023
好吧,对不起,你是对的。但它在运行时的成本可能不像人们怀疑的虚拟方法那么高。谢谢你的解释。
2赞
user17732522
9/20/2023
"ABI 明智的我怀疑编译器不会做额外的工作来消除最终方法“:即使他们这样做了,也不会改变类是多态的,因此 和 在多态类型上的行为仍然需要工作。因此,无论哪种方式,消除 vptr 对我来说似乎都是不可能的。dynamic_cast
typeid
0赞
Caleth
9/20/2023
只有当有人确实这样做了或这样的对象时,@user17732522,并且只有当编译器选择不将这些对象放入其他对象时dynamic_cast
typeid
评论
virtual void foo() final
使类具有多态性(因此您可以对其使用)。dynamic_cast
vptr
vptr
vptr