C ++钻石界面继承

时间:2012-10-26 14:08:27

标签: c++ interface multiple-inheritance

我有一个等级:

class ICommand
{
    public:
        virtual void start() = 0;
};

class IExtendedCommand : public ICommand
{
    public:
        virtual void doSomethingElse() = 0;
};

class ConcreteCommand : public ICommand
{
    public:
        virtual void start() {};
}    
class ExtendedConcreteCommand : public ConcreteCommand, public IExtendedCommand
{
    public:
        virtual void doSomethingElse() {};
}

ICommand和IExtendedCommand对象由工厂创建。

由于某种原因,当编译器说所有ICommand的方法在ExtendedConcreteCommand中都是纯粹的......

任何想法为什么以及如何解决这个问题?

PS:是的我正在将我的Android应用移植到C ++ / Qt(我已经使用了3年)。 无论如何,我想听听你将如何应对这一点。

修改

我正在移植的是MPC和VLC的远程控制应用程序。 我们的想法是创建可以通过工厂发送给玩家的命令。 Factory返回指向实现ICommand的对象的指针。因此,通过切换工厂实现,可以创建不同的命令。 ICommand声明所有主要方法和信号。 IExtendedCommand在玩家之间添加了一些通用信息。所以我想做的是通过工厂实例化IExtendedCommand,设置一些属性然后用start()方法启动它。我还想重用ConcreteCommand的功能。这导致我描述的问题。

3 个答案:

答案 0 :(得分:3)

你没有钻石。你有这个:

   +----------------------------------- missing start() !
   V
pv start()     pv doSomethingElse()     concrete doSomethingElse()

ICommand  ---> IExtendedCommand   ---\
                                      > ExtendedConcreteCommand
ICommand  ---> ConcreteCommand    ---/

pv start()     concrete start()

这意味着你有两个类型ICommand的基类,你需要覆盖它们的纯方法。但只有ConcreteCommand会覆盖start的“底部”版本,而另一个版本仍未覆盖。

如果你想要一个真正的钻石,你需要使用虚拟继承ICommand来制作class IExtendedCommand : virtual public ICommand基类虚拟,同样也需要ConcreteCommand。或者,您可以在start中为ExtendedConcreteCommand提供另一个覆盖。

答案 1 :(得分:1)

如果我理解你的符号,ExtendedConcreteCommand应该是一个具体的类,这意味着你试图做的某个地方

ExtendedConcreteCommand command;

在您上传的代码中,ExtendedConcreteCommand是纯虚拟类,因为方法IExtendedCommand::start()是纯虚拟的。

实际上,钻石继承是不良的编码实践,应该避免 。如果您坚持这样做,为了避免编译器问题,您必须定义IExtendedCommand::start()。通过将您的班级修改为

class IExtendedCommand : public ICommand
{
    public:
        virtual void doSomethingElse() = 0;
        virtual void start() {};
};

你的代码编译。

您还可以使用virtual继承。在这种情况下,您将只有 ICommand的一个实例,以及一个真正的钻石。在您的示例中,您有两个 ICommand个实例:一个来自IExtendedCommand而另一个来自ConcreteCommand

答案 2 :(得分:0)

只需从界面继承virtual

确实有运行时成本。