Exceptions are a special case. In their case, the inheritance is not to add new functionality, but to add new classes of errors. This lets your code catch particular kinds of errors while ignoring others.
Say you are writing a large project. You have a Data component, and you have a Display component. They can both fail in various ways, and you want to throw exceptions for these failures. The Display component doesn't care about exceptions arising from the Data component, though, and vice versa. If all the classes just threw Exception
, there'd be no way to figure out where the exception came from. However, if you subclass Exception
with DataException
and GraphicsException
, even though they don't add new functionality, you can now throw and catch those particular types of exceptions, i.e. a graphics component can catch GraphicsException
and not have to deal with data exceptions.