我经常看到代码(例如here),其中覆盖也被声明为虚拟,即使该类不打算再次进行子类化。例如。
class A {
virtual void foo();
}
class B : public A {
virtual void foo();
}
// there is no subclass of B (and most likely there will never be one)
在我天真的C ++初学者的思考中,我发现它更清晰,更明确,不会声明B::foo
虚拟,以防它不被覆盖。即
class B : public A {
void foo();
}
我写的许多方法并不意味着被覆盖。另一方面,我理解virtual
表示该方法被设计为被覆盖。我想这只是一个品味问题,但我不是百分百确定:
如果声明B::foo()
virtual
(假设B
不会被用作基类)会不会有什么不同?
答案 0 :(得分:3)
不,它没有任何区别。如果A::foo
在基类中声明为virtual
,则B::foo
也是虚拟的:无论您是否声明它。
答案 1 :(得分:3)
无需在派生类中标记重写虚拟方法dyld: Symbol not found: _OBJC_CLASS_$_CBAnalytics
Referenced from: /Users/diverseconnection/Library/Developer/CoreSimulator/Devices/983BAC55-2713-423B-B5F3-C135ECCC2768/data/Containers/Bundle/Application/D4CAC0C7-E3D6-48F5-B264-E6EB715F9709/trouble.app/trouble
Expected in: flat namespace
in /Users/diverseconnection/Library/Developer/CoreSimulator/Devices/983BAC55-2713-423B-B5F3-C135ECCC2768/data/Containers/Bundle/Application/D4CAC0C7-E3D6-48F5-B264-E6EB715F9709/trouble.app/trouble
(lldb)
。方法是否为虚拟的决定是在最少派生的类中进行的。
但是,在派生类中明确标记虚拟方法virtual
是个好主意,原因有两个:
virtual
限定符,编译器可以在应用程序发布之前捕获该错误,并发出警告。但是,在这种情况下,不需要特定的实现来发布诊断。
virtual
,则实现需要发出错误,但派生类使用virtual
说明符。
答案 2 :(得分:2)
方法不会丢失virtual
限定符,因此如果A::foo()
是虚拟的,B::foo()
也是virtual
,即使不重复B::foo()
中的关键字声明。
在override
之前,在派生类中重复virtual
以便记住它是一个重写方法可能是一种样式,现在我们可以使用override
代替(并且编译器检查它是正确的,但不能简单地使用virtual
)
我写的很多方法并不意味着被覆盖
因此,您可以将它们标记为final
以禁止覆盖该方法(如果有意义,您也可以将该类标记为最终)。