【问题标题】:Calling identically named methods in base classes在基类中调用同名方法
【发布时间】:2012-05-02 06:26:45
【问题描述】:
基类A 有一个子类B,B 有一个子类C。 A 实现了一个虚方法 doStuff(),B 没有,C 有。从C,我想调用A 的doStuff() 实现(我在C 的doStuff() 实现中执行此操作,但这并不重要。)我应该打电话:
A::doStuff();
或者:
B::doStuff();
第一个似乎更清楚,因为它指的是实际的实现。另一方面,如果我后来决定B 需要与doStuff() 不同,则第二个可能更有用A。哪个更标准?哪个更危险?
我有点惊讶B::doStuff() 没有触发任何警告,但我想根据定义B 有一个实现,即使它来自基类。基类和实现的链可以任意长和复杂吗?例如,如果我有A 到Z,每一个都是前一个的子类,我可以在链中的任何地方都有实现吗,并且调用任何类的方法只是“向上”直到找到一个实现?
【问题讨论】:
标签:
c++
methods
virtual
subclass
base-class
【解决方案1】:
首先,关于最后一段,是的,你完全正确。
接下来,关于主要问题:
这是一个逻辑问题,应根据具体情况进行处理。您是唯一可以决定是从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()。
我将这种方法作为一种替代方法。我并不是说它一定适用于你的情况,但它可能。
【解决方案2】:
致电B::doStuff。更好的是,如果可以的话,不要使用需要显式调用基类方法的设计。如果必须,请通过一些宏或别名构造模拟base.doStuff,以防止出现此类错误。您可以在类中定义别名(并确保其在编译时存在)BaseType 并使用 BaseType::doStuff 语法。
我有点惊讶 B::doStuff() 没有触发任何警告,但我想根据定义 B 有一个实现,即使它来自基类
没有什么要警告的。在您的情况下,这是一个法律场景。
基类和实现的链可以任意长吗
又复杂
可以,但不应该。需要长继承链并包含某种隐藏规则的设计通常会破坏应该调用哪些基类的哪些方法。