throw() in function signature in C++

2013-11-23
#c++ #exceptions

There is base class exception in standard library (header <exception>). It has default constructor, copy constructor, copy operator and destructor and virtual what() function. Latter returns string with additional information about exception.

#include <exception>
class MyException: public std::exception
{
    virtual const char* what() const throw()
    {
        return "My Exception happened";
    }
}

The most confusing part in the above code is throw(). It assures no exception will be thrown from the what() function. For example, if you want to allow exception int and float to be raised in this function, you must write throw(int,float) (you can not do it in the above example, this fucntion definition is fixed in base class). Ok, this example is mostly unchangable, so let’s write own MyException class without derivation from any standard library class.

#include <iostream>
#include <string>

class MyException
{
public:
    std::string what()
    {
        return "MyException happened";
    }
};

int main(int argc, char **argv)
{
    MyException a;
    try {
        throw a;
    } catch (MyException &e) {
        std::cout << e.what() << std::endl;
    } catch (int a) {
        std::cout << "int thrown " << a << std::endl;
    }

    return 0;
}

Ok, if you copy source code, compile and run it, you’ll see:

$ g++ main.cpp -o throw
$ ./throw
MyException happened

This behaviour is predictable. Exception thrown and caught by catch (MyException &e). No special modifiers is presented.

Lets change example a little (throwing exception from what()):

#include <iostream>
#include <string>

class MyException
{
public:
    std::string what()
    {
        throw 10;
        return "MyException happened";
    }
};

int main(int argc, char **argv)
{
    try {
        MyException a;
        throw a;
    } catch (MyException &e) {
        std::cout << e.what() << std::endl;
    }
    return 0;
}

Throwing exception from what() causes unhandled exception:

$ ./throw
terminate called after throwing an instance of 'int'
Aborted (core dumped)

Usage of throw() in function declaration is considered as a bad idea. But in this particular situation it is allowed: what() returns additional description, it must not send any other exception, as there is no guarantee this exception will behandled. Restrict exceptions from what():

#include <iostream>
#include <string>

class MyException
{
public:
    std::string what() throw()
    {
        throw 10;
        return "MyException happened";
    }
};

int main(int argc, char **argv)
{
    try {
        MyException a;
        a.what();
    } catch (...) {
        std::cout << "exception handled" << std::endl;
    }
    return 0;
}

Finally we get what we came from: this class is pretty like std::exception, isn’t it? throw() ensures no exceptions can be sent from show() function. So, compiler will fail? No! Compiler reports no errors. But an error occures in runtime:

$ ./throw
terminate called after throwing an instance of 'int'
Aborted (core dumped)

There is a little information why the code have failed. No exception (even raised in functions called from show()) will pass through show() throw(). Error will appear only at runtime.

So, throw() is used to ensure no additional exceptions will be raised from show() function and will escape catch(). But in general case such behaviour is difficult to predict and is a bad practice. Try not to use throw() in function signature without high necessity. Try not to use throw with particular allowed exceptions (like throw(A, B)) in any situation. Standart std::exception is very good to derive your exceptions in huge amount of sutuations.