基类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
,每个都是前一个的子类,我可以在链中的任何地方实现,并且调用任何类的方法只是“上链”直到它找到一个实现?
答案 0 :(得分: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()
。我将此方法作为替代方案。我不是说它一定适用于你的情况,但它可能会。
答案 1 :(得分:0)
致电B::doStuff
。更好的是,如果可以的话,不要使用需要明确调用基类方法的设计。如果必须,请通过某些宏或别名构造模拟base.doStuff
,以防止出现这种错误。您可以在类中定义别名(并确保它在编译时存在)BaseType
并使用BaseType::doStuff
语法。
我有点惊讶B :: doStuff()没有触发任何警告,但我认为根据定义B即使它来自基类也有实现
没有什么可以警告的。在您的情况下,这是一个法律场景。
基类和实现链是否可以任意长 和复杂的
是的它可以,但不应该。需要长继承链的设计加上包含某些隐藏规则的应该调用哪些基类的方法通常会被破坏。