Search code examples
c++exceptionraii

C++ code became no-linear when using exception


I've project which the main look like that

Object a;

if (! a.initialize(x, y, z))
  return EXIT_FAILURE;

// 100 lines using a

a.finalize();

I trying to change this part of code and using RAII idiome. So, I delete initialize function and finalize and move the code in the constructor and destructor.

In order to catch initialize() error, I throw an exception in the constructor if something fail.

So now, my code goes like this :

try
{
  Object a(x, y, z);

  // 100 lines using a
} catch (my_exception&)
{
  return EXIT_FAILURE;
}

the think that bother is the 100 lines of code. My try is too long for just one error. And I've multiple object like a.

so before my code was linear :

Object a;

if (! a.initialize(x, y, z))
  return EXIT_FAILURE;

Object b;
Object c;

if (!b.initialize() || !c.initialize())
  return EXIT_FAILURE;

a.finalize();

Now it looks ugly, difficult to read :

try
{
  Object a(x, y, z);

  try 
  {
    Object b;
    try
    {
      Object c;
    }
    catch (my_exception_c&)
    {
      return EXIT_FAILURE;
    }
  }
  catch (my_exception_b&)
  {
    return EXIT_FAILURE;
  }    

} catch (my_exception&)
{
  return EXIT_FAILURE;
}

How to do to use RAII and keep a code clear ?


Solution

  • In general, create a try block at the level at which you want to handle the exception. In this case, you just need a top-level block to clean up after any exception:

    try {
        Object a(x, y, z);
        Object b;
        Object c;
    
        // code using these
    
    } catch (...) {
        // end the program if any exception hasn't been handled
        return EXIT_FAILURE;
    }
    

    Now it's not "too long for one error"; it's the right length for any error which might occur.

    It would be a good idea to restrict yourself to exceptions derived from std::exception; then you could give some potentially useful information in the case that it's not handled:

    catch (std::exception const & ex) {
        std::cerr << "ERROR: " << ex.what() << std::endl;
        return EXIT_FAILURE;
    }