c++ exception : throwing std::string
Yes. std::exception
is the base exception class in the C++ standard library. You may want to avoid using strings as exception classes because they themselves can throw an exception during use. If that happens, then where will you be?
boost has an excellent document on good style for exceptions and error handling. It's worth a read.
C++ Exception - Throw a String
You are currently throwing a const char*
and not a std::string
, instead you should be throwing string("error")
edit: the error is resolved with
throw string("exception ! error");
String throwing exception
I do not know what you are trying to experiment, but despite being allowed by the language, throwing objects that are not instances of (subclasses of) std::exception
should be avoided.
That being said you have a bunch of inconsistencies in your code.
First cin >> x.second;
will stop at the first blank character. So in your example you have only "1,"
in x.second
, so you test fails and you code does not throw anything.
You should ignore the newline left by cin >> x.first
and use getline
to read a full line include spaces:
P x;
cin >> x.first;
cin.ignore();
std::getline(cin, x.second);
The first try
block invokes UB, because you are declaring a new x
in that block that will hide the one you have just read. It should be:
try
{
//P x; // do not hide x from the enclosing function!
T(x);
}
Finaly, and even it is not an error you should always catch non trivial object by const reference to avoid a copy. Remember that exceptions are expected to be raised in abnormal conditions, and when memory becomes scarce you should avoid copy. But you must catch the exact same object that was thrown. So the second catch
should be:
catch (std::string exception)
{
std::cout << "\n" << exception;
}
or better (avoid a copy):
catch (const std::string& exception)
{
std::cout << "\n" << exception;
}
How to throw std::exceptions with variable messages?
Here is my solution:
#include <stdexcept>
#include <sstream>
class Formatter
{
public:
Formatter() {}
~Formatter() {}
template <typename Type>
Formatter & operator << (const Type & value)
{
stream_ << value;
return *this;
}
std::string str() const { return stream_.str(); }
operator std::string () const { return stream_.str(); }
enum ConvertToString
{
to_str
};
std::string operator >> (ConvertToString) { return stream_.str(); }
private:
std::stringstream stream_;
Formatter(const Formatter &);
Formatter & operator = (Formatter &);
};
Example:
throw std::runtime_error(Formatter() << foo << 13 << ", bar" << myData); // implicitly cast to std::string
throw std::runtime_error(Formatter() << foo << 13 << ", bar" << myData >> Formatter::to_str); // explicitly cast to std::string
Throw string exception from inherited exception class
You are experiencing object slicing.
This happens when a derived instance is received by value as its base class -- In your case, catching std::exception
by value. Your derived class' member is "sliced off" in the process of conversion to the base class.
Receiving by pointer or by (const) reference is always preferable when you expect to use a parameter polymorphically. For catching a std::exception
you should always catch by const reference (I can't really think of a scenario where you wouldn't).
Can std::string::compare(const char*) throw an exception?
Except for destructors, swap functions, move constructors and move assignment operators, the standard marks a function noexcept
only if it has a wide contract, i.e., it has no preconditions. This overload requires the argument to be a null-terminated string, so the standard does not mark it as noexcept
.
The rational is specified in N3248:
Functions marked
noexcept
are difficult to test
When a function is marked with
noexcept
it becomes impossible to flag test failures,
notably in test drivers, by throwing an exception. A common example would be code
that validates preconditions on entry to a function:T& std::vector<T>::front() noexcept {
assert(!this->empty());
return *this->data();
}
When validating such defensive checks from a test driver, a reasonable approach is to
register an assert-handler that throws a well-defined precondition-violated exception,
which the test driver catches to ensure that the appropriateassert
s are indeed in
place....
Now we might argue that calling the function out-of-contract, when the
vector
is
empty, is undefined behavior so we should not expect any guarantees. The problem is that undefined behavior is being specified by the library; to the compiler, this code is
perfectly well defined and, ifassert
throws an exception, the program must terminate
in a well-specified manner, thwarting the test driver.Note that the issue here is not that we are using assertions to find bugs in our own
library implementations, but rather in user code that incorrectly calls into our library.
If we remove the ability to test these defensive assertions, we may get them wrong,
and thus put our users at risk for committing far more serious errors than propagating
an unexpected exception.
By the way, due to [res.on.exception.handling]/5:
An implementation may strengthen the exception specification for a non-virtual function by adding a non-throwing exception specification.
... libstdc++
and libc++
are free to mark this overload noexcept
.
C++ Exceptions - Is throwing c-string as an exception bad?
It is much better to throw a standard exception object. In general, the best practice is to throw something derived from std::exception
so that if in some situation it does cause your program to terminate, the implementation has a better chance of printing a useful diagnostic.
Because it isn't hard to do this, I would never recommend throwing a raw string literal.
#include <stdexcept>
void someFunction()
{
try {
// code
if (some error) {
throw std::runtime_error( "Description of error." );
}
}
catch (const std::exception& ex) {
std::cerr << ex.what() << "\nFatal error" << std::endl;
}
}
Related Topics
Hide User Input on Password Prompt
How to Write an Eof Character Ourselves
How to Detect/Avoid Memory Leaks in Your (Unmanaged) Code
C++ Double Address Operator? (&&)
Do Class/Struct Members Always Get Created in Memory in the Order They Were Declared
Loading 8 Chars from Memory into an _M256 Variable as Packed Single Precision Floats
Variadic Function Template with Pack Expansion Not in Last Parameter
Overloading Operator<<: Cannot Bind Lvalue to 'Std::Basic_Ostream<Char>&&'
How Does One Securely Clear Std::String
Why Does Windows 10 Start Extra Threads in My Program
How to Use Createfile, But Force the Handle into a Std::Ofstream
Difference Between C++03 Throw() Specifier C++11 Noexcept
How to Use Standard Library (Stl) Classes in My Dll Interface or Abi
C++ Array Assignment of Multiple Values
Std::String::C_Str() and Temporaries