如题,什么时候需要将一个类的方法声明为虚函数(virtual),这个问题涵盖技术和哲学两个层面。
从技术角度来说,如果你希望在运行阶段(而非编译阶段)根据对象的实际类型来调用方法时,就需要将它声明为一个虚拟函数。
但还有一个哲学层面的解释。
有些人认为,一个类的每个方法都应该是虚拟的,以便派生类可以以基类可能没有预料到的方式重写基类的行为。这确实可以提供了最大的灵活性,避免了将来必须重新设计类的风险。但我认为这种可扩展性的成本被严重低估了。
一旦你将一个方法标记为虚拟的,你的生活就会变得更加复杂。每个虚拟方法都是一个扩展点,这意味着你必须假设最坏的情况可能会发生。
例如,调用虚拟方法时不能持有任何锁(否则可能会与派生类死锁)。你还必须为各种可重入做好准备,因为派生类可能已决定在其实现中调用 MessageBox。你必须在虚拟方法返回后重新验证对象的最新状态,因为派生类可能在该虚拟方法中做了“疯狂”的事情,包括可能破坏对象本身!(当控制返回到基类时,使用无效的“this”指针时,程序还会异常崩溃)。
输入关键字 virutal 只需几秒钟,但你需要知道它实际上意味着的是什么。
我并不是说虚拟方法不好,我是说你需要了解你在做什么。
你不能这样认为:“天哪,有人可能想覆盖它,所以我会把它变成虚拟的。”
你应该在心里有这样的暗示:“天哪,我在这里创建了一个需要设计和测试的扩展点。”
当然,如果你的类是私有的,那么你是唯一可以从该类派生的人,因此,如果派生类覆盖了某个方法,你可以对派生类被允许执行的操作施加规则,并且你有权对这些派生类强制执行上述规则,因为你是编写程序的人。
但是,如果你允许别人从你的类中派生出来,那么你就进入了扩展性的世界,你的生活变得更加复杂。
总结
仅在必要的时候,才使用 virtual。
只有花上 10 分钟想清楚了类的继承结构和将来确认可能发生的扩展时,才使用 virtual。
最后
Raymond Chen的《The Old New Thing》是我非常喜欢的博客之一,里面有很多关于Windows的小知识,对于广大Windows平台开发者来说,确实十分有帮助。
本文来自:《Philosophical discussion on when to mark a method as virtual》