8

いくつかの純粋な仮想二項演算子を使用して抽象クラスを作成しようとしています。これは、演算子のポリモーフィズムを実現するために、派生クラスによって実装する必要があります。簡単な例を次に示します。

class Base {
public:
    virtual const Base& operator+ (const Base&) const = 0;
};

class Derived : public Base {
public:
    const Derived& operator+ (const Derived&) const;
};

const Derived& Derived::operator+ (const Derived& rvalue) const {
    return Derived();
}

オペレーターが何をするかは今のところ重要ではありません。重要な部分は、オペレーターが何を返すかです。一時的なDerivedオブジェクト、またはそのオブジェクトへの参照を返します。さて、コンパイルしようとすると、次のようになります。

test.cpp: In member function ‘virtual const Derived& Derived::operator+(const Derived&) const’:
test.cpp:12:17: error: cannot allocate an object of abstract type ‘Derived’
test.cpp:6:7: note:   because the following virtual functions are pure within ‘Derived’:
test.cpp:3:22: note:    virtual const Base& Base::operator+(const Base&) const

どうしたの?operator +(Baseで唯一の純粋仮想関数)がオーバーライドされていませんか?Derivedも抽象的である必要があるのはなぜですか?

4

2 に答える 2

6

の戻り型Derivedは基本型と共変にすることができますが、引数型で同じことを行うことはできません。つまり、オーバーライドする関数は次のようになります。

class Derived : public Base 
{ 
public: 
    const Derived& operator+ (const Base&) const; 
}; 
于 2012-10-21T14:18:29.623 に答える
3

この種のオーバーロードは、通常の抽象クラスではクリーンな方法では不可能です。最初に:+を非メンバーとして宣言する必要がありますオーバーロード演算子をメンバー関数または非メンバー(フレンド)関数として宣言しますか?

この機能が本当に必要な場合は、テンプレート化されたインターフェイスから継承するのが最善です。

template<typename T>
class AddEnabled {
  public:
    friend T operator+ (T const& left, T const& right) {
      return left+=right;
    }
};

今あなたは書く

class Foo: public AddEnabled<Foo>{
  Foo():mVal(0){
  }

  Foo& operator+=(Foo const& foo){
    mVal+=foo.mVal;
  }

 private:
  int mVal;
}

コメントアウトする Foo& operator+=(Foo const& foo){と、演算子が実装されていないことを示すコンパイラエラーが発生します。ルックアップに関連する原則について詳しく知りたい場合は、http ://en.wikipedia.org/wiki/Barton%E2%80%93Nackman_trickおよびhttp://en.wikipedia.org/wiki/Curiously_recurring_template_patternを参照してください。

HTH、マーティン

于 2012-10-21T14:33:40.900 に答える