Hello all:

I would be grateful for some basic advice about C++ error handling.

From my reading, I understand that the "try, throw, catch" method is preferable to dealing with return values, which can be cryptic. But I'm not sure if I understand exactly how this works. I made a simple example below and any comments would be appreciated. I would like to make a function out of the example below that checks the results of another calculation.

This is what I'm wondering. (1) Should the catch statement be included in that function? Or should it be somewhere else? (2) More generally, is it overkill to use try, catch, throw for something this simple (I would like to improve my style)? (3) If there is an error, I would like to terminate the program. How would I do that? Or does "catch" mean that that is done automatically?

These are probably dumb questions--thanks in advance for your patience.

double calculated   = 10.2;  // from previous calculation
double tolerance    =  0.3;  
double valueWanted  = 10.0;  // from previous calculation
const int calcError = 5;

try
{
    if (fabs(fTargetValue - fCalculated) <= fTolerance)
        cout << "Result is within range.";
    else
        cout << "Calculation failed."; 
    throw calcError;
}

catch (const int calcError) 
{
    cerr << "The calculation failed.\n" << endl;
}

Dani AI

Generated

Quick summary tied to the posts above: is right that return codes are perfectly fine for expected results, and exceptions are best for truly exceptional, unexpected failures. ’s example always throws because the throw sits unconditionally after the if/else — that will make the catch run every time, which is almost never what you want.

Use this rule of thumb:

  • If “out of tolerance” is a normal, frequent outcome the caller should check, return a status (or use std::optional/an error-type) so callers handle it directly.
  • If it represents a genuine, rare error that you cannot handle locally, throw an exception so it can be handled at a higher level (for example, in main()).

Practical tips and safe defaults:

  • Don’t throw primitive types (int). Throw objects derived from std::exception so callers can read what().
  • Throw by value, catch by const&.
  • Catch an exception only where you can handle it (recover, retry, or clean up and rethrow). If you want to terminate on error, catch in main() and return a nonzero exit code after logging.
  • Let RAII do cleanup: stack unwinding runs destructors when an exception propagates, so prefer RAII-managed resources instead of manual cleanup.

Example pattern (new example — not a copy of existing posts):

void ensureWithinTolerance(double got, double expected, double tol) {
    if (std::fabs(got - expected) > tol)
        throw std::runtime_error("value outside tolerance");
}

int main() {
    try {
        ensureWithinTolerance(10.2, 10.0, 0.3);
        std::cout << "OK\n";
    } catch (const std::exception& e) {
        std::cerr << "Fatal: " << e.what() << '\n';
        return EXIT_FAILURE;
    }
}

If you truly want immediate, abnormal termination, std::abort() forces it (no stack-unwinding). Prefer returning from main() after logging so destructors run and shutdown is clean.

Firstly, be aware that the appropriate time to use exceptions is a matter of opinion, and if you ask five people, you'll get back more than five different opinions :)

All the following, thus, is my opinion. To my mind, the clue is in the name; exceptions are for exceptional circumstances.

From my reading, I understand that the "try, throw, catch" method is preferable to dealing with return values, which can be cryptic.

I believe this to be fundamentally wrong; using exceptions because you can't understand your own return values is flawed, especially since exception handling is inherently more complicated than returning a value. You're writing the code, so if you can identify circumstances in which you can pass information by return value, you should. Return values are far less difficult to work with, to my mind.

In your example above, you will always be throwing an exception. Could you not do something like this?

// Declare function prototype
int checkValue(int calculated, int tolerance, int valueWanted);

// Define function
int checkValue(int calculated, int tolerance, int valueWanted)
{
  if (fabs(valueWanted- calculated) <= tolerance)
  {
    return 0; // Common return value for calculation working
  }
  else
  {
    return 1; // Your chosen return value to indicate calculation failed
  }
}
// Example usage somewhere in code
int failed = checkValue(calculated, tolerance, valueWanted);
if (failed == 0)
{
  cout<< "Calculation worked.";
}
else
{
  cout << "Calculation failed.";
  abort();
}

If you think you'll lose track of the return value meanings, this sort of thing is common:

#define CALCULATION_WORKED 0
#define CALCULATION_FAILED 1

and then you would replace the '0' and '1' return values in your code with 'CALCULATION_WORKED' and 'CALCULATION_FAILED', which would make your meaning obvious to everyone who reads the code. For those who don't like

#define

for their constants, there is the option of a suitable scoped

const

instead.

To my mind, that is simpler and easier to understand; using return values to pass information about {success/failure/more detailed information} is very common.

You can terminate your programme at any time with abort(), although it's generally considered better practice to structure your programme so that you end the code using the usual return statement in main().

Catch does not mean that the programme terminates; catch is actually your attempt to stop it terminating! If you do not handle an exception with a suitable catch, it will be thrown ever higher until finally the programme ends (if it is never caught and dealt with).

All the above is, as stated, no more than opinion. I know there are people who prefer exception over return values. That's their choice and I'm sure they're happy with it, which is nice :)

commented: Thanks for taking so much time Moschops. This really helped. +2
Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.