Yeah, the person, teacher, student stuff is pretty bad, and honestly I find that most "real-world" examples don't work very well as sub-classes. Where I do find it works fairly well is with more "gamified" type of stuff. For example:
Creature
/ \
Human Simple Monster
/ \
NPC Player
With a system like this we can have a basic "Creature" class that defines the basic things that the vast majority of creatures need (creation functions, blood type data (or lack thereof), corpse creation calling. Then from then we can split down into Monsters (that have reduced data stored, only a single health pool, and other simplified features) from humans (that have body part tracking, can equip weapons, and so forth). Then humans can be further subclassed into whether they are NPC's (including the AI code and so forth) or Players (in which case you include the UI code). (Alternatively if you wanted more intelligent monsters you might consider splitting along the "Intelligent/Animal" boundary and then maybe a second split of Intelligent along the "Interactive/Noninteractive").
Examples like that work well because as part of a game you are able to define clear-cut boundaries that lend themselves well to subclasses, and their use allows for sensible "defaults" to automatically exist for the vast majority of things, reducing the amount of code that you actually need to manually implement. Real-world examples, on the other hand, are rarely as simple and well-defined enough to lend themselves well to subclasses due to their overlaps and mutability as time goes on.