简体   繁体   中英

try catch using RAII?

I have a class which has some methods like follows (And more):

    template<class T>
    Logpp& operator<<(T const& obj)
    {
        *p_Stream << obj ;
        return *this ;
    }

    Logpp& operator<<(char const* zString)
    {
        *p_Stream << zString ;
        return *this ;
    }

    Logpp& operator<<(std::ostream& (*manip)(std::ostream&))
    {
        *p_Stream << manip;
        return *this ;
    }

I want to enclose the body of functions in a try catch block of the form:

    Logpp& operator<<(std::ostream& (*manip)(std::ostream&))
    {
        try
        {
            *p_Stream << manip;
            return *this;
        }
        catch(ios_base::failure& e)
        {
            //MyException has a stringstream inside and can use operator<<
            throw MyException("IO failure writing to log file : ") << e.what() << endl;
        }
    }

Q1: Is it advisable to use exceptions like this? (In each function). I am not familiar using exceptions so I am not sure.

Q2: If the answer to Q1 is positive, can I do something like this to remove redundancies?

    Logpp& operator<<(std::ostream& (*manip)(std::ostream&))
    {
        Catch<ios_base::failure> tc();
        try
        {
            *p_Stream << manip;
            return *this;
        }
        //destructor of tc will be written to catch the template exception type and rethrow as a MyException.
    }

Q1: Is it advisable to use exceptions like this? (In each function). I am not familiar using exceptions so I am not sure.

There's no particular problem, but no particular reason either unless you're planning to enrich the exception information, differentiate some ios_base::failure functions from others etc.. You only want to make each function bigger / more complex if it makes something else smaller / simpler.

Q2: If the answer to Q1 is positive, can I do something like this to remove redundancies?

You could potentially use a macro to generate the try/catch blocks for you. If you do what you suggest, then the destructor will be called while an exception is being handled: if you try to throw again then terminate() will be called. Check the C++ Lite FAQ for details: http://www.parashift.com/c++-faq-lite/exceptions.html#faq-17.9

Answer to Q1: meh...

Answer to Q2: nope, the destructor body will always be run and won't receive any exception data. You can't replace a catch clause in this way.

Even if you could, it wouldn't fall under the term RAII. It sort of resembles RAII in that use of automatic memory rules are used to cause certain things to happen, but that's about it. Where's the (R)esource that is being (A)quired, for instance...

Ad Q1:

I'd slightly recommend against it. Wrapping exceptions should be done when the caller eventually handling the exception should not know about the internal details and the original exception would not make sense to it. But for operator<< throwing std::ios_base::failure makes perfect sense so I'd not wrap here.

Ad Q2:

No, but you could do something like:

Logpp& do_output(std::ostream& (*manip)(std::ostream&))
{
    *p_Stream << manip;
    return *this;
}

Logpp& operator<<(std::ostream& (*manip)(std::ostream&))
{
    return wrap_exception(&Logpp::do_output, this, manip);
}

(probably a bit easier utilizing bind from TR1/Boost as

    return wrap_exception(bind(&Logpp::do_output, this, manip));

Wrapping exceptions is the sort of thing you should only do if you are sure you need to - it's not usually useful.

You can't catch the exception from a destructor, but you can do the following:

void handleCurrentException()
{
  try { throw; } // rethrow currently active exception
  catch (ios_base::failure& e)
  {
    // exception handling/rethrowing code
  }
}

Logpp& operator<<(std::ostream& (*manip)(std::ostream&))
{
  try
  {
    *p_Stream << manip;
    return *this;
  }
  catch(...)
  {
    handleCurrentException();
  }
}

Here the rethrowing code is short so it might not be worth it. Where the exception handling code is long it can be beneficial.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM