C++ FAQ Celebrating Twenty-One Years of the C++ FAQ!!!
(Click here for a personal note from Marshall Cline.)
Section 21:
[21.7] Are there other options to the "Circle is/isnot kind-of Ellipse" dilemma?

If you claim that all Ellipses can be squashed asymmetrically, and you claim that Circle is a kind-of Ellipse, and you claim that Circle can't be squashed asymmetrically, clearly you've got to revoke one of your claims. You can get rid of Ellipse::setSize(x,y), get rid of the inheritance relationship between Circle and Ellipse, or admit that your Circles aren't necessarily circular. You can also get rid of Circle completely, where circleness is just a temporary state of an Ellipse object rather than a permanent quality of the object.

Here are the two most common traps new OO/C++ programmers regularly fall into. They attempt to use coding hacks to cover up a broken design, e.g., they might redefine Circle::setSize(x,y) to throw an exception, call abort(), choose the average of the two parameters, or to be a no-op. Unfortunately all these hacks will surprise users, since users are expecting width() == x and height() == y. The one thing you must not do is surprise your users.

If it is important to you to retain the "Circle is a kind-of Ellipse" inheritance relationship, you can weaken the promise made by Ellipse's setSize(x,y). E.g., you could change the promise to, "This member function might set width() to x and/or it might set height() to y, or it might do nothing". Unfortunately this dilutes the contract into dribble, since the user can't rely on any meaningful behavior. The whole hierarchy therefore begins to be worthless (it's hard to convince someone to use an object if you have to shrug your shoulders when asked what the object does for them).

(Note: this FAQ has to do with public inheritance; private and protected inheritance are different.)

(Note: setSize(x,y) isn't sacred. Depending on your goals, it may be okay to prevent users from changing the dimensions of an Ellipse, in which case it would be a valid design choice to not have a setSize(x,y) method in Ellipse. However this series of FAQs discusses what to do when you want to create a derived class of a pre-existing base class that has an "unacceptable" method in it. Of course the ideal situation is to discover this problem when the base class doesn't yet exist. But life isn't always ideal...)