final是否意味着覆盖
Does final imply override?
据我所知,override
关键字声明给定的声明实现了一个基virtual
方法,如果找不到匹配的基方法,编译应该会失败。
我对final
关键字的理解是,它"告诉"编译器,任何类都不能覆盖这个virtual
函数。
那么override final
是多余的吗?它似乎编译得很好。override final
传达了哪些final
没有传达的信息?这种组合的用例是什么?
final
一开始不需要函数覆盖任何内容。其影响在[class.virtual]/4中定义为
如果某个类CCD_ 10中的虚拟函数CCD_virt说明符
final
和从B
派生的类D
中的函数D::f
覆盖B::f
,则程序格式不正确。
就是这样。现在override final
的意思就是
·此函数覆盖基类1(override
),并且不能被自身覆盖(final
)。"final
本身将施加较弱的要求。CCD_ 20和CCD_。
注意,final
只能用于通过-[class.mem]/8 的虚拟函数
virt说明符seq应仅出现在虚拟成员功能(10.3)。
因此声明
void foo() final;
实际上与相同
virtual void foo() final override;
由于两者都要求foo
重写某些东西——第二个声明使用override
,第一个声明有效,当且仅当foo
是隐式虚拟的,即当foo
重写基类中名为foo
的虚拟函数时,,这使派生函数中的foo
自动成为虚拟函数因此,在出现final
而不是virtual
的声明中,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;
}
输出为
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()
比较
f1()
和f6()
。我们知道CCD_ 38和CCD_。override
表示函数正在重写其基类中的虚拟函数。参见f1()
和f3()
final
表示函数不能被其派生类覆盖。(但函数本身不需要覆盖基类虚拟函数。)请参见f6()
和f4()
比较
f2()
和f3()
。我们知道,如果一个成员函数在没有virtual
和final
的情况下声明,则意味着它已经覆盖了基类中的虚拟函数。在这种情况下,关键字override
是多余的。比较
f4()
和f5()
。我们知道,如果一个成员函数是用virtual
声明的,并且它不是继承层次结构中的第一个虚拟函数,那么我们应该使用override
来指定覆盖关系。否则,我们可能会意外地在派生类中添加新的虚拟函数。比较
f1()
和f7()
。我们知道,任何成员函数,而不仅仅是虚拟成员函数,都可以在派生类中重写。virtual
指定的是多态性,这意味着运行哪个函数的决定将延迟到运行时而不是编译时。(这在实践中应该避免。)比较
f7()
和f8()
。我们知道,我们甚至可以覆盖基类函数,使其成为一个新的虚拟函数。(这意味着从D
派生的类的任何成员函数f8()
都将是虚拟的。)(在实践中也应该避免这种情况。)比较
f7()
和f9()
。我们知道,当我们想重写派生类中的虚拟函数而忘记在基类中添加关键字virtual
时,override
可以帮助我们找到错误。
总之,在我看来,最佳实践是:
- 只有在基类中第一个虚拟函数的声明中使用
virtual
- 始终使用
override
在派生类中指定重写虚拟函数,除非还指定了final
编译以下代码(带有final
说明符)。但当final
替换为override final
时,编译失败。因此,CCD_ 72比仅仅CCD_ 73传递更多的信息(并防止编译)。
class Base
{
public:
virtual ~Base() {}
};
class Derived : public Base
{
public:
virtual void foo() final
{
std::cout << "in Derived foon";
}
};
本质上,override final
说这个方法不能在任何派生类中重写,并且这个方法重写基类中的虚拟方法。单独的final
并没有指定基类覆盖部分。
无final
并不一定意味着override
。事实上,您可以声明一个virtual
函数,您可以立即声明final
,请参见此处。final
关键字简单地说明,没有派生的class
可以创建此函数的覆盖。
override
关键字很重要,因为它强制您实际上正在重写一个虚拟函数(而不是声明一个新的无关函数)。请参阅这篇关于override
的文章
长话短说,他们每个人都有自己的特殊目的,两者兼而有之通常是正确的。
- 使用ios:ate写入到流会覆盖现有文件
- 我可以重新分配/覆盖std::字符串吗
- 这行代码在C++类中意味着什么
- 叮叮当当在修复时插入多个"覆盖"说明符
- 谷歌模拟和覆盖关键字
- TMap::Emplace() 在应用现有密钥时会覆盖吗?
- 此测试()中发生了什么意外过程?为什么总是覆盖 ch[0 1 2..]?
- 这对"With a stackless coroutine, only the top-level routine may be suspended."意味着什么
- 寻找地理和伤害意味着超载
- 使用子类覆盖基类中定义的函数
- 当覆盖存在时调用基本虚拟"binded to object"函数
- C++指针在 for 循环中被覆盖
- "main"函数堆栈中的对象在第一个任务运行时被覆盖 (FreeRTOS)
- @CPPFLAGS@在 Makefile.in 中意味着什么?
- 为什么我的全局 new() 覆盖被绕过了?
- 被覆盖的函数不会反映在基类中,这是正常行为吗?
- C++找出覆盖同一行的数组
- 专门化模板覆盖函数/避免对象切片
- 重写打印函数而不是覆盖基类
- final是否意味着覆盖