2017-07-30 61 views
1

C++中的初学者很容忍我。何时在overriden函数中调用上层的函数?在其他代码之前或之后?

当你有一个虚拟重写函数时,你应该什么时候调用基本函数?它应该是这样的:

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分钟写出来,而且我不认为我在任何已读的书籍中都记得这一点。我总是选择第二个,因为在我的脑海中,你应该先处理更通用的东西,然后再处理更具体的东西。

对不起,如果这是一个简单的问题!

谢谢!

+2

没有设定规则。无论您的设计是否合理。 –

+1

取决于你想做什么......这一切都取决于你。 – Papipone

+0

谢谢你们,我在想这个。你是否应该瞄准某些特定的东西?一种方法通常被认为是更好的编码标准吗? – Dan

回答

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 可能是纯虚拟的,但是一些挂钩是完全没有要留下一个空的实现,因为他们的目的是要提供派生类选项在某些点行为进行自定义。

+0

非常感谢这个答案和解决方法,我从来没有想过。我很可能会在某个时候使用它。 +1 – Dan

相关问题