GG.*_*GG. 12 c++ java virtual-functions
我刚才读到我们不应该过度使用虚函数.人们认为虚拟功能越少,错误越少,维护也越少.
由于虚函数会出现什么样的错误和缺点?
我对C++或Java的上下文感兴趣.
我能想到的一个原因是由于v表查找,虚函数可能比正常函数慢.
Ste*_*hen 14
你发布了一些一揽子声明,我认为大多数务实的程序员会因为误导或误解而耸耸肩.但是,确实存在反虚拟狂热者,他们的代码对性能和维护也同样糟糕.
在Java中,默认情况下一切都是虚拟的.说你不应该过度使用虚函数非常强大.
在C++中,您必须声明一个虚拟函数,但在适当的时候使用它们是完全可以接受的.
我刚才读到我们不应该过度使用虚函数.
很难定义"过度"......当然"在适当的时候使用虚拟功能"是一个很好的建议.
人们认为虚拟功能越少,错误越少,维护也越少.由于虚函数,我无法获得可能出现的错误和缺点.
设计糟糕的代码很难维护.期.
如果你是一个库维护者,调试隐藏在高级层次结构中的代码,很难跟踪代码实际执行的位置,没有强大的IDE的好处,通常很难说哪个类覆盖了这个行为.它可能导致在跟踪继承树的文件之间跳转很多.
所以,有一些经验法则,都有例外:
这种情况的实际情况是虚拟功能非常有用,并且这些疑问不太可能来自平衡源 - 虚拟功能已经被广泛使用了很长时间.更新的语言正在采用它们作为默认语言.
虚函数比常规函数稍慢.但这种差异是如此之小,以至于除了最极端的情况之外,并没有产生任何影响.
我认为避免虚拟功能的最佳理由是防止接口滥用.
编写可以扩展的类是一个好主意,但是有太多开放的东西.通过仔细规划哪些功能是虚拟的,您可以控制(并保护)如何扩展类.
当类被扩展以破坏基类的契约时,会出现错误和维护问题.这是一个例子:
class Widget
{
private WidgetThing _thing;
public virtual void Initialize()
{
_thing = new WidgetThing();
}
}
class DoubleWidget : Widget
{
private WidgetThing _double;
public override void Initialize()
{
// Whoops! Forgot to call base.Initalize()
_double = new WidgetThing();
}
}
Run Code Online (Sandbox Code Playgroud)
这里,DoubleWidget打破了父类,因为它Widget._thing是null.有一个相当标准的方法来解决这个问题:
class Widget
{
private WidgetThing _thing;
public void Initialize()
{
_thing = new WidgetThing();
OnInitialize();
}
protected virtual void OnInitialize() { }
}
class DoubleWidget : Widget
{
private WidgetThing _double;
protected override void OnInitialize()
{
_double = new WidgetThing();
}
}
Run Code Online (Sandbox Code Playgroud)
现在Widget不会再遇到NullReferenceException.
每个依赖项都会增加代码的复杂性,并使维护更加困难.当您将函数定义为虚拟时,可以创建类对其他代码的依赖关系,这些代码目前可能甚至不存在.
例如,在C中,您可以轻松找到foo()的作用 - 只有一个foo().在没有虚函数的C++中,它稍微复杂一些:你需要探索你的类及其基类来找到我们需要的foo().但至少你可以提前确定性地做,而不是在运行时.使用虚函数,我们无法分辨执行哪个foo(),因为它可以在子类中定义.
(另一件事是你提到的性能问题,由于v-table).