(1) The target is not necessarily known at compile time.
(2) The catcher is likely not the same function as the thrower, with several other functions in between.
(3) The stack is unwound as part of the throw/catch, including things like destructors.
Even the uber-powerful "goto" that Dijkstra railed against didn't have these properties, let alone the tamer "goto" of modern languages like C. Personally I think (1) and (2) are reasons why exceptions are far worse than gotos, but if you're going to have them then you'd best have (3) as well. What I always find strange is people who look down their noses at code with gotos carefully used for error cleanup, but have no qualms about flinging exceptions around in their own code. I guess those who do not learn the lessons of history, etc.