C++ Function Try Blocks

Learn the basics of function try blocks in C++ with this beginner's guide. Discover how to catch exceptions thrown within a function and gracefully handle errors in your code.
This lesson is part of the course:

Professional C++

Comprehensive course covering advanced concepts, and how to use them on large-scale projects.

5a.jpg
Ryan McCombe
Ryan McCombe
Posted

When developing programs in C++, it's essential to handle exceptions that can occur during program execution. One way to handle these exceptions is by using function try blocks.

A function try-catch block is a special type of try-catch block that is used to catch exceptions thrown anywhere within the function that it is applied to. In this article, we will explain the basics of function try-catch blocks and show you how to use them in your code.

Previously, we have seen how we can have try and catch blocks inside a function:

#include <iostream>
#include <stdexcept>

void MyFunction() {
  try {
    throw std::runtime_error { "Oops!" };
  } catch (std::runtime_error e) {
    std::cout << e.what();
  }
}

There is an alternative syntax for this, where we want the try and catch to apply to our whole function. It looks like this:

#include <iostream>
#include <stdexcept>

void MyFunction() try {
  throw std::runtime_error { "Oops!" };
} catch (std::runtime_error e) {
  std::cout << e.what();
}

As with regular try-catch blocks, we can have multiple catch statements, to catch different types of errors:

#include <iostream>
#include <stdexcept>

void MyFunction() try {
  throw std::runtime_error { "Oops!" };
} catch (std::logic_error e) {
  std::cout << "Logic error!";
} catch (std::runtime_error e) {
  std::cout << "Runtime error!";
}

Where the function has a non-void return type, all of the catch statements will also need to respect that, by returning an appropriate object:

int GetNumber() try {
  throw std::runtime_error { "Oops!" };
  return 42;
} catch (std::runtime_error e) {
  std::cout << e.what();
  return -1;
}

Catching Exceptions in Member Initialization Lists

Function try blocks are particularly useful when we want to catch exceptions within a class constructor. In the following example, line 13 is making a call to the Character constructor, passing a value that is going to cause an exception.

But, how do we catch that exception within the Goblin constructor?

#include <iostream>
#include <stdexcept>

class Character {
public:
  Character(int Health) {
    if (Health < 0) throw std::logic_error {
      "Health cannot be negative!"
    };
  }
};

class Goblin : Character {
public:
  Goblin(int Health) : Character { Health } {
    // How can we catch the error??
  }
};

int main() {
  Goblin MyChar { -100 };
}

Our program crashes without showing our error:

terminate called after throwing an instance of std::logic_error

When a member initializer list throws an exception, a function try block is the only way to catch that exception:

class Goblin : Character {
public:
  Goblin(int Health) try : Character { Health } {
    // How can we catch the error??
  } catch (std::logic_error e) {
    std::cout << e.what() << std::endl;
  }
};

We now get our custom error message:

Health cannot be negative!
terminate called after throwing an instance of 'std::logic_error'

When an exception is thrown as part of a constructor, it is not possible to recover from that within the constructor. We just need to rethrow the error.

If we don’t rethrow the error, it will be implicitly rethrown for us, as indicated by the second line of our previous error log.

Therefore, the use of function try blocks within constructors has two purposes:

  • To change the type of error thrown, by rethrowing a different type
  • For secondary effects - eg, reporting the error to some tracker

Was this lesson useful?

Ryan McCombe
Ryan McCombe
Posted
This lesson is part of the course:

Professional C++

Comprehensive course covering advanced concepts, and how to use them on large-scale projects.

Exceptions and Error Handling
7a.jpg
This lesson is part of the course:

Professional C++

Comprehensive course covering advanced concepts, and how to use them on large-scale projects.

Free, unlimited access!

This course includes:

  • 106 Lessons
  • 550+ Code Samples
  • 96% Positive Reviews
  • Regularly Updated
  • Help and FAQ
Next Lesson

Internal and External Linkage

A deeper look at the C++ linker, how it interacts with our variables and functions, and how we can control it using the extern and inline keywords
a83.jpg
Contact|Privacy Policy|Terms of Use
Copyright © 2023 - All Rights Reserved