Details on C++ exceptions

  • 2020-05-27 06:47:13
  • OfStack

C++ details of exceptions

Programs sometimes encounter run-time errors that prevent the program from executing properly. c++ exceptions provide a powerful and flexible tool for handling this situation. The exception is a relatively new C++ feature that some older compilers may not have implemented. Also, some compilers turn this feature off by default, and we may need to use the compiler option to enable it.

1. Use of exception mechanism

Exceptions provide a way to pass one part of the control program to another. Handling exceptions has three components:

An exception is thrown
Use handlers to catch exceptions
Using try block

Sample code:


#include "stdafx.h"
#include <iostream>
double hmean(double a, double b);
int main()
{
  double x, y, z;
  std::cout << "Enter two numbers: ";
  while (std::cin >> x >> y) {
    try
    {
      z = hmean(x, y);
    }
    catch(const char *s ){
      std::cout << s << std::endl;
      std::cout << " Enter a new pair of numbers: ";
      continue;
    }
    std::cout << "Harmonic mean of " << x << " and " << y << " is " << z << std::endl;
    std::cout << "Enter next set of numbers <q to quit>: ";
  }
  std::cout << "Bye! \n";
  system("pause");
  return 0;
}

double hmean(double a, double b) {
  if (a == -b) {
    throw "bad hmean() arguments a= -b not allowed";

  }
  return 2.0 *a*b / (a + b);
}

Enter two numbers: 3 6
Harmonic mean of 3 and 6 is 4
Enter next set of numbers <q to quit>: 10 -10
bad hmean() arguments a= -b not allowed
 Enter a new pair of numbers: q
Bye!
 Please press any key to continue . . .

Program description:

try block:


   try
    {
      z = hmean(x, y);
    }

The code that throws the exception:


if (a == -b) {
    throw "bad hmean() arguments a= -b not allowed";

  }

Executing the throw statement is similar to executing the return statement, because it will also terminate the execution of the function. But instead of returning control to the caller, throw causes the program to step back along the sequence of function calls until it finds the function that contains the try block.

Handler (or catch block):


catch(const char *s ){
      std::cout << s << std::endl;
      std::cout << " Enter a new pair of numbers: ";
      continue;
    }

2. Use an object as an exception type

Normally, the function that throws the exception will pass one object. One of the important advantages of doing this is that you can use different types of exceptions to distinguish the exceptions that different functions throw in different situations. In addition, objects can carry information that the programmer can use to determine the cause of the exception. At the same time, the catch block can use this information to decide what action to take.

Example:

exc_mean.h


#include "stdafx.h"
#include <iostream>

class bad_hmean
{
private:
  double v1;
  double v2;
public :
  bad_hmean(double a = 0, double b = 0) :v1(a), v2(b) {}
  void mesg();
};
inline void bad_hmean::mesg() 
{
  std::cout << "hmean ( " << v1 << " ," << v2 << ") ;"
    << "invalid argumnents: a =-b \n";
}

class bad_gmean
{
public :
  double v1;
  double v2;
  bad_gmean(double a = 0, double b = 0) :v1(a), v2(b) {}
  const char * mesg();
};
inline const char* bad_gmean::mesg() {
  return "gmean() arguments shoud be >=0 \n";
}

Test code:


#include "stdafx.h"
#include <iostream>
#include <cmath>
#include "exc_mean.h"

double hmean(double a, double b);
double gmean(double a, double b);

int main()
{
  using std::cout;
  using std::cin;
  using std::endl;

  double x, y, z;
  1 >> 2;
  cout << "Enter two numbers ";
  while (cin >> x >> y)
  {
    try 
    {
      z = hmean(x, y);
      cout << "Harmonic mean of " << x << " and " << y << " is " << z << endl;
      cout << " Geometric mean of " << x << " and " << y << " is " << gmean(x, y) << endl;
      cout << " Enter next set of numbers <q to quit >:";
    }
    catch (bad_hmean & bg)
    {
      bg.mesg();
      cout << "Try again. \n";
      continue;
    }
    catch (bad_gmean & hg)
    {
      cout << hg.mesg();
      cout << "Value used: " << hg.v1 << " ," << hg.v2 << endl;
      cout << "Sorry, you don't get to play any more .\n ";
      break;
    }

  }
  cout << " Bye! \n";
  system("pause");
  return 0;
  return 0;
}

