3

我有一个层次结构:

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 的功能。这导致了我描述的问题。

4

3 回答 3

3

你没有钻石。你有这个:

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

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

pv start()     concrete start()

这意味着您有两个type 基类ICommand,并且您需要覆盖它们的纯方法。但仅ConcreteCommand覆盖 的“底部”版本start,而另一个保持未被覆盖。

如果你想要一个真正的钻石,你需要通过使用虚拟继承来使ICommand基类成为虚拟class IExtendedCommand : virtual public ICommand的: ,同样地 for ConcreteCommandstart或者,您可以为in提供另一个覆盖器ExtendedConcreteCommand

于 2012-10-26T14:13:52.797 回答
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

于 2012-10-26T14:14:27.740 回答
0

virtual只需从接口继承ly 即可。

这确实有运行时成本。

于 2012-10-26T14:14:00.830 回答