2

次の問題があります。基本クラスとそれを継承するいくつかのクラスがあります。これらのクラスはすべて非常によく似たインターフェイスを共有しており、ほとんどの共有メソッドをオーバーロードする必要はほとんどありません。

ただし、それらはすべて、互いに派生し、非常に類似したインターフェースを共有する異なるメンバーオブジェクトを使用しています。

class BaseClass
{
    protected:
        Com* com;

    public:
        void setReady()
        {
            com->setReady();
        }
}

class DerivedClass : BaseClass
{
    protected:
        DerivedCom* com;
}

class Derived2Class : BaseClass
{
    protected:
        Derived2Com* com;
}

から継承されたバージョンの代わりに、のバージョンを実行できるようにするにはどうすればよいDerivedClassですか?setReady()comBaseClass

4

5 に答える 5

4

Comのさまざまな実装を使用してインスタンスを構築します。(DerivedComがComを実装していると仮定)

class BaseClass
{
    protected:
        Com* com;

    public:
        BaseClass(Com* c = new Com) : com(c) 
        {}

        void setReady()
        {
            com->setReady();
        }
}

class DerivedClass : BaseClass
{
    public:
        DerivedClass() : BaseClass(new DerivedCom) 
        {}
}

class Derived2Class : BaseClass
{
    public:
        Derived2Class() : BaseClass(new Derived2Com) 
        {}
}
于 2012-11-19T13:34:11.567 に答える
2

簡単な解決策は、保護された仮想関数を導入することです。これは、または:getCom()を返します。Com*Com&

virtual Com* getCom()
{ return this->com; }

子クラスはそれをオーバーライドして、独自のComから派生したインスタンスを返すことができます。次にsetReady()、関数を次のように実装できます。

void setReady()
{
    getCom()->setReady();
}

その後com、メンバーを作成できますprivate

このソリューションの欠点はCom、子クラスに複数の派生インスタンスがあることです。

于 2012-11-19T13:31:48.927 に答える
1

たぶん、クラステンプレートがあなたを助けるかもしれません:

class BaseClass
{
protected:
    Com* com;

public:
    virtual void setReady()
    {
        com->setReady();
    }
};

template<typename T>
class ComDerived : public BaseClass {
protected:
    T* com;
public:
    void setReady()
    {
        com->setReady();
    }
};

class DerivedClass : public ComDerived<DerivedCom>
{

};

class Derived2Class : public ComDerived<Derived2Com>
{

};
于 2012-11-19T13:29:39.557 に答える
0

d909bの答えに基づいて構築するには、次のようにします。

class BaseClass {
private:
   virtual Com * alloc_com() {
      return new Com;
   }
   Com * com;
public:
   BaseClass() : com(alloc_com()) {}
   void setReady() {
      com->setReady();
   }
};

class DerivedClass {
private:
   virtual Com * alloc_com() override {
      return new DerivedCom;
   }
};

class Derived2Class {
private:
   virtual Com * alloc_com() override {
      return new Derived2Com;
   }
};

これは、DerivedComがComからパブリックに継承し、Comに仮想デストラクタがある場合にのみ機能します。Comに仮想デストラクタがない場合は、仮想dealloc_com関数も必要です。それ以外の場合は、テンプレートまたはCRTPパターンを使用する必要があります。そうすると、コンパイル時にオブジェクトのタイプを推測できる場合に限定されます。ただし、これらが唯一のケースであることがわかっている場合は、テンプレートを使用すると、仮想関数呼び出しのオーバーヘッドを追加せずにインターフェイスを使用できます。

于 2012-11-19T14:07:04.090 に答える
0

なぜテンプレート化されたマザークラスではないのですか?

template <typename T>
class BaseClass
{
    protected:
        T* com;

    public:
        void setReady()
        {
            com->setReady();
        }
};

class DerivedClass : BaseClass<DerivedCom>
{
};

class Derived2Class : BaseClass<Derived2Com>
{
};
于 2012-11-19T13:30:12.437 に答える