double hmean(double a, double b) {
  if (a == -b)
    throw bad_hmean(a, b);
  return 2.0 * a*b / (a + b);
}
double gmean(double a, double b) {
  if (a < 0 || b < 0) throw bad_gmean(a, b);
  return std::sqrt(a * b);
}

 The output :
Enter two numbers 4 12
Harmonic mean of 4 and 12 is 6
 Geometric mean of 4 and 12 is 6.9282
 Enter next set of numbers <q to quit >:5 -5
hmean ( 5 ,-5) ;invalid argumnents: a =-b
Try again.
5 -2
Harmonic mean of 5 and -2 is -6.66667
gmean() arguments shoud be >=0
Value used: 5 ,-2
Sorry, you don't get to play any more .
 Bye!
 Please press any key to continue . . .

3. Abnormal specification

The exception specification is a feature of C++98, but c++11 rejects it. This means that c++11 is still in the standard, but may be dropped from the standard later, so it is not recommended.

Example exception specification:


double harm(double a ) throw(bad_thing);// Might throw  bad_thing abnormal 
double marm(double ) throw() ;// Do not throw an exception 

The role of the exception specification:

1. Tell the user that you may need to use the try block, however this can be easily done using annotations.

2. Have the compiler add runtime checking code to check for violations of the exception specification, which is difficult to check. For example, marm may not raise an exception, but it may call a function that calls another that raises an exception

In general, it is best not to use this feature, and c++11 also recommends ignoring exception specifications

However, c++11 does support a special exception specification using the keyword noexcept

For example,


double marm() noexcept;

4. The stack unwinding

Assuming that the function terminates due to an exception (not due to return), the program will also free the memory in the stack, but will not stop after the first return address of the normal stack, but will continue to free the stack until it finds a return address located in the Try block. Control then passes to the exception handler at the end of the block, not to the first statement following the function call. This process is called stack unwinding.

5. exception class

The newer C++ compiler merges exceptions into the language. For example, to support the language, the exception header (previously exception.h or except.h) defines the exception class, which c++ can use as a base class for other exception classes.

The header files exceptionhe and stdexcept define some common exception classes

There are: logic_error, runtime_error, domain_error, etc

6. Unexpected exception and uncaught exception handling

When an exception is raised, it causes problems in both cases. First, if it is thrown in a function with an exception specification, it must match some exception in the specification list (in the inheritance hierarchy, the class type matches the class and its derived objects), or it becomes an unexpected exception. By default, this will lead to abnormal program termination (although C + + 11 to discard the exception specification, but still support it, and some existing code to use it) if an exception is not in the function in the trigger (or function without exception specification), you must catch it, if there is no capture (without try catch or no matching blocks, will appear this kind of circumstance), then uncaught exception is called an exception. This will cause the program to terminate abnormally. However, you can modify the program's response to unexpected exceptions and to catch them.

No exception caught:

Failure to catch an exception does not cause the program to terminate in an immediate exception; instead, the program calls the function terminate() first. By default, terminate() calls the abort() function. This behavior of terminate() can be modified by specifying the function terminate() should call instead of abort(). To do this, call the set_terminate() function. set_terminate() and terminate() are both declared in the header file exception:


typedef void (*terminate_handle)() ;
terminate_handle set_terminate(terminate_handle f) throw();//c++ 98
terminate_handle set_terinate(terminate_handle f) noexcept; //c++11
void teminate(); //c++98
void teminate() noexcept ; //c++11

Example:


void myQuit()
{
  std::cout << "Terminating due to uncaught exception \n";

  system("pause");
}

 Execute at the beginning of the program :
set_terminate(myQuit);

exception

If an unexpected exception occurs, the program calls the unexcepted() function, which calls teminate(), which defaults to abort(). Like the set_terminate() function, there is also an set_unexpeceted() function that can modify the behavior of unexcepted (). These functions are also declared in the header file exception:


   try
    {
      z = hmean(x, y);
    }
0

Use as follows:


   try
    {
      z = hmean(x, y);
    }
1

When I tested vs 2015, I did not implement this functionality, but had to display calls to terminate() and unexpected();

If you have any questions, please leave a message or come to the site community to exchange discussion, thank you for reading, hope to help you, thank you for your support of the site!


Related articles: