For a while, I've heard people say things like, "always prefer composition to inheritance". Today I looked into this argument more. Turns out the real argument should have been "Don't use inheritance at the wrong times". Durr. Essentially, this boils down to the "Is-a" vs. "Has-a" relationships we all learned in whatever Object Oriented 101 course you took. If two things share an "is-a" relationship, you can use inheritance. If it's a "has-a" relationship, it should be included through composition. For example, a patient has an ID, and a patient is a person. Following this rule will get you out of most of the problems with using inheritance wrong.
Another, perhaps more important, thing to consider is the Liskov substitution principle. It basically says if I have class D derive from class B, I should be able to replace all instances of B with D anywhere in my program. The program should behave exactly as before. If it doesn't, D should not have inherited from B. An implication of the Liskov substitution principle is that "is-a" really means that every method in the base class applies to the derived class. That is, if all birds can fly(), and a penguin cannot fly(), it shouldn't derive from a bird. For development purposes, a penguin is not a bird.
Another place where inheritance is probably inappropriate, is when you create linear inheritance chains. This is simply there to anticipate change someday, but it complicates code unnecessarily today. Merging the classes would be simpler (and by extension, safer) today. You can break them up again when you actually need the hierarchy, and it will cost just as much then. The difference is that you pay the price (in both time and complexity) only when you need it. I've talked about this issue before.
Anyway, I should probably go back to studying for exams, instead of watching Software Engineering lectures at French universities. La la la.