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分钟的时间来写,我不认为我在任何我读过的书中都记得这个。我总是选择第二个,因为在我的脑海中,你应该首先处理更通用的东西,然后是更具体的东西。
很抱歉,这是一个简单的问题!
谢谢!
答案 0 :(得分:1)
语言中没有这样的要求。这是一个界面设计问题,虽然库有时需要在特定时间调用基类,但我认为这是一个糟糕的API。
最好的设计不要求用户调用基本版本......永远。这消除了派生类的作者的任何负担。我听说过这个名为无合约的 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 可能是纯虚拟的,但是一些钩子完全可以留下一个空实现,因为它们的目的是提供选项派生类来定制某些点的行为。