将基类函数标记为虚函数和final函数有什么意义吗?

Is there any sense in marking a base class function as both virtual and final?

本文关键字:函数 什么 final 类函数 基类 记为      更新时间:2023-10-16

在c++ 11的final关键字的各种解释中,我看到了这样的例子。

class base
{
public:
    virtual void f() final;
};
class derived : public base
{
public:
    virtual void f();    // Illegal due to base::f() declared final.
};

这实际上是final的有用用途吗?为什么要在基类中声明虚函数(意味着它可以在派生类中有效地重写),然后立即将其标记为final(否定该含义)?virtual void f() final的效用是什么?

我可以看到标记derived::f() final而不是base::f()的值。在这种情况下,base::f()可能有一个很好的基于设计的理由,为什么f()应该是虚拟的,而derived::f()单独有一个很好的基于设计的理由,为什么不应该再派生类覆盖它的实现。

如果你不希望函数被多态覆盖,为什么不直接去掉virtual关键字呢?当然,派生类仍然可以非多态地覆盖函数。因此,基类中virtual void f() final的目的是使base::f()以任何方式(无论是作为虚函数还是非虚函数)都不可重写吗?如果是这样,那么在这种情况下,我们必须添加virtual关键字以启用final,这似乎有点不幸。我认为将非虚函数标记为final应该是合法的。

virtual的意义和final的意义似乎相矛盾时,为什么要用virtual void f() final来表示基类中的函数?

将基类函数标记为虚函数和final函数有什么意义吗?

是的,至少暂时是这样。

我发现自己在一个相对较大且不熟悉的现有c++源代码库中。大部分代码都是在c++ 11之前编写的。我发现我想确保基类中虚函数的所有重写都标记为override。困难的部分是找到所有这些覆盖。

我用final标记了基类中的虚函数,编译器很快向我展示了每个覆盖的声明位置。然后很容易按照我想要的方式装饰覆盖,并从基类中的虚拟中删除final

您可以将其标记为virtual,以指示它在您继承的类中是'virtual'(即使您不必这样做),并将其标记为final,以指示从您的类派生的任何类都不能进一步覆盖它。例如,在实现抽象基类时可能会发生这种情况。这是c++ 11,所以没有用;override是一个更好的指示,因为它由编译器强制执行。

另一种可能性:您希望此方法不被重写,但您希望能够在不重新编译的情况下更改该方法。请记住,virtual表示它在虚拟表中。即使编译器不允许你重写它

我认为您所展示的示例的目的是演示virtual和final之间的优先级,仅此而已。这是final的一个最小使用,而不是一个有用的

将非虚方法标记为final是没有意义的,因为无论如何都不能覆盖它们。如果您希望编译器防止隐藏,那是一个完全不同的问题,这与final方法无关。从某种意义上说,非虚方法已经是final了,但是是可隐藏的。

另一种选择是非虚函数。但是非虚函数可以被派生类隐藏。因此,如果想要防止函数隐藏,可以将其指定为virtual final。