Vasilly.Prokopyev
Vasilly.Prokopyev

Reputation: 874

Class that is privately inherited from std::runtime_error is not caught as std::exception

It's all in this example

class MyException: std::runtime_error // note, there is no public keyword in inheritance
{
public:
   MyException(const std::string & x)
      : std::runtime_error(x)
   {}
};


int main( )
{
   try
   {
      throw MyException("foo");
   }
   catch (std::exception & e )
   {
      std::cout << "catched std exception: " << e.what() << std::endl;
   }
   catch (...)
   {
      std::cout << "catched ... " << std::endl;
   }
}

It writes on stdout string "catched ...". But, if I change inheritance to public as class MyException : public std::runtime_error, it works as expected (for me) and writes "catched std exception: foo"

What part of the c++ standard requires such behavior? And why? In what cases such behavior could be useful?

Upvotes: 1

Views: 511

Answers (3)

juanchopanza
juanchopanza

Reputation: 227518

It makes sense and is consistent with the rules for overload resolution. Outside of MyException, your class is-not-an std::exception. You should see private inheritance as an implementation detail (with very high coupling.)

It is in 15.3 Handling an exception:

A handler is a match for an exception object of type E if

— The handler is of type cv T or cv T& and E and T are the same type (ignoring the top-level cv-qualifiers), or

— the handler is of type cv T or cv T& and T is an unambiguous public base class of E, or

— the handler is of type cv1 T* cv2 and E is a pointer type that can be converted to the type of the handler by either or both of - a standard pointer conversion (4.10) not involving conversions to pointers to private or protected or ambiguous classes — a qualification conversion

— the handler is a pointer or pointer to member type and E is std::nullptr_t.

(emphasis mine)

Upvotes: 3

ravi
ravi

Reputation: 10733

Because private inheritance doesn't allow you to treat Derived*/Derived& as Base*/Base&. That means you cannot put Derived* where Base* is expected.

Actually private inheritance is used when you just want implementation of some class without accepting it's interface...

Upvotes: 3

ForEveR
ForEveR

Reputation: 55897

It's private inheritance, MyException is not convertible to std::runtime_error.

Upvotes: 2

Related Questions