3

いくつかの純粋な仮想パブリック メソッドを持つ抽象基本クラスとして実装されたインターフェイスがあります。サブクラス間の違いは大きくないため、これらの純粋仮想関数はテンプレートを使用して実装できます。そのため、複数の継承を使用して、実装を提供する適切にテンプレート化されたヘルパー クラスを混在させることを考えました。ただし、コンパイラは、基本クラスが抽象であると不平を言います。ヘルパー mix-in の実装を考慮していないため、必要なメソッドの実装がないと考えています。

例えば:

class TrivialList {
    int count;
public:
    TrivialList(int count) : count(count){}
    virtual double Average() const=0;
    int Count() const {return count;}
    virtual ~TrivialList(){}
};
template<typename TIndexable> class AverageHelper {
public:
    double Average() const {
        TIndexable const & self = static_cast<TIndexable const &>(*this);
        double sum=0.0;
        for(int i=0;i<self.Count();++) sum += self.Get(i);
        return sum / self.Count();
    }
};
class IndexableList : public TrivialList, public AverageHelper<IndexableList> {
    std::vector<double> backend;
public:
    IndexableList(int count) : TrivialList(count), backend(count) { }
    double & Get(int i) { return backend[i];}
    double const & Get(int i) const { return backend[i];}
};
IndexableList * MakeList() {return new IndexableList(5);} //error!
//    cannot instantiate abstract class

MSC 10.0 (Visual Studio 2010) を使用しています。g++ 4.5 を使用すると、コードは同様のエラーで失敗します。

Getまたは、私のプロジェクトの実際の同等物は、適切なパフォーマンスのためにインライン化する必要がある非常にマイナーな操作であるため(put-pixel/get-pixelを考えてください)、仮想にすることはできません-したがって、汎用アルゴリズムではなく、汎用アルゴリズムをテンプレート化する必要があります仮想関数呼び出しを介して。

4

2 に答える 2

5

テンプレートを介してミックスインを実装するには、抽象基本クラスから派生する抽象関数を実装するテンプレートが必要です。

したがって、次のように変更してコードを修正できます。

// ...
template<typename TIndexable> class AverageHelper : public TriviaList{

// ...
class IndexableList : public AverageHelper<IndexableList> {

一般に、複数の mix-in を提供する場合は、基本クラスのインスタンスを乗算しないように仮想継承を使用するか、次のサンプルのようにチェーン継承を使用できます。

class Abstract {
public:
    virtual void foo() = 0;
    virtual void bar() = 0;
};

template<class Base>
class FooImpl : Base {
public:
    void foo() { /* default foo implementation */ }
};

template<class Base>
class BarImpl : Base {
public:
    void bar() { /* default bar implementation */ }
};

class Derived : public BarImpl<FooImpl<Abstract> > {
    // You have both foo() and bar() implementations available
};
于 2010-06-22T11:17:50.520 に答える
4

AverageHelper<>::Average()オーバーライドしないため、機能しませんTrivialList::Average()。仮想関数をオーバーライドするには、オーバーライドするクラスが、オーバーライドされる関数を含むクラスから継承する必要があります。

テンプレートを次のように変更できます。

template<typename TIndexable, typename Base > 
class AverageHelper : public Base {
public:
  template< typename T >
  AverageHelper(T arg) : Base(arg) {}
  // ... 
};

class IndexableList : public AverageHelper<IndexableList,TrivialList> {
public:
  IndexableList(int count) : AverageHelper<IndexableList,TrivialList>(count) {}
  // ...
};

から仮想的に派生したい場合がありますTrivialList

template<typename TIndexable, typename Base > 
class AverageHelper : virtual public Base {
  // ... 
};
于 2010-06-22T11:16:56.947 に答える