我有一个独特的情况,我需要两层接口,并希望有两层类来实现它们:
class IFood {
public:
virtual ~IFood() = default;
virtual int GetColor() const = 0;
};
class IFruit : public IFood {
public:
virtual int GetAverageSeedCount() const = 0;
};
class GreenFood : public IFood {
virtual int GetColor() const override {return GREEN;}
};
class GreenApple : public GreenFood, public IFruit {
virtual int GetAverageSeedCount() const override {return 5;}
};(我意识到这些接口并不是很有意义。对不起。)
在某些情况下,我可能有一个IFood对象的集合,但在另一些情况下,我可能有一个IFruit对象的集合。实际上,以IFood为代表的接口有5-8个函数。
如果这段代码能够编译并运行,我就完了。不幸的是,它失败了,因为编译器没有意识到GreenApple实现了IFood应用程序接口(缺少GetColor)。这确实存在于我们扩展的基本GreenFood中,但是拆分接口实现似乎不会让编译器满意。
对于IFood中的每个函数,我可以让IFruit实现它,并直接调用ParentClass::functionName()。但由于IFood中有5-8个函数和几十种潜在的水果类型,这并不像我想的那样优雅。
我很好奇是否有任何解决方案可以让编译器在父类中找到这些缺失的API,或者有什么好方法可以让我重新构造我的接口以保持优雅?
如果需要,我可以提供更具体的示例。谢谢你的建议!
发布于 2017-02-06 12:42:33
对IFruit和GreenFood中的基类使用虚拟关键字。
class IFood {
public:
virtual ~IFood() = default;
virtual int GetColor() const = 0;
};
class IFruit : public virtual IFood {
public:
virtual int GetAverageSeedCount() const = 0;
};
class GreenFood : public virtual IFood {
virtual int GetColor() const override {return GREEN;}
};
class GreenApple : public GreenFood, public IFruit {
virtual int GetAverageSeedCount() const override {return 5;}
};发布于 2017-02-06 12:58:17
有几种方法可以解决这个问题。
首先,GreenApple知道它继承了GreenFood和IFruit,而IFruit继承了它自己的实现GetColor()的需求,这是在GreenFood()中实现的,所以从一个角度来看,这是GreenApple的责任:
class GreenApple : public GreenFood, public IFruit {
virtual int GetAverageSeedCount() const override {return 5;}
virtual int getColor() const override {
return GreenFood::GetColor();
}
};这是一个稍微简洁的变体,它避免了丑陋的显式类引用:
class GreenFood : public IFood {
virtual int GetColor() const override
{
return GreenFoodColor();
}
int GreenFoodColor() const
{
return GREEN;
}
};
class GreenApple : public GreenFood, public IFruit {
virtual int GetAverageSeedCount() const override {return 5;}
virtual int getColor() const override {
return GreenFoodColor();
}
};这将会起作用,但这仍然会以两次从IFood继承的GreenApple结束。这可能会产生它自己的问题。
避免重复继承的另一种解决方案是不直接在继承IFood中使用IFruit,而是以某种方式要求它的子类继承自该接口:
class IFruit {
public:
virtual int GetAverageSeedCount() const = 0;
virtual IFood &getIFood()=0;
virtual const IFood &getIFood() const=0;
};
class GreenApple : public GreenFood, public IFruit {
virtual int GetAverageSeedCount() const override {return 5;}
virtual IFood &getIFood() override { return *this; }
virtual const IFood &getIFood() const { return *this; }
};任何看着IFruit的人都知道这附近的某个地方藏着一个IFood。也许在里面塞一个operator IFood &,让整个过程更加透明。
https://stackoverflow.com/questions/42060369
复制相似问题