I have defined my own exceptions ans I get errors at compile time:
/home/me/my_proj/CMyExceptions.hpp:38:63: error: no matching function for call to ‘MyException1::MyException1()’
MyException2(const std::string& msg) : m_msg(msg) {}
^
/home/me/my_proj/CMyExceptions.hpp:38:63: note: candidates are:
/home/me/my_proj/CMyExceptions.hpp:23:3: note: MyException1::MyException1(const string&)
MyException1(const std::string& msg) : m_msg(msg) {}
^
/home/me/my_proj/CMyExceptions.hpp:23:3: note: candidate expects 1 argument, 0 provided
/home/me/my_proj/CMyExceptions.hpp:17:7: note: MyException1::MyException1(const MyException1&)
class MyException1 : public std::exception
^
My exceptions are:
class MyException1 : public std::exception
{
private:
std::string m_msg;
public:
MyException1(const std::string& msg) : m_msg(msg) {}
virtual ~MyException1() throw() {};
virtual const char* what() const throw()
{
return m_msg.c_str();
}
};
class MyException2 : public MyException1
{
private:
std::string m_msg;
public:
MyException2(const std::string& msg) : m_msg(msg) {}
virtual ~MyException2() throw() {};
virtual const char* what() const throw()
{
return m_msg.c_str();
}
};
What am I doing wrong? Shall I call the parent constructor (MyException1) before initialization?
You have m_msg in MyException1 and put it again in MyException2. This means MyException2 actually contains two m_msg variables. Is this what you intended?
The error message is because MyException1 does not have a default constructor, so MyException2 must call its constructor in the initialization list. I suggest
class MyException2 : public MyException1
{
public:
MyException2(const std::string& msg) : MyException1(msg) {}
};
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.
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
This question already has answers here:
Why does an overridden function in the derived class hide other overloads of the base class?
(4 answers)
Closed 7 years ago.
When compiling the following code :
class Base {
public:
Base(){}
virtual ~Base(){}
virtual bool equals(const Base* rhs) const { return false;}
};
class DerivedA : public Base {
public:
DerivedA() : Base(), val(0) {}
virtual ~DerivedA() {}
virtual bool equals(const DerivedA* rhs) const { return this->val == rhs->val;}
int val;
};
class DerivedB : public Base {
public:
DerivedB() : Base(), val(0) {}
virtual ~DerivedB() {}
virtual bool equals(const DerivedB* rhs) const { return this->val == rhs->val;}
int val;
};
int main() {
const DerivedA a;
const DerivedB b;
std::cout << a.equals(&b);
}
I get:
../main.cpp:104:26: error: no matching function for call to ‘DerivedA::equals(const DerivedB*) const’
std::cout << a.equals(&b);
^
../main.cpp:104:26: note: candidate is:
../main.cpp:88:15: note: virtual bool DerivedA::equals(const DerivedA*) const
virtual bool equals(const DerivedA* rhs) const { return this->val == rhs->val;}
^
../main.cpp:88:15: note: no known conversion for argument 1 from ‘const DerivedB*’ to ‘const DerivedA*’
But why doesn't it use the base class virtual bool equals(const Base* rhs) const?
bool DerivedA::equals(const DerivedA* rhs) const
is not an override of
bool Base::equals(const Base* rhs) const
but an other overload (as you may notice with override) which hides the base method.
If you just want to 'unhide' base method, you may add
using Base::equals;
into your derived class.
But to really solve your issue, you have to use multiple dispatch.
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 the following:
class Base
{
protected:
std::string _name;
public:
virtual ~Base(){}
const std::string &name;
Base()
: _name ("(no name)")
, name(_name)
{}
};
template <typename T>
class BaseH : public Base
{
public:
virtual ~BaseH() {}
BaseH() : Base() {}
T& operator~(){ ; return static_cast<T&>(*this);}
};
class One : public BaseH<One>
{
public:
One() : BaseH<One>() { _name = "One"; }
};
class Two
: public One
, public BaseH<Two>
{
public:
Two() : BaseH<Two>() { _name = "Two"; }
};
int main(int argc, char *argv[])
{
std::cout << Two().name << std::endl;
return 0;
}
I want to derive Two from both One and BaseH<Two>, because Two is a specialization of One, and the operator~ in BaseH must always return a reference of the type of the object that's calling it.
Compilation errors are obviously:
In constructor ‘Two::Two()’:
error: reference to ‘_name’ is ambiguous
error: candidates are: std::string Base::_name
error: std::string Base::_name
In function ‘int main(int, char**)’:
error: request for member ‘name’ is ambiguous
error: candidates are: const string& Base::name
error: const string& Base::name
How do I make _name and name accessible in both One and Two, while setting the const references via constructor delegation? What is the cleanest way to do that?
Looks like you've got the diamond problem. Have you tried virtual inheritance?
e.g.:
template <typename T>
class BaseH : virtual public Base
{
// ...
};
class One : virtual public BaseH<One>
{
// ...
};
edit: further reading on the diamond problem here: http://www.cprogramming.com/tutorial/virtual_inheritance.html