6

重複の可能性:
クラス階層の operator== をオーバーロードする正しい方法は何ですか?

次のコードのように、基本クラスといくつかの派生クラスがあります。

class Base
{
public:
    friend bool operator==(const Base&, const Base&);
    virtual ~Base(){}

private:
    virtual bool equals(const Base& other) const = 0;
};

bool operator==(const Base& lhs, const Base& rhs)
{
    return lhs.equals(rhs);
}

class A : public Base
{
public:
    A(int x) : x_(x){}

private:
    virtual bool equals(const Base& other) const;
    int x_;
};

bool A::equals(const Base& other) const
{
    const A* pA = dynamic_cast<const A*>(&other);
    if(!pA) return false;
    return x_ == pA->x_;
}

class B : public Base
{
public:
    B(double y) : y_(y){}

private:
    virtual bool equals(const Base& other) const;
    double y_;
};

bool B::equals(const Base& other) const
{
    const B* pB = dynamic_cast<const B*>(&other);
    if(!pB) return false;
    return y_ == pB->y_;
}

2 つの派生クラスを比較できるようにするには、operator== が必要です。問題は、オブジェクト指向の方法でこれをどのように達成するかです (たとえば、カプセル化、保守性、および拡張性を考慮して)。それを行うための推奨パターンはありますか?dynamic_cast を回避する上記のアプローチに代わるものはありますか?

4

1 に答える 1

3

あなたのやり方は完璧ではありません。から派生した次のクラスを検討してくださいA:

class AA : public A
{
public:
    AA(int x, int y) : A(x), y_(y) {}

private:
    virtual bool equals(const Base& other) const;
    int y_;
};

bool AA::equals(const Base& other) const
{
    const AA* pAA = dynamic_cast<const AA*>(&other);
    if(!pAA) return false;
    return A::equals(other) && y_ == pAA->y_;
}

次に、operatator ==基本的なルールを破ります。対称関係ではありません。

   A a(1); 
   AA aa(1,1); 
   assert(a == aa);
   assert(!(aa == a));

短い修正は使用することtypeidです:

bool operator==(const Base& lhs, const Base& rhs)
{
    return typeid(lhs) == typeid(rhs) && lhs.equals(rhs);
}
于 2012-10-24T08:31:24.130 に答える