patterncppMinor
Equals method implemented in the class
Viewed 0 times
themethodimplementedequalsclass
Problem
Is this a proper way to implement an equality check? In
Is there any other way to implement
EDIT
Made the
Equals method, I am relying on bad_cast exception to know if the objects are of the same class or not. Is there any other way to implement
Equals() in C++?class Shape
{
public:
virtual ~Shape() = 0;
bool operator==(const Shape& s)
{
return Equals(s);
}
virtual bool Equals(const Shape& s) = 0;
};
class Circle : public Shape
{
bool Equals(const Shape& c) override
{
try
{
const Circle& other = dynamic_cast(c);
// condition to check equality.
}
catch(std::bad_cast&)
{
return false;
}
catch(...)
{
throw;
}
}
};
class Square : public Shape
{
bool Equals(const Shape& s) override
{
try
{
const Square& other = dynamic_cast(s);
// condition to check equality.
}
catch(std::bad_cast&)
{
return false;
}
catch(...)
{
throw;
}
}
};
typedef std::shared_ptr ShapePtr;
typedef std::vector Shapes;
Shapes LoadShapes()
{
Shapes shapes;
shapes.push_back(std::make_shared(42));
shapes.push_back(std::make_shared(52));
shapes.push_back(std::make_shared(62));
shapes.push_back(std::make_shared(10));
return shapes;
}
int main()
{
auto circle = std::make_shared(42);
auto shapes = LoadShapes();
for ( auto& shape : shapes)
{
if ( *shape == *circle)
{
std::cout << *shape << "\n";
}
}
}EDIT
Made the
operator== as non-virtual method.Solution
Sorry to bump this one year old question, but there is something inherently wrong in your equality check if you ever extend to more than one level of inheritance.
Consider a class
Why does this fail?
However
Consider a class
Foo deriving from Circle, assuming the same implementation (with changed types of course).Foo foo;
Circle circle;
Shape & shapeFoo = foo;
Shape & shapeCircle = circle;
// these two should behave the same, but they don't:
std::cout << (shapeFoo == shapeCircle) << std::endl;
std::cout << (shapeCircle == shapeFoo) << std::endl;Why does this fail?
shapeFoo == shapeCircle will call shapeFoo.Equals(shapeCircle) which will be dispatched on the implementation of Equals in class Foo. There the dynamic_cast will fail, correctly returning false.However
shapeCircle == shapeFoo will call shapeCircle.Equals(shapeFoo) which will be dispatched on the implementation of Equals in class Circle. There the dynamic_cast will succeed (as Foo is a descendant of Circle). Then the method will compare only the attributes of Circle, probably returning true.Code Snippets
Foo foo;
Circle circle;
Shape & shapeFoo = foo;
Shape & shapeCircle = circle;
// these two should behave the same, but they don't:
std::cout << (shapeFoo == shapeCircle) << std::endl;
std::cout << (shapeCircle == shapeFoo) << std::endl;Context
StackExchange Code Review Q#10531, answer score: 6
Revisions (0)
No revisions yet.