I have a try catch statement in my main function
try
{
app.init();
}
catch(std::string errorMessage)
{
std::cout << errorMessage;
return 1;
}
but when I throw "SOME_ERROR"; The console output is simply
terminate called after throwing an instance of 'char const*'
Aborted (core dumped)
How can I make errorMessage output to the console?
Please do not throw anything which is not derived from std::exception.
An exemption might be an exception intended to terminate the program (providing an internal state, though)
You either intend to throw std::string OR catch const char*:
throw std::string("error")
catch(const char* message)
However as pointed out, it's better just to derive from std::exception:
#include <iostream>
// must include these
#include <exception>
#include <stdexcept>
struct CustomException : std::exception {
const char* what() const noexcept {return "Something happened!\n";}
};
int main () {
try {
// throw CustomException();
// or use one already provided
throw std::runtime_error("You can't do that, buddy.");
} catch (std::exception& ex) {
std::cout << ex.what();
}
return 0;
}
You need to derive something from std::exception. <--if you want memory safety
It has a method: virtual const char* ::std::exception::what() const noexcept;
Build your char* you want to see in the constructor, store it, return it for what() then free it in the destructor for memory safe exceptions.
Related
I am taking a course online and came across some syntax I am not really sure I understand.
#include <iostream>
#include <exception>
using namespace std;
class derivedexception: public exception {
virtual const char* what() const throw() {
return "My derived exception";
}
} myderivedexception;
int main() {
try {
throw myderivedexception;
}
catch (exception& e) {
cout << e.what() << '\n';
}
}
My Problem is with:
virtual const char* what() const throw()
What does this line mean?
also, what is with the
} myderivedexception;
in the end of the class declaration?
This line:
virtual const char* what() const throw()
says that what is a virtual method that returns a pointer to a constant char (which means it can be used to return a string literal, or the contents of a std::string obtained by calling the string::c_str() function), is itself constant so it doesn't modify any class members, and it does not throw any exceptions.
This line:
} myderivedexception;
creates an instance of the derivedexception class named myderivedexception. You probably do not want to do this, but instead throw an unnamed exception:
throw derivedexception();
I've problem with exceptions:
#include <iostream>
#include <cstring>
#include <exception>
class except :public std::exception
{
char* err;
public:
except(const char* s) noexcept
{
err = new char[strlen(s) + 1];
strcpy(err, s);
err[strlen(s)] = 0; //is it necessary??
}
virtual const char* what() noexcept
{return err;}
virtual ~except() noexcept
{delete err;}
};
double div(const double& a, const double& b) noexcept
{
if (b == 0.0)
throw except("DIVIDED BY 0");
return a / b;
}
int main()
{
try
{
std::cout << div(5.0, 0.0);
}
catch (std::exception &ex)
{
std::cout << ex.what();
}
return 0;
}
I want to print "DIVIDED BY 0" but I get:
terminate called after throwing an instance of 'except'
what(): std::exception
Aborted
Process returned 134 (0x86)
Shall I put noexcept in every function/member function that doesn't throw any exceptions?
Is err[strlen(s)] = 0 necessary? (in except::except(const char* s))
I want to print "DIVIDED BY 0" but I get: terminate called after throwing an instance of 'except'
double div(const double& a, const double& b) noexcept
You are claiming that you won’t throw an exception, but you are lying. The result is the call to std::terminate when you actually throw.
The problem is a actually twofold. Firstly, as #manni66 suggests, div should not be declared noexcept and this does cause a run-time error, but removing it does not solve the issue.
The second problem is that what has been declared:
virtual const char* what() noexcept;
whereas it's declared in std::exception as:
virtual const char* what() const noexcept;
and this difference in signature means that when it's caught by the handler for std::exception, it calls std::exception::what() and not except::what()
A couple of points worth mentioning:
Ensure that your function overloads exactly match those in the base class.
If you are expecting a certain type of exception to be thrown then try to catch that first with a specific handler and use an appropriate name for the exception for clarity.
As others have mentioned, please try to use the std::string class if you can. It will make things easier and safer. Although in this case, as point two eludes to, a string member is not really necessary as the class is specific enough not to need further qualification.
Don't create an exception class unless it's adding some specific value (though the value, may simply be that you want to specifically catch a certain type of exception and handle in a certain way.) If you wanted a more general exception then std::runtime_error or in this case std::overflow_error would be decent choices and both take a std::string as an argument to the constructor, so no need to create your own exception class.
For example:
#include <exception>
using namespace std;
class divide_by_zero : public std::exception
{
public:
virtual const char* what() const noexcept { return "DIVIDED BY 0"; }
};
double div(const double& a, const double& b)
{
if (b == 0.0)
throw divide_by_zero();
return a / b;
}
int main()
{
try
{
std::cout << div(5.0, 0.0);
}
catch (divide_by_zero &ex)
{
std::cout << ex.what();
}
catch (std::exception &ex)
{
std::cout << ex.what();
}
return 0;
}
Output:
DIVIDED BY 0
I have a function using try-catch. so I want use and another class to print out different kind of messages. What should I do?
I use namespace std. I'm new at this an not familiar with using namespace std. Please guide me thanks.
SparseException::SparseException ()
{ }
SparseException::SparseException (char *message)
{ }
void SparseException::printMessage () const
{
// ...
}
try
{
//did some stuffs here.
}
catch (exception e)
{
char *message = "Sparse Exception caught: Element not found, delete fail";
SparseException s (message);
s.printMessage();
}
Derive your exception class from std::exception and override what(). Remove your function printMessage and implement (override):
virtual const char* what() const throw();
In C++11 this function has this signature:
virtual const char* what() const noexcept;
Then your catch clause and printing of exception's reason can look like this:
catch (const std::exception& e)
{
std::cerr << "exception caught: " << e.what() << '\n';
}
Or if you are going to throw only your exception, you can simply do this:
SparseException::SparseException ()
{ }
SparseException::SparseException (char *message)
{ }
void SparseException::printMessage () const
{
// ...
}
try
{
//did some stuffs here.
//Possibly
//throw SparseException();
//or
//throw SparseException("Some string");
//Make sure you can throw only objects of SparseException type
}
catch (SparseException e)
{
e.printMessage();
}
If the line with throw is executed, the result of try block will be terminated and the catch block will execute, where e is the object you have thrown.
I have a silly question. I read this article about std::exception http://www.cplusplus.com/doc/tutorial/exceptions/
On catch (exception& e), it says:
We have placed a handler that catches exception objects by reference (notice the ampersand & after the type), therefore this catches also classes derived from exception, like our myex object of class myexception.
Does this mean that by using "&" you can also catch exception of the parent class? I thought & is predefined in std::exception because it's better to pass e (std::exception) as reference than object.
The reason for using & with exceptions is not so much polymorphism as avoiding slicing. If you were to not use &, C++ would attempt to copy the thrown exception into a newly created std::exception, potentially losing information in the process. Example:
#include <stdexcept>
#include <iostream>
class my_exception : public std::exception {
virtual const char *what() const throw() {
return "Hello, world!";
}
};
int main() {
try {
throw my_exception();
} catch (std::exception e) {
std::cout << e.what() << std::endl;
}
return 0;
}
This will print the default message for std::exception (in my case, St9exception) rather than Hello, world!, because the original exception object was lost by slicing. If we change that to an &:
#include <stdexcept>
#include <iostream>
class my_exception : public std::exception {
virtual const char *what() const throw() {
return "Hello, world!";
}
};
int main() {
try {
throw my_exception();
} catch (std::exception &e) {
std::cout << e.what() << std::endl;
}
return 0;
}
Now we do see Hello, world!.
Does this mean that by using "&" you can also catch exception of the parent class?
No, this doesn't increase the scope of where you will catch exceptions from (e.g. from the parent class of the class that contains the try/catch code).
It also doesn't increase the types of exceptions that can be caught, compared to catching by value (catch(std::exception e) without the & - you'll still catch each exception that either is std::exception or derives from it).
What it increases is the amount of data that you will actually get when you catch the exception.
If an exception is thrown that derives from std::exception, and you catch it by value, then you are throwing out any extra behavior in that exception class. It breaks polymorphism on the exception class, because of Slicing.
An example:
class MyException : public std::exception
{
public:
virtual const char* what() const
{
return "hello, from my exception!";
}
};
// ...
try
{
throw MyException();
}
catch(std::exception& e)
{
// This will print "hello, from my exception!"
std::cout << e.what() << "\n";
}
// ...
try
{
throw MyException();
}
catch(std::exception e)
{
// This will print "Unknown exception"
std::cout << e.what() << "\n";
}
No the & has absolutely no bearing on the polymorphic nature of exception handlers. Their wording is very poor, it does seem to indicate that the & is somehow responsible. This is not the case. You are correct, & just passes by reference which is a tad more efficient.
Also as a general rule, you should really try to avoid cplusplus.com.
Updated link: What's wrong with cplusplus.com
Using reference to exception here can reduce the temporary objects created, and it can also keep the polymorphism.
I want to call a function that may throw an exception. If it does throw an exception, I want to catch it and pass the exception object to a handler function. The default implementation of the handler function is simply to throw the exception. Here is whittled-down code to illustrate the issue:
struct base_exception : exception {
char const* what() const throw() { return "base_exception"; }
};
struct derived_exception : base_exception {
char const* what() const throw() { return "derived_exception"; }
};
void exception_handler( base_exception const &e ) {
throw e; // always throws a base_exception object even if e is a derived_exception
}
int main() {
try {
throw derived_exception();
}
catch ( base_exception const &e ) {
try {
cout << e.what() << endl; // prints "derived_exception" as expected
exception_handler( e );
}
catch ( base_exception const &e ) {
cout << e.what() << endl; // prints "base_exception" due to object slicing
}
}
}
However, the throw e in exception_handler() throws a copy of the static type of the exception, i.e., base_exception. How can I make exception_handler() throw the actual exception having the correct run-time type of derived_exception? Or how can I redesign things to get what I want?
You can put a throw_me virtual function in the base exception class, and have every derived class override it. The derived classes can throw the proper most derived type, without slicing. Even though the function has the same definition in each class, they're not the same - the type of *this is different in each case.
struct base_exception : exception
{
char const* what() const throw() { return "base_exception"; }
virtual void throw_me() const { throw *this; }
};
struct derived_exception : base_exception
{
char const* what() const throw() { return "derived_exception"; }
virtual void throw_me() const { throw *this; }
};
void exception_handler( base_exception const &e ) {
e.throw_me();
}
You can use throw; to re-throw the exception that was caught. You could also use a template.
template<typename T> void rethrow(const T& t) { throw t; }
Throw by value, catch by reference. It'll save you a lot of headaches.
What you are looking for is called "propagating" the exception. To do so, you have to use the throw keyword without parameters inside the catch block. It will not copy the exception and the exception will be caught by the next catch block on its way or will make your program abort if it's not caught again.