I'm quite iffy when it comes to C++ std:exception handling. Here's some sample code I found on the web, which I currently use.
class MyBaseException : public std::exception
{
public:
explicit MyBaseException(const std::string & message)
: m_Base(message.c_cstr()) {}
explicit MyBaseException(const char *message)
: m_Base(message) {}
virtual ~MyBaseException() throw () {}
protected:
typedef std::exception m_Base;
};
class MyDerivedException : public MyBaseException
{
public:
explicit MyDerivedException (const std::string & message)
: m_Base(message.c_cstr()) {}
explicit MyDerivedException (const char *message)
: m_Base(message) {}
virtual ~MyDerivedException () throw () {}
protected:
typedef MyBaseException m_Base;
};
Now, what I'd like to do is to automatically prepend every exceptions raised with the following scheme.
Some code raises a MyDerivedException exception with the following:
"original_exception_message"
When the MyDerivedException receives "original_exception_message", I'd like to prepend it with:
"Derived Exception Raised: "
And when MyBaseException receives the MyDerivedException exception, I'd like to prepend it with:
"Base Exception Raised: "
Such that the final message would look like this:
"Base Exception Raised: Derived Exception Raised: original_exception_message"
I gotta feeling I'm going to get all sorts of nasty replies on this, about bad concepts and bad practices... But I don't claim to be an expert.
Note that the prepend messages aren't actually that. They would be a little more informative.
Thanks in advance.
#include <iostream>
#include <exception>
class MyBaseException : public std::exception
{
public:
explicit MyBaseException(const std::string & message)
: m_message("Base Exception Raised: " + message) {}
virtual const char* what() const throw ()
{
return m_message.c_str();
}
private:
const std::string m_message;
};
class MyDerivedException : public MyBaseException
{
public:
explicit MyDerivedException (const std::string& message)
: MyBaseException("Derived Exception Raised: " + message) {}
};
int main()
{
try
{
throw MyDerivedException("derived");
}
catch(std::exception const& e)
{
std::cout << e.what();
}
return 0;
}
And read this link http://en.cppreference.com/w/cpp/error/exception
Related
I wrote the following code:
class GameException : public mtm::Exception {
};
class IllegalArgument : public GameException {
public:
const char *what() const noexcept override {
return "A game related error has occurred: IllegalArgument";
}
};
class IllegalCell : public GameException {
public:
const char *what() const noexcept override {
return "A game related error has occurred: IllegalCell";
}
};
How may I use inheritance here to prevent some code duplication? As you can see I'm returning the same sentence but with different ending (Which is the class name).
I though about implementing GameException as the following:
class GameException : public mtm::Exception {
std::string className;
public:
const char *what() const noexcept override {
return "A game related error has occurred: "+className;
}
};
But how may I change the value of className for the rest of my classes?
Plus, I'm getting the error:
No viable conversion from returned value of type
'std::__1::basic_string' to function return type 'const char *'
The error is because char [] + std::string yields a std::string but the method is delcared to return a const char *.
To avoid problems with returning a pointer to temporary, I would suggest this:
class GameException : public mtm::Exception {
std::string message;
public:
GameException(const std::string& pref)
: message("A game related error has occurred: " + pref)
{}
const char* what() const noexcept override {
return message.c_str();
}
};
Derived classes then only need
struct some_excpetion : GameException {
some_exception() : GameException("some_exception") {}
};
PS: Inheriting from std::runtime_error can be more convenient, because it already implements what() and comes with a constructor that takes the message to be returned by what(). You can basically remove your GameException and inherit from std::runtime_error instead.
Given the following classes:
#include <iostream>
using std::ostream;
class MatrixException: public std::exception {
public:
virtual ~MatrixException() {
}
virtual const char* what() throw ()const = 0; // error1 , error2
};
class BadDims: public MatrixException {
public:
const char* what() throw ()const override {
return "Bad dimensions";
}
};
Can someone explain me why I get the following errors?
expected ';' at end of member declaration
expected unqualified-id before '=' tokenov
What #VTT and the other guys said, BUT, std::exception::what is declared noexcept so you shouldn't be promising / threatening to throw anything in the first place.
Therefore, the code should look like this (after a bit of tidying up)
#include <exception>
class MatrixException : public std::exception {
public:
virtual ~MatrixException() { }
virtual const char* what() const noexcept = 0;
};
class BadDims : public MatrixException {
public:
const char* what() const noexcept override { return "Bad dimensions"; }
};
What mystifies me is why the OP's code compiles at all. Perhaps someone older (if that is possible) and wiser (err, ditto) can explain that to me.
Live demo.
I have two functions a() and b(), which are having own exception classes (consecutively a_exc and b_exc) that inherit from std::logic_error.
void a() { (...) throw a_exc(some_val) }
void b() { (...) throw b_exc(some_val) }
class a_exc : public std::logic_error
{
private:
int foo;
public:
a_exc(int val, const std::string& what_msg="Msg.")
: std::logic_error(what_msg), foo(val) {}
void show() { //show foo }
}
class b_exc : public std::logic_error
{
private:
std::string bar;
public:
a_exc(std::string val, const std::string& what_msg="Msg.")
: std::logic_error(what_msg), bar(val) {}
void show() { //show bar }
}
Let's say I have following part of code:
try {
a();
b();
}
catch (const std::logic_error& e)
{
e.what();
// e.show();
}
catch (const std::logic_error& e) catches both a_exc and b_exc. Of course this block cannot use e.show(), because catched obj is std::logic_error.
And here's my problem. I wonder if there is any chance to call show() method in std::logic_error catch block when catched exception was a_exc or b_exc. I know, calling show() is possible if I create separate catch blocks for a_exc and b_exc, but I want to call this method with using just one catch block. Is it possible?
You can, provided that show() is a const member function:
catch (const std::logic_error& e)
{
e.what();
if(const a_exc* a = dynamic_cast<const a_exc*>(&e))
a->show();
else if(const b_exc* b = dynamic_cast<const b_exc*>(&e))
b->show();
}
See it Live on Coliru. Though, it's usually a bad idea to call other functions that may throw in your catch exception handler.
Some thoughts on design.
Querying the type of exception within the catch block is logically no different to simply providing two catch blocks.
To be clear:
catch(X& x)
{
if (dynamic_cast<Y*>(&x)) {
// it's a Y
}
if (dynamic_cast<Z*>(&z)) {
// it's a Z
}
else {
// it's an X
}
}
is logically the same as:
catch(Y& t)
{
// it's a Y
}
catch(Z& z)
{
// it's a Z
}
catch(X& x)
{
// it's an X
}
Except that the second is clearer, more maintainable and resistant to inadvertent slicing on a subsequent copy.
The first is using "code to find code", which is always a maintenance disaster waiting to happen.
Your question raises more questions of its own:
Are a_exc and b_exc two kinds of the same error? If so, this argues for a polymorphic base class, which you can catch in preference to std::logic_error
Do you really need the show() method? Can you simply build the what string in the constructor, and pass this string to the constructor of std::logic_error? If this is at all possible, it is the route I would recommend. The moment you start adding special interfaces to exceptions, you pollute your entire code base with the necessity of knowing about this interface. If you're writing a library, you've now polluted every application that uses your library.
Assuming you do need show, and a_exc and b_exc really are two kinds of the same error, we can still avoid polymorphism. Perhaps we can shore the 'show' message as a string, and build it in the constructor. Now it's just data. No fuss, no complication.
(complete) example using polymorphic base class (a_exc an b_exc are kinds of the same thing)
#include <stdexcept>
#include <string>
struct showable_logic_error : std::logic_error
{
using std::logic_error::logic_error;
virtual void show() const = 0;
};
class a_exc : public showable_logic_error
{
private:
int foo;
public:
a_exc(int val, const std::string& what_msg="Msg.")
: showable_logic_error(what_msg)
, foo(val)
{}
void show() const override
{
//show foo
}
};
class b_exc : public showable_logic_error
{
private:
std::string bar;
public:
b_exc(std::string val, const std::string& what_msg="Msg.")
: showable_logic_error(what_msg)
, bar(val)
{}
void show() const override
{ //show bar
}
};
void a() { throw a_exc(1); }
void b() { throw b_exc("b"); }
int main()
{
try
{
a();
}
catch(showable_logic_error const& e)
{
e.show();
}
}
complete example in which no polymorphism is required:
#include <stdexcept>
#include <string>
#include <sstream>
struct message_builder
{
template<class T>
static std::string build_what(const std::string& whatstr, T&& info)
{
std::ostringstream ss;
ss << whatstr << " : " << info;
return ss.str();
}
};
class a_exc
: public std::logic_error
, private message_builder
{
public:
a_exc(int val, const std::string& what_msg="Msg.")
: std::logic_error(build_what(what_msg, val))
{}
};
class b_exc
: public std::logic_error
, private message_builder
{
private:
std::string bar;
public:
b_exc(std::string val, const std::string& what_msg="Msg.")
: std::logic_error(build_what(what_msg, std::move(val)))
, bar(val)
{}
};
void a() { throw a_exc(1); }
void b() { throw b_exc("b"); }
int main()
{
try
{
a();
}
catch(std::logic_error const& e)
{
e.show();
}
}
You should consider creating a derived type:
struct show_exc : public std::logic_error
{
virtual void show() = 0;
};
class a_exc : public show_exc
{
int foo_;
public:
virtual void show() override { /*...*/ };
};
and then use a distinguishing catch:
catch (const show_exc& e) {
// ..
}
catch (const std::logic_error& e) {
// ..
}
I understand that to properly catch exceptions using multiple inheritance I need to use virtual inheritance.
I'm not necessarily advocating the controversial use of multiple inheritance, but I do not want to design systems that make its usage impossible. Please do not distract from this question to advocate or attack the use of multiple inheritance.
So let's say I have the following base exception type:
class BaseException : public virtual std::exception {
public:
explicit BaseException(std::string msg)
: msg_storage(std::make_shared<std::string>(std::move(msg))) { }
virtual const char* what() const noexcept { return msg_storage->c_str(); }
private:
// shared_ptr to make copy constructor noexcept.
std::shared_ptr<std::string> msg_storage;
};
What is the proper way to create an exception hierarchy from BaseException?
My problem lies with constructing the exception types. Ideally every exception just constructs its parent, but this is impossible due to virtual inheritance. One solution would be to construct every parent up the chain:
struct A : public virtual BaseException {
explicit A(const std::string& msg) : BaseException(msg) { }
};
struct B : public virtual A {
explicit B(const std::string& msg, int code)
: BaseException(msg), A(msg), code_(code) { }
virtual int code() const { return code_; }
private:
int code_;
};
struct C : public virtual B {
explicit C(const std::string& msg, int code)
: BaseException(msg), A(msg), B(msg, code) { }
};
But this seems very repetitive and error-prone. Furthermore, this makes it impossible for constructors of exception types to add/change information passed in by their children before passing through to their respective parents.
I have found a reasonable solution that's not broken as far as I can see. It uses a slightly modified base exception type:
struct BaseException : virtual std::exception {
explicit BaseException(std::string msg)
: msg_storage(std::make_shared<std::string>(std::move(msg))) { }
virtual const char* what() const noexcept { return msg_storage->c_str(); }
protected:
BaseException();
private:
std::shared_ptr<std::string> msg_storage;
};
Then the rules are:
Every exception inherits publicly and virtually from its parent exceptions.
Every exception declares a protected default constructor and defines a protected constructor initializing all data members.
Every exception that is supposed to be Constructible defines a public constructor that directly calls the constructors defined in 2 for every ancestor.
All copy constructors should be noexcept.
An example hierarchy using this:
// A regular derived exception.
struct RuntimeError : virtual BaseException {
RuntimeError(std::string msg) : BaseException(std::move(msg)) { }
protected: RuntimeError() { }
};
// Derived exception with data member.
struct OSError : virtual RuntimeError {
OSError(std::string msg, int e) : BaseException(std::move(msg)), e(e) { }
virtual int error_code() const noexcept { return e; }
protected:
OSError();
OSError(int e) : e(e) { }
private:
int e;
};
// Non-constructible exception type.
struct FatalError : virtual RuntimeError {
protected: FatalError() { }
};
// A composed exception type.
struct FatalOSError : virtual FatalError, virtual OSError {
FatalOSError(std::string msg, int e)
: BaseException(std::move(msg)), OSError(e) { }
protected: FatalOSError() { }
};
I have made my own exception class which derives from runtime_error and is getting an int in the c'tor.
I would like to make a base class for this exception, in order to use polymorphism, so I could catch only the base class and basically I would be catching the derived class, and then call .what() method from it.
So, this is the base class: (ofc in another cpp file I got baseException::~baseException(){})
class baseException
{
virtual ~baseException()=0 {}
virtual const char* what()=0;
};
And this is the derived class:
class myException: public runtime_error, public baseException
{
public:
myException(int): runtime_error("Error occured") {}
const char* what() {return runtime_error::what();}
};
But when in the main I write:
catch(baseException* x)
{
cout<<x->what();
}
it just skips it and does not enter the block, even though myException inherits from baseException. Any suggests?
You should catch exceptions by reference (or const reference), not by pointer.
Your baseException doesn't have the what method, you should probably just derive baseException from runtime_error.
class baseException : public runtime_error
{
public:
baseException(const std::string& what) : runtime_error(what) {}
};
and then
class myException: public baseException
{
public:
myException(int): baseException("Error occured") {}
};
Although I prefer the following idiom:
class myException: public baseException
{
public:
myException(int x): baseException(getWhatMessage(x)) {}
private:
static std::string getWhatMessage(int x) { /*generate the message*/ }
};
On the catch part. If you throw using throw myException(5), then you should catch like this
catch(baseException& x)
{
cout<<x.what();
}
Your catching a reference to a baseException object; therefor you just know the methods of that class. baseException does not have a member called what() though. This causes the error.
Make baseException derive from runtime_error or catch a myException directly.
Edit:
This snippet shows that theres absolutely no reason why pointers shouldnt work together with exceptions:
#include <iostream>
#include <string>
class A {
public:
virtual int test() = 0;
};
class B : public A {
public:
virtual int test() {
return 42;
}
};
int _tmain(int argc, _TCHAR* argv[])
{
try {
throw new std::string("foo");
} catch (std::string* ecx){
std::cout << *ecx << std::endl;
}
try {
throw new B();
} catch (A* ecx) {
std::cout << ecx->test() << std::endl;
}
}
Output:
foo
42
UPDATE: this answer was based on the original version of the question. It now seems that the problem isn't calling what() (as you've worked around that by redeclaring it in your base class). The problem is simply that you're trying to catch a pointer and (I guess) throwing a value; the solution is to catch by reference:
catch (myException const & ex) {
std::cerr << ex.what() << std::endl;
}
(assuming you fix your declaration of what() to be const; if for some reason you really need it to be non-const, then remove const from the catch line).
ORIGINAL ANSWER describing how to call what() if it isn't declared in baseException:
I want to catch baseException*
You'd be better off catching baseException const &; there's no sensible way to throw a pointer.
and call their .what() methods
If you want to call what() , then you might be better off catching std::exception const & instead; unless you also want some functionality from your base class. In that case, perhaps your base class should inherit from std::runtime_error; or perhaps it should inherit from std::exception, in which case your myException type would need to use virtual inheritance.
If you really want to access what() from your classes as they stand, then you'll need to cross-cast to std::exception:
catch (myException const & ex) {
std::cerr << dynamic_cast<std::exception const &>(ex).what() << '\n';
}