Pages

Sunday, 30 November 2014

C++ Exceptions

In this post I want to discuss about exceptions in c++ specifically related to c++98/03. The syntax that we can use to specify whether a function can throw exception is

function_name() throw()

The keyword here is throw, the keyword tells the compiler that the specific function can throw. But, unlike Java the caller of this method is not forced to catch the exception. There is no concept of checked and runtime exception in c++. We can say that exceptions in c++ is always runtime. We can decorate the keyword throw with more information by specifying what sort of exception it will throw as shown below

function_name() throw(int)

The above tells the compiler that this function will throw an exception of type int and only int. So what will happen if for some reason the function end of throwing an exception other than int? The application will terminate in such a case. It is possible to add a hook to call user defined function when terminate is called, refer to this link for more details set_terminate

Let us create a simple c++ program to see what happens in different cases
  
  #include<exception>
  #include<string>
  #include<iostream>

   void funcThrowInt() throw(int) {
      throw 1;
   }
   
   //even though we actually throwing double but in the signature we specify that we are throwing int
   void funcThrowDouble() throw(int) {
      throw 1.0
   }

   void funcInt() throw() {
       throw 1;
  }

  void funcDouble() throw() {
      throw 1.0;
  }

  void funcString() throw() {
      throw std::string("error");
  }

  void funcIntWithoutThrow() {
     throw 1;
  }

  void funcDoubleWithoutThrow() {
     throw 1;
  }

  void funcStringWithoutThrow() {
     throw 1;
  } 

  int main() {
     try {
             //we will try each of these functions in turn
     } catch (const int& e) {
       std::cout << "caught in int" << std::endl;
     } catch(const double& e) {
       std::cout << "caught in double" << std::endl;
     } catch (const std::exception& e) {
        std::cout << "caught in exception" << std::endl;
     } catch(...) {
        std::cout << "caught in all" << std::endl;
     }
  }


Let us try now to call the method funcThrowInt() and see what happens. It display the message "caught in int" which is expected as we promised to throw only int and we are keeping to our promise.

Let us now try to call the method funcThrowDouble(). Here we are violating the promise as even though we declared that we will throw only int but we end up throwing double. As expected the application terminates.

What if we do not specify what type we will throw; can we then throw anything we want? This is what happens

  • funcInt()  :  application terminates
  • funcDouble() : application terminates
  • funcString() :  application terminates
So using the syntax throw () is similar to noexcept() in c++11

Finally, let us try the last option of not specifying the throw keyword

  • funcIntWithoutThrow()  : caught in int
  • funcDoubleWithoutThrow() : caught in double
  • funcStringWithoutThrow() : caught in all
Some of you mind be wondering why for the last case it was not caught by std::exception. The reason is simple as we threw a string rather than a subclass of the std::exception. In actual application we should always throw exception by subclassing the base class std::exception as it is more robust.

Further reading 

No comments:

Post a Comment