virtual method in exceptions - c++

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';
}

Related

Error with definition of "(abstract) exception class" with function "what()"

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.

Calling method from own exception class catched by its base class

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) {
// ..
}

What is the proper way to create an exception hierarchy?

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() { }
};

Inherit custom exception class from both boost::exception and std::runtime_error

I would like to introduce a hierarchy of my custom exception classes, derived both from boost::exception and std::runtime_error so that what() returns something meaningful.
So far I had no luck:
#include <iostream>
#include <stdexcept>
#include <boost/exception/all.hpp>
typedef boost::error_info<struct tag_foo_info, unsigned long> foo_info;
struct foo_error : virtual boost::exception, virtual std::runtime_error
{
explicit foo_error(const char *const what)
: std::runtime_error(what)
{ }
};
static void foo()
{
BOOST_THROW_EXCEPTION(foo_error("foo error") << foo_info(100500));
}
int main(int argc, char *argv[])
{
try
{
foo();
}
catch (const std::exception& e)
{
std::cerr << boost::diagnostic_information(e);
return 1;
}
return 0;
}
just keeps complaining that there are no appropriate default constructor available for std::runtime_error.
The closest I can get is to throw an actual std::runtime_error using
BOOST_THROW_EXCEPTION(boost::enable_error_info(std::runtime_error("foo error")) << foo_info(100500)))
but that's not really what I want. Basically, I want an exception class being catchable by catch (const std::exception& e), catch (const std::runtime_error& e), catch (const boost::exception& e) and catch (const foo_error& e). Is that possible? Thank you in advance.
You need public inheritance
struct Exception : public boost::exception, public std::runtime_error
{
Exception()
: std::runtime_error("Hello World")
{}
};
int main()
{
try {
try {
throw Exception();
}
catch(const std::runtime_error&) {
std::cout << "std::runtime_error" << std::endl;
throw;
}
}
catch(const boost::exception&) {
std::cout << "boost::exceptionr" << std::endl;
}
return 0;
}
Your code will work if you replace the two virtual:
Throw in function void foo()
Dynamic exception type: boost::exception_detail::clone_impl<foo_error>
std::exception::what: foo error
[tag_foo_info*] = 100500
The boost exception library has a class deriving from your exception:
// Curiously recurring template pattern (exception.hpp:419:20)
class clone_impl: public Exception, public clone_base;
Due to virtual inheritance the most derived class is responsible to initialize the base classes (clone_impl does not)
std::runtime_error already inherits from std::exception. So you only need inherit std::runtime_error and you'll get both.
UPDATE:
I meant inheriting only std::runtime_error. What if you try this:
#include <iostream>
#include <stdexcept>
struct foo_error : public std::runtime_error
{
explicit foo_error(const char *const what)
: std::runtime_error(what)
{ }
};
static void foo()
{
throw foo_error("foo error");
}
int main(int argc, char *argv[])
{
try
{
foo();
}
catch (const std::exception& e)
{
std::cerr << boost::diagnostic_information(e);
return 1;
}
return 0;
}
left out the boost stuff for simplicity.

Exception does not get caught

I have a base and a derived exceptions, public inner classes of store:
//base class - ProductException
class ProductException: exception
{
protected:
const int prodNum;
public:
//default+input constructor
ProductException(const int& inputNum=0);
//destructor
~ProductException();
virtual const char* what() const throw();
};
//derived class - AddProdException
class AddProdException: ProductException
{
public:
//default+input constructor
AddProdException(const int& inputNum=0);
//destructor
~AddProdException();
//override base exception's method
virtual const char* what() const throw();
};
this function which throws the derived exception:
void addProduct(const int& num,const string& name) throw(AddProdException);
void Store::addProduct( const int& num,const string& name )
{
//irrelevant code...
throw(AddProdException(num));
}
and a function which calls the function and tries to catch an exception:
try
{
switch(op)
{
case 1:
{
cin>>num>>name;
st.addProduct(num,name);
break;
}
}
}
...
catch(Store::ProductException& e)
{
const char* errStr=e.what();
cout<<errStr;
delete[] errStr;
}
The derived class should get caught, but I keep getting the error "unhandled exception". Any ideas why? Thanks!
The reason is that AddProdException is not a ProductException, because you are using private inheritance:
class AddProdException: ProductException {};
You need to use public inheritance:
class AddProdException: public ProductException {};
The same applies to ProductException and exception, assuming the latter is an std::exception.
Without the public keyword, inheritance is considered private by default. This means AddProdException is-not a ProductException. Use public inheritance like so:
class AddProdException : public ProductException
{
public:
//default+input constructor
AddProdException(const int& inputNum=0);
//destructor
~AddProdException();
//override base exception's method
virtual const char* what() const throw();
};
Also, inherit from std::exception publicly in ProductException as well, otherwise you won't be able to catch std::exceptions either (or even better, from std::runtime_error).