繁体   English   中英

尝试使用RAII捕获?

[英]try catch using RAII?

我有一个类有一些方法,如下(和更多):

    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 ;
    }

我想将函数体包含在表单的try catch块中:

    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:建议使用这样的例外吗? (在每个功能中)。 我不熟悉使用异常,所以我不确定。

Q2:如果Q1的答案是肯定的,我可以做这样的事情来消除冗余吗?

    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:建议使用这样的例外吗? (在每个功能中)。 我不熟悉使用异常,所以我不确定。

没有特别的问题,但没有特别的原因,除非你计划丰富异常信息,区分一些ios_base ::失败函数与其他函数等。你只想让每个函数更大/更复杂如果它使其他更小的东西/更简单。

Q2:如果Q1的答案是肯定的,我可以做这样的事情来消除冗余吗?

您可以使用宏来为您生成try / catch块。 如果你按照你的建议行事,那么在处理异常时会调用析构函数:如果你再次尝试抛出,那么将调用terminate() 有关详细信息,请查看C ++ Lite常见问题解答: http//www.parashift.com/c++-faq-lite/exceptions.html#faq-17.9

回答Q1:meh ......

回答Q2:nope,析构函数体将永远运行,不会收到任何异常数据。 您不能以这种方式替换catch子句。

即使你可以,也不会属于RAII这个词。 它有点类似于RAII,因为使用自动内存规则会导致某些事情发生,但就是这样。 例如,(A)所需的(R)资源在哪里......

广告Q1:

我稍微建议反对它。 当最终处理异常的调用者不应该知道内部细节并且原始异常对它没有意义时,应该完成包装异常。 但是对于operator<< throw std::ios_base::failure非常有意义所以我不会在这里包装。

广告Q2:

不,但你可以这样做:

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);
}

(可能更容易利用来自TR1 / Boost的绑定作为

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

包装异常是你应该做的事情,如果你确定你需要 - 它通常不是很有用。

您无法从析构函数中捕获异常,但您可以执行以下操作:

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();
  }
}

这里的重新抛出代码很短,所以可能不值得。 异常处理代码很长的地方可能是有益的。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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