Correct Way to Inherit from Std::Exception

Correct way to inherit from std::exception

If you want to make use of the string constructor, you should inherit from std::runtime_error or std::logic_error which implements a string constructor and implements the std::exception::what method.

Then it's just a case of calling the runtime_error/logic_error constructor from your new inherited class, or if you're using c++11 you can use constructor inheritance.

Should I inherit from std::exception?

The main benefit is that code using your classes doesn't have to know exact type of what you throw at it, but can just catch the std::exception.

Edit: as Martin and others noted, you actually want to derive from one of the sub-classes of std::exception declared in <stdexcept> header.

C++ Exceptions and Inheritance from std::exception

When you inherit privately, you cannot convert to or otherwise access that base class outside of the class. Since you asked for something from the standard:

§11.2/4:

A base class is said to be accessible if an invented public member of the base class is accessible. If a base class is accessible, one can implicitly convert a pointer to a derived class to a pointer to that base class (4.10, 4.11).

Simply put, to anything outside the class it's like you never inherited from std::exception, because it's private. Ergo, it will not be able to be caught in the std::exception& clause, since no conversion exists.

C++ create new exceptions by inheriting from the std::exception

You need to actually catch your exception:

try
{
throw stack_full_error("Stack is full!");
} catch(stack_full_error& ex)
{
std::cout << ex.what();
}

Is the `std::exception`, in its current form, redundant?

No, nothing stops you from doing this.

However, some code that wants to catch "any exception" will catch const std::exception&, and if your exception type doesn't derive from std::exception then that won't work.

Sure, we can catch ... instead but that's, in my experience, used as a last-ditch "blunt instrument" for avoiding termination due to uncaught exceptions, and can't tell you anything about the exception itself.

Boost exceptions don't derive from std::exception and it's really annoying.

Why not just make all the exceptions part of this standard hierarchy?

If you don't intend to ever let your exception types make get all the way to the top, then there may not be a practical problem here. But, why take the chance? You lose nothing by adding : std::runtime_error or somesuch, and the text string that you'll pass to the base is useful information for the diagnosing programmer.

Inherit Exceptions in C++

When you catch like this:

catch (TGAException e) {
cout << e.what() << endl;
}

The compiler makes a copy of the original exception and assigns it to e. It uses the TGAException copy constructor so the exception seen inside the catch block is not an ImagetypeException, it is a TGAException. This phenomenon is called object slicing.

If you catch it this way:

catch (const TGAException & e) {
cout << e.what() << endl;
}

No copy is needed and it will work the way you expect it to.

As a general guideline: Always catch exceptions by reference, and almost always catch them by const reference.

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

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)

How to inherit from std::runtime_error?

This is the correct syntax:

class err : public A, public std::runtime_error

And not:

class err : public A, public std::runtime_error("")

As you are doing above. If you want to pass an empty string to the constructor of std::runtime_error, do it this way:

class err : public A, public std::runtime_error
{
public:
err() : std::runtime_error("") { }
// ^^^^^^^^^^^^^^^^^^^^^^^^
};

Here is a live example to show the code compiling.

Can't catch class derived from std::exception by reference to std::exception

When you inherit from a base class during the definition of a class, the default access modifier for the inheritance is private. This means that the two following definitions are equivalent:

class derived : base { /* ... */ };
class derived : private base { /* ... */ };

The language doesn't allow1 you to refer to a derived class from a private base2. As an example, the following code does not compile:

int main()
{
derived d;
base& b = d; // <== compilation error
}
error: 'base' is an inaccessible base of 'derived'
base& b = d;
^

live example on wandbox.org


This is the reason why your catch block cannot handle Exception. Change your inheritance to public...

class Exception : public std::exception

...and your original code will work.

live example on wandbox.org


1 See [dcl.init.ref] and [conv.ptr].

2 Unless you're in the scope of derived itself. See this live example on wandbox.org.



Related Topics



Leave a reply



Submit