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).
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 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 this piece of code:
class object
{
public:
virtual ~object(){ }
bool equals(const object& J)const
{
return &J == this;
}
int operator==(const object& J)const
{
return equals(J);
}
virtual int getHash()const;
virtual void getType()const;
void* operator new(size_t size)
{
void*mem = malloc(size);
return mem;
}
};
class notcopyable
{
private:
notcopyable(const notcopyable&){}
notcopyable& operator=(const notcopyable&){}
public:
notcopyable(){}
};
class exception :
public object,public notcopyable
{
private:
public:
virtual ~exception();
virtual const char* info();
};
class exception_not_implemented :
public exception
{
public:
exception_not_implemented()
{
}
virtual const char* info()
{
return "exception_not_implemented: ";
}
};
class exception_oob :public exception
{
public:
exception_oob()
{
}
virtual const char* info()
{
return "Index out of boundary";
}
};
There are two functions throw exception_not_implemented:
void object::getType()const
{
throw exception_not_implemented();
}
int object::getHash()const
{
throw exception_not_implemented();
}
And getting this error:
error C2248: 'js::notcopyable::notcopyable' : cannot access private member declared in class 'js::notcopyable'
The output of the compiler says:
This diagnostic occurred in the compiler generated function 'js::exception::exception(const js::exception &)'
If I delete the two throw shown above, it works well. But the same error doesn't happens to exception_oob. I can't figure out why.
You can temporarily add a private copy constructor declaration, which will generate an error at the point where a copy is being made. Then you can fix that code to not make copies.
The error should happen at other place where you call the (private) copy constructor.
For example:
Exception a;
Exception b = a; // error : cannot access private member ...
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';
}