Tito
Tito

Reputation: 2300

C++ implementing object equality with multiple levels of iheritance

i need to implement an isEqual method to multiple objects that are have multiple levels of inheritance. For this reason i have decided to create not a interface since the method are not pure virtual but just a class that i can use later as a tag.

Those classes implement a single method isEqual. Since i need a default behavior defined those methods are not pure virtual.

class A_Interface {
    virtual isEqual(shared_ptr<A_Interface> obj);
    ...
    virtual otherMethod1();
}


class B_Interface : public virtual A_Interface {
    virtual isEqual(shared_ptr<B_Interface> obj);
    ...
    virtual otherMethod2();
}


class C_Interface : public virtual B_Interface {
    virtual isEqual(shared_ptr<C_Interface> obj);
    ...
    virtual otherMethod3();
}

each class implements it's own "interface like" tag class mentioned above and inherits from the parent like this:

class A : public virtual A_interface;
{
    isEqual(shared_ptr<A_Interface> obj){
    ...
    }
};



class B : public virtual A, 
          public virtual B_interface 
                {
    using A::isEqual;
    isEqual(shared_ptr<B_Interface> obj){
    ...
    }
};


class C : public virtual B,
          public virtual C_interface 
  {
    using B::isEqual;
    isEqual(shared_ptr<C_Interface> obj){
    ...

    bool parentIsEquals = B::isEqual(obj);

    ...
    }
};

In order to avoid name hinding in Class B i explicitelly declared the

using A::isEqual;

statement which solved the problem but now in class C when i want to reffer to the method "isEqual" parent class B and explicitelly specifing it like that

bool parentIsEquals = B::isEqual(obj);

i get the error

"B::isEqual' is ambiguous"

which I also understand since i have two signatures i.e.

using A::isEqual;
isEqual(shared_ptr<B_Interface> obj);

what i do not know is how to address this issue since the argument in this case "obj" does match bought signatures. I would like to understand if there a better pattern/proposition of implementing this problem.

Upvotes: 0

Views: 88

Answers (1)

YSC
YSC

Reputation: 40070

Keep it simple.

With the following class hierarchy:

struct A     { int value1; };
struct B : A { int value2; };
struct C : B { int value3; };

You can define equality operators for As, Bs and Cs

bool operator==(A const& lhs, A const& rhs)
{
    return lhs.value1 == rhs->value1;
}
bool operator==(B const& lhs, B const& rhs)
{
    return lhs.value2 == rhs->value2
           && static_cast<A const&>(lhs) == static_cast<A const&>(rhs);
}
bool operator==(C const& lhs, C const& rhs)
{
    return lhs.value3 == rhs->value3
           && static_cast<B const&>(lhs) == static_cast<B const&>(rhs);
}

With it, a bit of sugar:

template<class Wrapper>
bool operator==(A const& lhs, Wrapper const& rhs)
{ return lhs == *rhs; }
template<class Wrapper>
bool operator==(Wrapper const& rhs, A const& lhs)
{ return rhs == lhs; }
// and so on...

All those simple functions allow you a great deal of flexibility:

B b1{{1}, 2};
auto c2 = std::make_unique<C>(C{{{1}, 2}, 3});
bool const equals = b1 == c2; // true

Upvotes: 1

Related Questions