繁体   English   中英

最后尝试从Java到C ++

[英]Try-catch-finally from java to c++

我想在不使用RAII的情况下转换c ++中的Java异常处理。

问题主要涉及finally块。

我找到了使用以下方法的论文:

“一个困难是,必须在try块的每次退出之前执行finally子句。普通try块有许多令人惊讶的潜在退出:正常退出,抛出异常,return语句,break语句,继续语句,或未能捕获异常。必须在每一个语句之前执行finally子句(如果它们在try块或catch块中使用),例如,以下Java代码显示了大多数退出方法一个try块:

try {
  switch (x) {
    case 0: continue next;
    case 1: break out;
    case 2: throw new TException();
    case 3: return(0);
  }
} catch (Error e) {
    throw(e);
} finally {
    System.out.println("finally");
}

然后,我们的解决方案是在必须执行的所有地方简单地复制final块的文本。 如果finally块的大小很大,则可能表明Java程序员可能希望使其成为一种方法,以便最大程度地减少C ++中的代码重复。

以下C ++代码显示了必须如何为try块的所有出口复制finally块:”

  try
   {
     switch(x)
     {
     case 0:
     /* finally clause, continue from try block */
     java_lang_System::out->println(_j_toString("finally"));
     goto next;
     case 1:
     /* finally clause, break from try block */
     java_lang_System::out->println(_j_toString("finally"));
     goto out;
     case 2:
     /* finally clause, throw exception from try block */
     java_lang_System::out->println(_j_toString("finally"));
     throw(new TException());
     case 3:
     /* finally clause, return from try block */
     java_lang_System::out->println(_j_toString("finally"));
     return(0);
     }
   }
   catch(java_lang_Error *e)
   {
     /* finally clause, caught exception from try block */
     java_lang_System::out->println(_j_toString("finally"));
     throw(e);
   }
   catch(...)
   {
     /* finally clause, uncaught exception from try block */
     java_lang_System::out->println(_j_toString("finally"));
     throw;
   }
     /* finally clause, normal exit from try block */
     java_lang_System::out->println(_j_toString("finally"));

我不了解如何在真实的通用程序示例中使用它。 开关中的变量x是什么,应该如何使用?

GSL是一个支持CppCoreGuidelines的库。 准则建议为此使用gsl :: final

#include <gsl/gsl_util>

int main()
{
    std::srand(unsigned(std::time(nullptr)));

    auto cleanup = gsl::finally([]{
        std::cout << "FINALLY it is my turn." << '\n';
    });

    try
    {
        if(std::rand() % 2)
            throw std::runtime_error("Woopsie 1");

        if(std::rand() % 2)
            throw std::logic_error("Woopsie 2");

        std::cout << "No woopsies on me" << '\n';
    }
    catch(std::runtime_error const& e)
    {
        std::cout << e.what() << '\n';
    }
    catch(std::logic_error const& e)
    {
        std::cout << e.what() << '\n';
    }
}

但是您确实应该为新课程转向RAII设计。 这将消除使用“最终”对象的需要。

注意:请从现实中的#include <random>获取随机数。

这只是示例代码。 所要指出的是,java finally块实际上是在多个点插入的。 所显示的代码只是一个示例,列出了breakcontinuereturnthrow ,它们需要复制finally块的代码-作为最终代码。

例如:

try {
    ...
    return ...;
    ...
} finally {
    A;
}

会成为

try {
    ...
    { A; }
    return ...;
    ...
    { A; }
} catch (java_lang_Error *e) {
    A;
    throw e; // If the catch was not there originally
}

实际上,这就是Java字节码中发生的情况。

因此,所有试图最终离开Java的代码都需要复制finally块的代码。

暂无
暂无

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

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