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.
Is Virtual Inheritance necessary for Exceptions?
You're probably thinking about this Boost.Exception guideline, which I'll copy here for completeness:
Using Virtual Inheritance in Exception Types
Exception types should use virtual inheritance when deriving from other exception types. This insight is due to Andrew Koenig. Using virtual inheritance prevents ambiguity problems in the exception handler:
#include <iostream>
struct my_exc1 : std::exception { char const* what() const throw(); };
struct my_exc2 : std::exception { char const* what() const throw(); };
struct your_exc3 : my_exc1, my_exc2 {};
int
main()
{
try { throw your_exc3(); }
catch(std::exception const& e) {}
catch(...) { std::cout << "whoops!" << std::endl; }
}
The program above outputs "whoops!" because the conversion to std::exception is ambiguous.
The overhead introduced by virtual inheritance is always negligible in the context of exception handling. Note that virtual bases are initialized directly by the constructor of the most-derived-type (the type passed to the throw statement, in case of exceptions.) However, typically this detail is of no concern when boost::exception is used, because it enables exception types to be trivial structs with no members (there's nothing to initialize.) See Exception Types as Simple Semantic Tags.
Is it advisable to inherit from std::optional?
Is this still a bad idea? And if yes, what can go wrong?
As you already stated, inheriting from classes without virtual destructor leads to UB when destroyed from base class.
In addition, when inheriting from 3rd party library classes, you also depends of future interface.
You might be in trouble when/if std::optional
adds functions with same name (especially constructors). Depending of the "conflicts", your code might no longer compile, or worst, select the wrong overload and behave not as you expect.
Note that it is not only member functions, but also apply to free functions and so ADL. So it also applies when removing methods/function/overload (unlikely for std
though).
Less immediate problematic, even without conflicts, is that interface of your class change with function not necessary matching your expected interface.
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
Image Scaling (Keepaspectratiobyexpanding) Through Opengl
Is There a Reference_Wrapper<> for Rvalue References
How to Delete[] a Pointer That Points into an Allocated Array, But Not to the Start of It
Initializer List for Dynamic Arrays
How to Make Gcc Warn on Passing Too-Wide Types to Functions
Counting the Number of Occurrences of a String Within a String
How to Query a Running Process for Its Parameters List? (Windows, C++)
Std::Vector to String with Custom Delimiter
How to Deal with Global-Constructor Warning in Clang
Overriding Static Variables When Subclassing
Detecting Simulated Keyboard/Mouse Input
Differencebetween Cout, Cerr, Clog of iOStream Header in C++? When to Use Which One
Issue with Cin When Spaces Are Inputted, Using String Class
How to Create a Type in C++ That Takes Less Than One Byte of Memory
What Is the Most Efficient Way to Display Decoded Video Frames in Qt