I have some pointers to a base type of Shape. I want to compare these objects using the == operator. The == operator should obviously return false if the objects are of different derived type. If they are of the same derived type however the members of the derived type should then be compared.
I have read that using the C++ RTTI is bad practice and should only be used in rare and essential circumstances. As far as I can see this problem cannot be generally solved without using the RTTI. Each overloaded == operator would have to check the typeid, and if they are the same perform a dynamic_cast and compare the members. This seems like a common need. Is there some kind of idiom for this problem?
#include <iostream>
using namespace std;
class Shape {
public:
Shape() {}
virtual ~Shape() {}
virtual void draw() = 0;
virtual bool operator == (const Shape &Other) const = 0;
};
class Circle : public Shape {
public:
Circle() {}
virtual ~Circle() {}
virtual void draw() { cout << "Circle"; }
virtual bool operator == (const Shape &Other) const {
// If Shape is a Circle then compare radii
}
private:
int radius;
};
class Rectangle : public Shape {
public:
Rectangle() {}
virtual ~Rectangle() {}
virtual void draw() { cout << "Rectangle"; }
virtual bool operator == (const Shape &Other) const {
// If Shape is a Rectangle then compare width and height
}
private:
int width;
int height;
};
int main() {
Circle circle;
Rectangle rectangle;
Shape *Shape1 = &circle;
Shape *Shape2 = &rectangle;
(*Shape1) == (*Shape2); // Calls Circle ==
(*Shape2) == (*Shape1); // Calls Rectangle ==
}
typeid
does, so why reinvent the wheel? I can ask the same of the OP. Saying "I have read that using the C++ RTTI is bad practice and should only be used in rare and essential circumstances" - overlooks the fact their scenario is precisely where RTTI should be used. Note RTTI encompassestypeid
+dynamic_cast
, and as the former is very cheap, I assume the OP's aversion to RTTI overall was based only on things read about the latter. Coursedynamic_cast
should be avoided where possible (like here) if speed is a concern, but it's usually not that bad – underscore_d