5

基类A有子类BB也有子类CA实现了一个虚方法doStuff()B没有,也C确实。从C,我想调用A的实现doStuff()(我在C的实现中这样做,doStuff()但这并不重要。)我应该调用

A::doStuff();

或者:

B::doStuff();

第一个似乎更清楚,因为它指的是实际的实现。另一方面,如果我后来决定B需要doStuff()不同于A. 哪个更标准?哪个更危险?

我有点惊讶B::doStuff()没有触发任何警告,但我想根据定义B,即使它来自基类,它也有一个实现。基类和实现的链可以任意长和复杂吗?例如,如果我有Athrough Z,每个都是前一个的子类,我是否可以在链中的任何地方都有实现,并且调用任何类的方法是否只是“向上链”直到找到实现?

4

2 回答 2

2

首先,关于最后一段,是的,你是绝对正确的。

接下来,对于主要问题:

这是一个逻辑问题,应该根据具体情况进行处理。您是唯一可以决定是从B还是从调用逻辑的人A,即使B::doStuff()尚未实现。没有正确的答案。

但是,您应该查看模板方法模式。我的猜测是,如果你想C调用一些东西,A然后你决定你想要D(的兄弟C)做同样的事情,你就是在复制代码。所以我会采取不同的方法:

class A
{
private:
   void doAStuff(); //doesn't have to be here
public:
   virtual void doStuff()
   {
      doAStuff();
   }
   void doAStuffAndStuff();
   {
      doAStuff();
      doStuff();
   }
}

class B : A
{
public:
   virtual void doStuff(); //or not
}

class C : B
{
public:
   virtual void doStuff();
}

IMO 这更直观。假设我有一个A* a,我不知道的动态类型a

  • 如果我想doStuff()用最派生类中的逻辑调用,我调用doStuff().
  • 如果我想doStuff()用最派生类中的逻辑调用,但我也想要来自 的逻辑A,我调用doAStuffAndStuff().

我将这种方法作为一种替代方法。我并不是说它一定适用于你的情况,但它可能。

于 2012-04-20T16:56:28.267 回答
0

打电话B::doStuff。更好的是,如果可以的话,不要使用需要显式调用基类方法的设计。如果必须,请base.doStuff通过某些宏或别名构造进行模拟,以防止出现此类错误。您可以在类中定义别名(并确保其在编译时存在)BaseType并使用BaseType::doStuff语法。

我有点惊讶 B::doStuff() 没有触发任何警告,但我想根据定义 B 有一个实现,即使它来自基类

没有什么可警告的。在您的情况下,这是一个法律场景。

基类和实现的链可以任意长和复杂吗

是的,它可以,但它不应该。需要长继承链并包含某种隐藏规则的设计通常会破坏应该调用哪些基类的哪些方法。

于 2012-04-20T16:59:34.923 回答