Exception handling costs absolutely nothing when not triggered (on most reasonably platforms these days, due to zero-cost exceptions), while that comparison instruction is still there, still taking its performance cost for every call of every function that could theoretically fail in the entire program.
If it's a hot path, branch prediction will almost certainly make the cost of that comparison negligible though. If it's not a hot path, does it matter?
The difference in cost is negligible compared to the difference in correctness. Vtables are so optimized (and often elided) and caches so efficient and comparisons are cheap and branch predictors so great that the cost of both of these is functionally 0 in all code I touch outside the tightest inner in physics sims and rendering pipelines. Even there the differences is statistically negligible.
On correctness, it is impossible to forget to deal with an exception, it is Tuesday when a C program forgets to check an error code. Did you know printf returns an error code?
There are ways to force these returns to be checked by the compiler, but a language needs to be structured around it to be sane otherwise you wind up with every printf in an if statement. Forced exception checking is almost as burdensome, anybody with a few years of java ought to agree or at least see where I am coming from.
Error handling is just plain hard. Only a few languages do it really well. I think either could be done right if baked in from the first language spec. But that is not where most code is written, most Java, C and C++ has to exist now. Clearly C has only error codes, and it has the most bugs. Java has exceptions and finally to force the dev to handle everything right there, which I think is a huge source of anti-patterns but better than error codes. C++ has exceptions and destructors which work the best of these, but still separate error handling from code execute all the time when it is only desirable most of the time.