i´m moving c# c++ forgive me if question basic or has misconceptions...
i want build own exception used on try/catch blocks. need report custom exception code, custom exception message , custom exception source origin - may have or of these parameters.
so i´ve built class:
commonexception.hpp
namespace exceptionhelper { class commonexception : public std::exception { public: commonexception(); commonexception(std::string message); commonexception(std::string source, std::string message); commonexception(int code, std::string source, std::string message); virtual ~commonexception(); const char *what() const throw(); private: int exceptioncode; std::string exceptionsource; std::string exceptionmessage; }; }
and implementation:
commonexception.cpp
namespace exceptionhelper { commonexception::commonexception() { exceptioncode = 0; exceptionmessage = "no message."; exceptionsource = "no source."; } commonexception::commonexception(std::string message) { exceptioncode = 0; exceptionmessage = message; exceptionsource = "no source."; } commonexception::commonexception(std::string source, std::string message) { exceptioncode = 0; exceptionmessage = message; exceptionsource = source; } commonexception::commonexception(int code, std::string source, std::string message) { exceptioncode = code; exceptionmessage = message; exceptionsource = source; } commonexception::~commonexception() { } const char *commonexception::what() const throw() { std::stringstream s; s << "code : " << exceptioncode << std::endl; s << "source : " << exceptionsource << std::endl; s << "message : " << exceptionmessage << std::endl; return s.str().c_str(); } }
and implementation:
main () { try { ... code ... throw new commonexception(10, "here", "test exception"); } catch (const std::exception &exc) { std::cerr << "exception detected:" << std::endl; std::cerr << exc.what(); } catch (...) { std::cerr << "unknown exception called." << std::endl; throw; } }
for reason i´m getting result:
unknown exception called. terminate called after throwing instance of 'linuxcommon::exceptionhelper::commonexception*' aborted (core dumped)
questions:
a) why not catching custom exception ? b) i´m pretty sure there better ways exception handling, cannot figure out yet...
thanks helping...
some notes code.
you may want derive exception class
std::runtime_error
(instead ofstd::exception
), sincestd::runtime_error
provides constructor error message string. of course can add own exception's data members derived class.you don't need define virtual destructor empty body exception class, since don't have explicit cleanup code execute.
std::exception
has virtual destructor, , work fine derived exception class.you can use more idiomatic c++ syntax initialize exception data members in constructors, e.g. instead of:
commonexception::commonexception() { exceptioncode = 0; exceptionmessage = "no message."; exceptionsource = "no source."; }
you can use:
commonexception::commonexception() : exceptioncode(0), exceptionmessage("no message."), exceptionsource("no source.") { }
- if pass string parameters, can still pass value, may want
std::move()
value initialize data members, e.g. instead of:
commonexception::commonexception(std::string source, std::string message) { exceptioncode = 0; exceptionmessage = message; exceptionsource = source; }
you can do:
commonexception::commonexception(std::string source, std::string message) : exceptioncode(0), exceptionmessage(std::move(message)), exceptionsource(std::move(source)) { }
consider making single-string-argument constructor
explicit
, prevent bogus implicit conversions strings exceptions:explicit commonexception(std::string message);
in current form,
what()
method implementation can throw, because inserting operations (<<
) onstd::stringstream
can throw:
const char *commonexception::what() const throw() { std::stringstream s; s << "code : " + exceptioncode << std::endl; s << "source : " + exceptionsource << std::endl; s << "message : " + exceptionmessage << std::endl; return s.str().c_str(); }
so, remove throw()
specification, making simply:
const char* commonexception::what() const
(as side note, modern c++11 way of marking method non-throwing using noexcept
).
you may want use '\n'
instead of std::endl
avoid premature pessimization.
moreover, returning in line temporary string:
return s.str().c_str();
the const char*
pointer returned caller point garbage @ call site: introduces bug.
to fix that, may want consider adding std::string
data member, format whole error message string inside data member during exception object construction (i.e. in constructors - may build private helper method that, avoid repeating code in each constructor), , return m_str.c_str()
what()
method.
if derive exception class std::runtime_error
, can build whole error message string @ construction time, , pass std::runtime_error
's constructor. in case, std::runtime_error::what()
right thing, , won't need override what()
in exception class.
e.g.
// derive std::runtime_error instead of std::exception class commonexception : public std::runtime_error ... commonexception::commonexception( /* exception data */ ) : std::runtime_error(builderrormessage( /* exception data */ ) { } // private helper method std::string commonexception::builderrormessage( /* exception data */ ) { // build exception message string here, // e.g. can use std::ostringstream here, // , call str() method // return whole error message string. ... }
at exception's "client" side, have:
... code ... throw new commonexception(10, "here", "test exception"); } catch (const std::exception &exc)
instead, consider throwing by value, instead of dynamically allocating exception object on heap, e.g. do:
throw commonexception( /* exception data*/ );