Why does C++ allow to throw anything?

生来就可爱ヽ(ⅴ<●) 提交于 2021-02-08 19:42:06

问题


I just saw this question and its related answers. Considering I never ran into this way of using throws before, I was quite surprised to find out this is even possible.

  • What's the logic behind allowing (almost) anything to be thrown and caught?
  • Is there a use of the throw-catch syntax that goes beyond exception/error signaling? And if so, is that considered bad practice or are there "common" usages of this I was never aware of?

回答1:


This is hard to answer without speculation, but Bjarne's 1998 paper "An Overview of the C++ Programming Language" uses arbitrary types when describing exception handling, and suggests creating a hierarchy of said types for convenient/semantics. It would seem that he did not have a "base class" of exception in mind for any of these in the beginning.

It's possible that the notion of having a standard hierarchy (based on std::exception) began life as an "addition", a convenient way to approach Bjarne's suggested use of exceptions, rather than the building-blocks on which everyone's use of exceptions should be based. That contemporary practice is to derive all exceptions from std::exception would seem to have come along later.

Nowadays, I can't think of a good reason not to do that, if for no other reason than people using your code will probably expect a top-level catch (const std::exception&) to suck up anything useful. I do also tend to put a catch (...) in main, though, just in case.

Speaking more practically, if this weren't the case, there would have to be additional rules constraining throw to only be "valid" on expressions with type deriving from std::exception, which would not seem to have any real-world benefit sufficient to justify the additional rules. C++, believe it or not, comes from a place of minimalism in terms of the question "why don't we have such-and-such a rule", although obviously its bloat would seem to contradict this after all these years.

I doubt this has anything to do with using throw for non-exceptional things, because that has always been considered bad practice. The way Bjarne describes this feature is:

Exceptions are used to transfer control from a place where an error is detected to some caller that hasexpressed interest in handling that kind of errors. Clearly, this is a mechanism that should be used only for errors that cannot be handled locally. [..] Exceptions can be used to make error handling more stylized and regular.

So it's clear that at least the original design intent (and, again, this is still common wisdom) is to use exceptions for exceptional/errory cases only.




回答2:


1. You can throw anything because C++ does not define the purpose of specific classes as java or C# do. In this languages you can only throw objects of classes which inherit from their specified exception class. C++ does not have the one exception class(nobody forces you to use std-stuff).

2. Using throw/catch to signal non-error messages is called exception driven development and is indeed considered bad practice. exception driven development leads to code that's hard to understand. It also can result in sections of code not getting executed unintentionally. I highly recomment against doing this.




回答3:


When the handler is entered, e will be a copy of the Int_overflow object that was created inside the add function to describe what went wrong. The parallel to function calls is now almost exact: The throw-expression passes an Int_overflow object to the handler declared to accept objects of class Int_overflow. The usual initialization semantics are used to pass this argument. The type of the object thrown is used to select the handler in approximately the way the arguments of a function call is used to select an overloaded function. Again, a slightly different way of looking at the throw-expression is as a return statement where the argument is not only passed back to the caller, but is also used to select which caller to return to.
[...]
Relying of such fundamental and well-supported language concepts rather than inventing some special ‘‘exception type’’ ensures that the full power of C++ is available for the definition and use of exceptions.

"Exception Handling for C++", Andrew Koenig, Bjarne Stroustrup, 1989

This may answer your question about the logic behind that behavior. The creators of C++ wanted to use pre-existing technology to implement the new feature.

For your question about legitimate use of that functionality I'll give you another quote from the same publication:

We do not wish to use exception handling as a substitute for more conventional control structures

I leave it to you and other commenters to decide if more modern practices may have surpassed the initial ideas of the inventors.




回答4:


C++ has a general philosophy of allowing the programmer to do whatever they like (and to shoot themselves in the foot), most restrictions are only in place to enable portability and even some of those aren't enforced by some compilers.

If you don't need (the admittedly small) overhead of creating a std::exception object C++ doesn't force you to pay for it. For example you might throw an error code directly, this is much easier than creating a subclass of std::exception with an error code member. Of course the caller of your code needs to know to expect to catch numbers not std::exception subclasses. For this reason in general it's better to only throw subclasses of std::exception but you don't have to.




回答5:


I'm not Bjarne Stroustrup, but I'll try to give an answer.

What's the logic behind allowing (almost) anything to be thrown and caught?

The convention is to throw a derivative of std::exception from the standard library. If you limit what can be thrown, you're confined to using only that. C++ tries to: 1. Give you a lot of flexibility 2. Manage the already complicated complexity of the language By letting the language throw and catch anything, you're giving the programmer flexibility. You're also making the language less complex, by moving std::exception to the standard library instead of it being part of the language itself.

Is there a use of the throw-catch syntax that goes beyond exception/error signaling?

Yes, you can use it for passing signals. It's an ill-advised anti-pattern (abuse).



来源:https://stackoverflow.com/questions/53629837/why-does-c-allow-to-throw-anything

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!