I've been bitten by this request many times in my own code. I'll present a simplified example:
struct Fruit
{
virtual bool is_equal(Fruit const & f) const = 0; // Compare two fruits
// Some dangerous actions:
bool operator==Fruit const & f)
{
return is_equal(f); // Dispatch!
}
};
struct Strawberry : public Fruit
{
bool is_equal(Fruit const & f)
{
bool equal = false;
// The f could be any fruit, such as tomatoes or pineapples or bananas.
// Need to perform a dynamic_cast to verify that the f is a strawberry.
Strawberry const & s = dynamic_cast<Strawberry const &>(f);
// perform strawberry comparison;
return equal;
};
}
struct Banana : public Fruit
{
bool is_equal(Fruit const & f)
{
bool equal = false;
// The f could be any fruit, such as tomatoes or pineapples or strawberries.
// Need to perform a dynamic_cast to verify that the f is a banana.
Banana const & b = dynamic_cast<Banana const &>(f);
// perform banana comparison;
return equal;
};
}
bool Compare_Fruits(Fruit const * pf1, Fruit const * pf2)
{
if (*pf1 == *pf2)
{
cout << "Fruits are equal\n";
return true;
}
cout << "Fruits are different\n";
return false;
}
int main(void)
{
// Fun with fruit.
Fruit * p_fruit_1 = new Strawberry;
Fruit * p_fruit_2 = new Banana;
Fruit * p_fruit_3 = new Strawberry;
// Is this valid, comparing two different fruits, when
// we just want to compare two strawberries?
if (Compare_Fruits(p_fruit_1, p_fruit_3)) // OK, both are strawberries
{
// ...
}
if (Compare_Fruits(p_fruit_1, p_fruit_2)) // Not OK, two different fruits.
{
// ...
}
return 0;
}
The point here is that if you are implementing the equal operation in the base class so that descendents can compare instances, you have made a poor decision. Be aware that I can pass a pointer to an instance of one descendent (Strawberry) to the comparison method of another descendent (Banana), because the equality function is based on pointers to the base class. Unfortunately, there is no way to tell how many or all of the descendents that are derived from the base class.
For programming safety, I highly recommend against placing virtual comparison operators in the base class. The base class should have comparison operators, declared protected, that only compare the base data members. This method would be called by the descendents.