-2

Is it a way to avoid code duplication (FinalAction function call in all catch blocks and in a try one)?

try
{
    // some actions including creation of new objects
    FinalAction();
}
catch (const Exception1& ex1)
{
    ProcessException1(ex1);
    FinalAction();
}
catch (const Exception2& ex2)
{
    ProcessException2(ex2);
    FinalAction();
}
// ...
catch (const ExceptionN& exN)
{
    ProcessExceptionN(exN);
    FinalAction();
}
catch (...)
{
    ProcessUnknownException();
    FinalAction();
}

Update: FinalAction() should be called before the destructors of the objects created in the try block. So simple solution like the following one doesn't work here.

try
{
    // some actions including creation of new objects
}
catch (const Exception1& ex1)
{
    ProcessException1(ex1);
}
catch (const Exception2& ex2)
{
    ProcessException2(ex2);
}
// ...
catch (const ExceptionN& exN)
{
    ProcessExceptionN(exN);
}
catch (...)
{
    ProcessUnknownException();
}
FinalAction();

Some more information about FinalAction: it doesn't throw and it doesn't clean any resources allocated in the try block.

Constructor
  • 7,273
  • 2
  • 24
  • 66
  • Calling the same method from both _try_ and _catch_ suggests code smell. Could you provide us with further details regarding what you're trying to accomplish? Maybe that would help with finding a solution. – Xavier Alvarez Dec 06 '15 at 15:54
  • does `FinalAction()` potentially throw? if not just use RAII – Mgetz Dec 06 '15 at 15:54
  • @XavierÁlvarez In fact it is a simple wait for a key press. But it gave me an idea of a generalization. – Constructor Dec 06 '15 at 15:57
  • @Mgetz How RAII can be used here? A destructor of a RAII object will be called before the first `catch` block as I know. – Constructor Dec 06 '15 at 15:58
  • @Constructor no it will be called in reverse order of construction when the enclosing scope exits. So if the object holding `FinalAction()` is outside the `try` you're fine – Mgetz Dec 06 '15 at 15:59
  • @Mgetz And if the enclosing scope is a `try` block then it will be called before the first `catch` block. – Constructor Dec 06 '15 at 16:00
  • Only the first `catch block` *corresponding to that `try`*. Not any random `catch` block associated with a random nested `try`. – Puppy Dec 06 '15 at 16:01
  • @Puppy All `catch` blocks in my answer are corresponding to the only `try` block. – Constructor Dec 06 '15 at 16:03
  • @Constructor: Right, but he doesn't want you to put it in the scope of that `try` block. He wants you to put it in the parent scope of that `try` block. – Puppy Dec 06 '15 at 16:04
  • 1
    @Puppy Then it is the same as a simple call of it after all `catch` blocks. – Constructor Dec 06 '15 at 16:05
  • @Constructor: Your edits have contradicted themselves. Your first statement is that `FinalAction()` must be called at the end of each `catch`. Then you say that `FinalAction()` must be called before destroying any objects in the `try` block. It can't be both, and your former (code-repeating) example *does not* achieve the effect of the latter. So which is it? – Nicol Bolas Dec 06 '15 at 19:42
  • @NicolBolas OK, you are right. `FinalAction()` must be called at the end of `catch` blocks if an exception is thrown. If it is not thrown it should be called at the end of the `try` block before destroying any objects in the `try` block. – Constructor Dec 06 '15 at 20:11
  • @Constructor: Why the restriction within the try block? After all, `FinalAction` *cannot* be reliant on anything those objects do, since it will be called after they're destroyed in the event of an exception. So I'm not sure how this restriction could be *necessary*. – Nicol Bolas Dec 06 '15 at 20:15

3 Answers3

1

Although your question is not an exact duplicate, the answer to this question is appropriate.

What you seem to bee asking for is the equivalent of a finally-clause in C++ and the answer is that in C++ this is normally solved through RAII.

I won't repeat the quite extensive answer that was given in the linked SO question, but in summary you make sure that cleanup of resources is done in a destructor. It is likely that your FinalAction() is the one that is cleaning up resources right now.

Community
  • 1
  • 1
dhavenith
  • 2,028
  • 13
  • 14
  • No, in my question `FinalAction` hasn't nothing with resource cleanup. – Constructor Dec 06 '15 at 16:08
  • It's a million miles away from even being a vague duplicate, and "the" answer? There are seven! – Lightness Races in Orbit Dec 06 '15 at 17:55
  • 1
    @LightnessRacesinOrbit: The _accepted_ answer, the one which has more than twice as many upvotes as number two, gives a good description of RAII. Not knowing what the FinalAction() function did, before the update to the question, "Use RAII" appeared to me to be a good answer. – dhavenith Dec 06 '15 at 20:18
  • @dhavenith: It's a pretty terrible answer. The OP wants to find out how to use RAII to best effect. Just "use RAII" is not helpful. – Lightness Races in Orbit Dec 06 '15 at 21:54
0

I don't know to which classes do ProcessExceptionX and FinalAction belong or what does ProcessException do, but maybe you could have just one ProcessException that gets a parameters and executes FinalAction, e.g.:

...
try {
  FinalAction();
}
catch (const Exception1& ex1) {
  ProcessException(ex1);
}
...

void ProcessException (Exception e) {
 // do things
 FinalAction();
}
Xavier Alvarez
  • 283
  • 2
  • 10
  • No, I can't. `Exception1` ... `ExceptionN` are different exception classes with no common base. And what about handling of unknown exceptions? – Constructor Dec 06 '15 at 18:40
-2

The simplest thing to do is just call it after the try block.

bool success = false;
try
{
    // some actions including creation of new objects
    FinalAction();
    success = true;
}
catch (const Exception1& ex1)
{
    ProcessException1(ex1);
}
if (!success)
    FinalAction();

However it's pretty dubious to be doing this instead of using a class to manage whatever resource you're cleaning up with FinalAction.

Puppy
  • 144,682
  • 38
  • 256
  • 465
  • 2
    Thank you for that solution. But it is a bit ugly, isn't it? – Constructor Dec 06 '15 at 16:07
  • I don't clean any resource with `FinalAction`, it is a simple `wait-for-a-keypress` action. – Constructor Dec 06 '15 at 16:35
  • @Constructor: It directly expresses the semantic you want- if it threw, do FinalAction. – Puppy Dec 06 '15 at 17:38
  • @Puppy Yes, I know your solution is appropriate here. I thought to do it in the same manner but decided to search a nicer solution at [SO]. And I haven't found it yet. – Constructor Dec 06 '15 at 18:32
  • There aren't really any nicer solutions. You need to write the code that does the thing you want it to do. You can't get around that. – Puppy Dec 06 '15 at 20:08