2017-05-24 34 views
25

我读一个真棒awesome C++11 tutorial和作者提供了这个例子,同时解释final关键字:是否有意义最终关键字添加到虚拟功能在没有基类的类(不派生)

struct B { 
    virtual void f() const final; // do not override 
    virtual void g(); 
}; 
struct D : B { 
    void f() const;  // error: D::f attempts to override final B::f 
    void g();  // OK 
}; 

那么在这里使用final关键字是否有意义?在我看来,你可以避免在这里使用virtual关键字,并且防止f()被覆盖。

+2

我不想敲它,因为上师可能会出现并提出一个用例,它解决了一些非常模糊的编译错误...但它看起来像一个愚蠢的事情。 – StoryTeller

+2

[有没有将基类函数标记为virtual和final的意义?](https://stackoverflow.com/questions/16739135/is-there-any-sense-in-marking-a-base -class-function-as-both-virtual-and-final) –

+0

实际上还有更多的重复,例如[最终虚拟函数有什么意义?](https://stackoverflow.com/questions/11704406/) – Ruslan

回答

32

如果您没有将函数标记为virtualfinal那么子类仍然可以实现该函数并隐藏基类函数。

通过使功能virtualfinal子级别不能覆盖隐藏功能。

+2

我知道一个古茹会来。尽管我认为这在开销方面有点太过分了(可能会或可能不会被忽略),只是为了防止隐藏。 +1。 – StoryTeller

+2

很明显,在这个问题上已经达成了共识,但是我为了一个人想要解释如何不做任何有用的*和*打破另一种语言功能将被视为一种好处。 – Quentin

+1

@Quentin消除了模糊的可能性,例如在模板的情况下void doStuff(DerivedFromB&b){b.f(); }',你可以100%确定'f()'调用去哪里 – Caleth

2

你的直觉是正确的:使功能virtual只能立即用final来限制它对非虚函数没有任何好处。这只是一个简短的示例代码片段来演示该功能。

此外,在其他的答案中描述,这实际上打破了功能隐藏 - 你将永远不会成为能够有一个f功能具有相同的参数列表中D或任何派生类的。
当您决定在模型中限制f时,这是一个权衡。由于无法在此处执行实际的虚拟呼叫,因此您基本上有缺点,没有任何好处。

+1

我想到隐藏名字。因此,您可以防止派生类隐藏f()。如果你声明没有virtual关键字的f(),我猜可以隐藏在派生类中。 –

+0

与往常一样,评论与downvotes相得益彰。 – Quentin

+1

我认为downvotes是由于你对禁用名称隐藏的态度。我想这个功能实际上可以用于某些特殊用途,但我不能说出任何这样的目的。 – Ruslan

11

是的!在您提供的示例中,final关键字可以防止任何派生类重写f(),正如您所说的那样。如果函数是非虚拟,D:f()允许隐藏函数的基类版本:

struct B { 
    void f() const; // do not override 
    virtual void g(); 
}; 
struct D : B { 
    void f() const; // OK! 
    void g();  // OK 
}; 

通过使f()一个virtualfinal功能,任何试图在覆盖或隐藏导致编译错误。

相关问题