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 の2 つの基本クラスがICommandあり、両方の純粋なメソッドをオーバーライドする必要があります。ただしConcreteCommand、 の「最下位」バージョンのみをオーバーライドしstart、他のバージョンはオーバーライドされません。

実際のダイヤモンドが必要な場合は、仮想継承を使用して基本クラスをICommand仮想する必要があります。または、 in に別のオーバーライドを提供することもできます。class IExtendedCommand : virtual public ICommandConcreteCommandstartExtendedConcreteCommand

于 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継承を使用することもできます。その場合、のインスタンスは 1 つだけ ICommandであり、実際のダイヤモンドも 1 つだけです。あなたの例では、の2 つのインスタンスがありICommandます。1 つは から来てIExtendedCommandおり、もう 1 つは から来ていConcreteCommandます。

于 2012-10-26T14:14:27.740 に答える
0

virtualインターフェイスから ly を継承するだけです。

これにはランタイム コストがかかります。

于 2012-10-26T14:14:00.830 に答える