qua*_*ant 49 c++ overriding virtual-functions final
据我所知,override关键字声明给定的声明实现了一个基本virtual方法,如果找不到匹配的基本方法,编译应该失败.
我对该final关键字的理解是它告诉编译器没有类会覆盖这个virtual函数.
那是override final多余的吗?好像编译好了.哪些信息override final传达的final不是?这种组合的用例是什么?
Col*_*mbo 43
final不要求函数首先覆盖任何东西.其效果在[class.virtual]/4中定义为
如果
f某个类中的虚函数B使用virt-specifier 标记,final并且在D从B函数D::f覆盖派生的类中B::f,则该程序格式错误.
而已.现在override final只是意味着
"这个函数覆盖了一个基类one(override)并且不能自己重写(final)."
final它自己会强加一个较弱的要求.
override并final有独立的行为.
注意,final只能用于虚函数 - [class.mem]/8
甲的virt说明符-SEQ应仅在一个虚拟的成员函数(10.3)的声明出现.
因此宣言
void foo() final;
Run Code Online (Sandbox Code Playgroud)
实际上是一样的
virtual void foo() final override;
Run Code Online (Sandbox Code Playgroud)
因为两者都需要foo覆盖某些东西 - 第二个声明是通过使用override,第一个声明是有效的,当且仅当它foo是隐式虚拟时,即当foo覆盖foo在基类中调用的虚函数时,这会使得foo派生的虚函数自动虚拟. 因此override,在声明中final,多余的,但不会virtual发生.
尽管如此,后一种声明表达的意图更加清晰,绝对应该是首选.
Rei*_*ica 18
final并不一定意味着该函数被覆盖.这是完全有效的(如果有些可疑值)申报虚函数作为final其首次在继承层次声明.
我可以想到创建一个虚拟的,即时的最终函数的一个原因是,如果你想阻止派生类给出相同的名称和参数不同的含义.
以下代码(带有final说明符)可编译。但final替换为时编译失败override final。因此override final传达的信息比仅仅 . 更多的信息(并阻止编译)final。
class Base
{
public:
virtual ~Base() {}
};
class Derived : public Base
{
public:
virtual void foo() final
{
std::cout << "in Derived foo\n";
}
};
Run Code Online (Sandbox Code Playgroud)
本质上,override final表示此方法不能在任何派生类中重写,并且此方法重写基类中的虚拟方法。final单独不指定基类重写部分。
(如果要赶时间,请跳到最后查看结论。)
双方override并final只能申报一个虚函数出现。这两个关键字可以在同一函数声明中使用,但同时使用它们是否有用取决于情况。
以以下代码为例:
#include <iostream>
using std::cout; using std::endl;
struct B {
virtual void f1() { cout << "B::f1() "; }
virtual void f2() { cout << "B::f2() "; }
virtual void f3() { cout << "B::f3() "; }
virtual void f6() final { cout << "B::f6() "; }
void f7() { cout << "B::f7() "; }
void f8() { cout << "B::f8() "; }
void f9() { cout << "B::f9() "; }
};
struct D : B {
void f1() override { cout << "D::f1() "; }
void f2() final { cout << "D::f2() "; }
void f3() override final { cout << "D::f3() "; } // need not have override
// should have override, otherwise add new virtual function
virtual void f4() final { cout << "D::f4() "; }
//virtual void f5() override final; // Error, no virtual function in base class
//void f6(); // Error, override a final virtual function
void f7() { cout << "D::f7() "; }
virtual void f8() { cout << "D::f8() "; }
//void f9() override; // Error, override a nonvirtual function
};
int main() {
B b; D d;
B *bp = &b, *bd = &d; D *dp = &d;
bp->f1(); bp->f2(); bp->f3(); bp->f6(); bp->f7(); bp->f8(); bp->f9(); cout << endl;
bd->f1(); bd->f2(); bd->f3(); bd->f6(); bd->f7(); bd->f8(); bd->f9(); cout << endl;
dp->f1(); dp->f2(); dp->f3(); dp->f6(); dp->f7(); dp->f8(); dp->f9(); cout << endl;
return 0;
}
Run Code Online (Sandbox Code Playgroud)
输出是
B::f1() B::f2() B::f3() B::f6() B::f7() B::f8() B::f9()
D::f1() D::f2() D::f3() B::f6() B::f7() B::f8() B::f9()
D::f1() D::f2() D::f3() B::f6() D::f7() D::f8() B::f9()
Run Code Online (Sandbox Code Playgroud)
比较f1()和f6()。我们知道这一点,override并且final在语义上是独立的。
override表示该函数正在其基类中覆盖虚拟函数。请参阅f1()和f3()。final表示该函数不能被其派生类覆盖。(但是函数本身不必重写基类虚函数。)请参见f6()和f4()。比较f2()和f3()。我们知道,如果声明一个成员函数不virtual带有和final,则表示它已经覆盖了基类中的虚函数。在这种情况下,关键字override是多余的。
比较f4()和f5()。我们知道,如果用声明成员函数,virtual并且它不是继承层次结构中的第一个虚函数,那么我们应该使用它override来指定重写关系。否则,我们可能会意外地在派生类中添加新的虚函数。
比较f1()和f7()。我们知道,可以在派生类中重写任何成员函数,而不仅仅是虚函数。什么virtual规定是多态的,这意味着决定哪个函数运行被延迟,直到运行时间而不是编译时间。(在实践中应避免这样做。)
比较f7()和f8()。我们知道,我们甚至可以重写基类函数并将其设为新的虚函数。(这意味着f8()派生自该类的任何成员函数D都是虚函数。)(在实践中也应避免这样做。)
比较f7()和f9()。我们知道,override当我们想覆盖派生类中的虚函数而忘记virtual在基类中添加关键字时,可以帮助我们找到错误。
总之,我个人认为最佳实践是:
virtual声明基类中的第一个虚函数;override除非final另外指定,否则始终用于在派生类中指定重写虚拟函数。| 归档时间: |
|
| 查看次数: |
13616 次 |
| 最近记录: |