Reputation: 145
I want to translate the java exception handling in c ++, without using RAII.
The problem mainly concerns the finally block.
I found a paper which use the following approach:
"One difficulty is that the finally clause must be executed before every exit from the try block. There are a surprising number of potential exits from a general try block: a normal exit, throwing an exception, a return statement, a break statement, a continue statement, or failing to catch an exception. The finally clause must be executed before each of these (if they are used in the try block or a catch block). For example, the following Java code shows most of the ways to exit from a try block:
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");
}
Our solution then is to simply duplicate the text of the finally block in all places where it must be executued. If the finally block is significant in size, this might suggest that the Java programmer might want to make it a method, in order to minimize the code repetition in C++.
The following C++ code shows how the finally block must be replicated for all the exits from a try block:"
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"));
I do not understand how to use it in a real generic program example. What is the variable x in the switch and how should I use it?
Upvotes: 2
Views: 3519
Reputation: 109567
It is just sample code. The point made, is that the java finally block actually is inserted at multiple points. The shown code is just a sample, listing break
, continue
, return
and throw
that need to copy the code of the finally block - as final code.
For instance:
try {
...
return ...;
...
} finally {
A;
}
would become
try {
...
{ A; }
return ...;
...
{ A; }
} catch (java_lang_Error *e) {
A;
throw e; // If the catch was not there originally
}
Actually this is what happens in java bytecode.
So all code leaving the java try-finally needs to copy the code of the finally block.
Upvotes: 1
Reputation: 48625
The GSL is a library that supports the CppCoreGuidelines. The guidelines recommend using gsl::finally for this:
#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';
}
}
But you really should move to a RAII
design for new classes. That would obviate the need to use a "finally" object.
Note: Please get your random numbers from #include <random>
in real life.
Upvotes: 5