隐式虚拟传播的原因是什么?

What is the reason of implicit virtual-ness propagation?

本文关键字:是什么 虚拟 传播      更新时间:2023-10-16

我只使用c++ 2~3个月,最近我发现了标识符final,它出现在虚函数之后。直到今天,我还认为省略virtual会阻止虚拟性的传播,但我错了。它隐式传播。

我的问题是这样的。为什么允许隐式传播?为什么存在不能使函数虚,而不存在不能使函数不虚?在某些情况下是不是更好?还是在虚拟第一次被引入的时候?

根据Clifford的回答,甚至有一个编译器会在缺少虚拟时产生警告。


为什么在c

中隐式传播方法的虚拟性

我希望上面的链接能回答我的问题,但它没有。

------------新增-------------

有关于询问此功能的有用性的评论。我认为虚函数上的final关键字是使函数去虚拟化的原因。函数不能再被重写,因此派生类必须重新声明函数,无论它是否具有相同的名称。如果final与去虚拟化不同,请帮助我理解。如果final没有区别,那么从引入final这一事实来看,反虚拟化的有用性是不言而喻的。我同意强制显式虚拟会产生bug,但我很好奇是否还有其他原因。

关于为什么存在(或不存在)的答案通常是相当困难的,因为它变成了猜测和意见的问题。然而,最简单的答案可能是最少惊讶原则。要想出一个有意义的、可靠的、可预测的方案是很困难的。

"去虚拟化"一个函数到底是什么意思?如果在运行时调用对象上的"去虚拟化"函数,它会使用指针的静态类型吗?如果静态类型有虚函数,而运行时类型没有,会发生什么?

#include <iostream>
struct A     {  virtual void f() const { std::cout << "A"; }  };
struct B : A {          void f() const { std::cout << "B"; }  };
struct C : B {  virtual void f() const { std::cout << "C"; }  };
struct D : C {          void f() const { std::cout << "D"; }  };
void f(const A& o) { o.f(); }
int main()
{
                // "devirtualized"     real C++
    f(A{});     // "A"                 "A"
    f(B{});     // "A" or "B"?         "B"
    f(C{});     // "C"?                "C"
    f(D{});     // oh god              "D"
}
还有一个事实是,对于绝大多数设计,虚函数在整个层次结构中必须保持虚。要求它们都使用virtual将会引入各种难以诊断的bug。c++通常会尽量避免使用那些需要遵守规则才能正确使用的特性。