什么时候调用override函数中的上层函数?在其他代码之前还是之后?
Posted
技术标签:
【中文标题】什么时候调用override函数中的上层函数?在其他代码之前还是之后?【英文标题】:When to call the upper hierarchy's function in overriden function? Before or after other code? 【发布时间】:2017-07-30 01:22:46 【问题描述】:C++ 初学者,请耐心等待。
当有一个虚拟覆盖函数时,你应该什么时候调用基函数?应该是这样的:
void Player::onCollision ( Collidable& otherObject )
/* OTHER CODE */
/* OTHER CODE */
PhysicalActor::onCollision ( otherObject );
或者这个:
void Player::onCollision ( Collidable& otherObject )
PhysicalActor::onCollision ( otherObject );
/* OTHER CODE */
/* OTHER CODE */
现在我不知道这是否真的有一个固定的规则 - 是应该总是先走还是总是最后走,甚至介于两者之间。我试过用谷歌搜索,但我不确定要谷歌搜索什么,因为标题花了我 5 分钟才写完,而且我认为我在读过的任何书中都不记得这一点。我总是选择第二个,因为在我看来,你应该先处理更通用的东西,然后再处理更具体的东西。
对不起,如果这是一个简单的问题!
谢谢!
【问题讨论】:
没有固定的规则。任何对你的设计有意义的东西。 取决于你想做什么......这完全取决于你。 谢谢大家,我在想这个。你应该瞄准特定的东西吗?一种方式通常被视为更好的编码标准吗? 它完全是特定于应用程序的。它甚至不必在之前或之后,也可以在中间调用,就像调用普通函数一样。当您希望调用该基本函数时,只需调用它即可。 【参考方案1】:语言中没有这样的要求。这是一个接口设计问题,虽然库有时确实需要在某些时候调用基类,但我认为这是一个糟糕的 API。
最好的设计不需要用户调用基本版本......永远。这消除了派生类的作者的任何负担。我听说过这种称为 contract-free 的 api 设计,因为没有必须接受的协议才能覆盖该功能。
通常使用您让用户接受的此类合同,它将基类逻辑与客户端覆盖的部分混合在一起。所以而不是:
class Base
//...
public:
// ** this version must be called before an override does anything
virtual void doSomething()
prepare(data);
private:
Data data;
这要求如果你覆盖 doSomething,你必须在做任何事情之前首先调用基础版本。
更好的界面应该是这样的:
class Base
//...
public:
void doSomething() // ** NOT virtual
prepare(data);
doSomethingHook();
protected:
virtual void doSomethingHook() // default is to do nothing
private:
Data data;
这保证了任何调用 doSomething() 的人总是会在调用被覆盖的虚函数之前准备好数据,现在虚逻辑被“移到一边”到一个没有排序责任的钩子函数中,只负责做该做的事。
当然,doSomethingHook 可能是纯虚拟的,但有些钩子可以留空实现,因为它们的目的是提供 选项派生类来自定义特定点的行为。
【讨论】:
非常感谢这个答案和我从未想过的解决方法。我很可能会在某个时候使用它。 +1以上是关于什么时候调用override函数中的上层函数?在其他代码之前还是之后?的主要内容,如果未能解决你的问题,请参考以下文章
重载(overload)覆盖(override)隐藏(hide)的区别
避免在构造函数中调用虚方法(Do not call overridable methods in constructors)