4

基本クラスがあり、operator== を定義しています。AndBは and のサブクラスであり、 onAを定義するのを忘れています。その後、比較に使用され、通常、これは予期しない結果をもたらします。そのような「忘れ」を避けるための良い方法はありますか?質問を明確にするために例を追加します。operator==BA::operator==B

class A
{
public:
    bool operator==(const A& rhs) const
    {
        return i == rhs.i;
    }

    int i
};

class B : public A
{
public:
    int j;
}

B b1, b2;
b1.i = 1; b1.j = 2;
b2.i = 1; b1.j = 3;
bool b = (b1 == b2); // will be true
4

3 に答える 3

3

greatwolfの優れたアプローチに対して暗黙的な変換を許可するのは少し注意が必要です。

#include <type_traits>

namespace stuff
{

    template<class T, class U>
    bool operator== (const T &lhs, const U &rhs)
    {
        using namespace std;
        static_assert(is_convertible<T, U>{} || is_convertible<U, T>{},
                      "invalid argument type");
        static_assert
        (
               is_same<T, U>{}
            || ( not is_base_of<T, U>{} && not is_base_of<U, T>{})
            , "use explicit casts to compare derived to base class types"
        );
        return is_equal(lhs, rhs);
    }

    template<class T>
    bool is_equal(T const&, T const&)
    {
        // force compile-time failure when instantiating
        static_assert(std::is_same<T, void>{},
          "no free is_equal function for these argument types available");

        return false;
    }

    class A
    {
    private:
        int i;

        friend bool is_equal(A const& lhs, A const& rhs)
        { return lhs.i == rhs.i; }

    public:
        A(int p_i) : i(p_i) {}
    };

    class B : public A
    {
        int j;

    public:
        B(int p_i, int p_j) : A(p_i), j(p_j) {}
    };

    class C : public A
    {
    private:
        int j;

        friend bool is_equal(C const& lhs, C const& rhs)
        {
            return    is_equal(static_cast<A const&>(rhs),
                               static_cast<A const&>(lhs))
                   && lhs.j == rhs.j;
        }

    public:
        C(int p_i, int p_j) : A(p_i), j(p_j) {}
    };

}

struct D
{
    operator stuff::C() const
    {
        return stuff::C(1, 42);
    }
};

#include <iostream>
int main()
{
    stuff::A a(1), aa(1);
    stuff::B b(1, 42), bb(1, 42);
    stuff::C c(1, 42), cc(1, 42);

    D d;

    // commented lines invoke compilation failures
    std::cout << "a == aa: " << (a == aa) << std::endl;
  //std::cout << "a == b : " << (a == b ) << std::endl;
  //std::cout << "b == bb: " << (b == bb) << std::endl;
  //std::cout << "a == c : " << (a == c ) << std::endl;
    std::cout << "c == cc: " << (c == cc) << std::endl;
    std::cout << "d == c : " << (d == c ) << std::endl;
}
于 2013-09-13T04:10:26.270 に答える