You do not want to embed the equality operators, == or != , In the base class. The base class does not know how many or contents of descendants.
For example, using an example of the Shape class:
struct Shape { virtual bool equal_to(const Shape& s) const = 0;
To satisfy the equality operators of the Shape class, each child must implement the equal_to method. But wait, how does Square know which type of other Shape ?
In this example, the Square class should use dynamic_cast to refer to the Square object. This will not work if the argument is Circle , Flower , Cloud or some other undefined form.
The following is the correct concept that you must follow:
Square my_square; Cloud my_cloud; Shape * p_shape_1 = &my_square; // Square is-a Shape, so this is legal. Shape * p_shape_2 = &my_cloud; // Cloud inherits from Shape, so this is legal. if (*p_shape_1 == *p_shape_2) // Legal syntax because of Shape::operator==(). { //???}
The comparison above causes nasty behavior. This can happen in common functions that only work on shapes.
Decision
Change the design . You should never set up a public comparison operator that compares with the base class in the base class. Nastya.
Descendants are compared with descendants. Period. Squares to squares, flowers to flowers, and circles to circles. Implementation of comparison operators in descendant classes.
Comparing the contents of a base class: If you have common content in a base class, use the protected method to compare only the methods of the base class:
struct Shape { protected: bool equal_shape_content(const Shape& s) const; };
This will make your program more reliable as it only compares the contents of the Shape with another Shape. That is all you can guarantee. See also "Slicing a base class."