C++. Developing a class demonstrating the implementation of an overflow exception

Developing a class demonstrating the implementation of an overflow exception

This topic provides an example of how you can implement a class that handles an overflow exception using the try…catch statement. In this example, you can learn to develop your own classes that use the C++ exception mechanism to handle exceptions.


Contents


Task

Develop an Int class that behaves like an int type, only it still throws an exception in cases of overflow. The condition of the problem is taken from the book of B. Straustrup “C++ Programming Language”.


Implementation features

In the Int class, for demonstration purposes, the C++ exception mechanism is used to prevent overflow.

For built-in type int overflow may occur in the following situations:

  • during the creation of a class object. In the class constructor, the wrong value can be set right away;
  • during the operation of assigning some value. This value may be incorrect;
  • during the summation (subtraction) of two objects of type Int. The sum of objects may exceed the maximum (minimum) allowable, resulting in overflow;
  • during the multiplication of two objects of type Int among themselves;
  • other situations that can be implemented. For example, multiplication of object of type int to some number.

To catch the overflow for the Int type, the Int class uses work with the long type, which has a wider range of values (takes up more memory) of positive and negative values. Accordingly, you can make the necessary checks to exceed the maximum (minimum) allowable value of type int. The Int class is implemented for 16-bit int values.

 


Instructions

For the purpose of demonstration, the following functions are implemented in the Int class:

  • default constructor;
  • constructor with one parameter. The constructor uses the try…catch statement to check that the parameter value is correct;
  • operator function operator=(Int &), which overloads the assignment operator =. This function is used to assign objects of type Int;
  • overloaded operator function operator=(long), which overloads the assignment operator =. This function is used to assign some value to an object of class Int. This function uses a try…catch block;
  • operator function operator+(Int) overloading the summation operator +. This function uses a try…catch block;
  • operator function operator*(Int), overloading the multiplication operator *. The function uses the try…catch mechanism to verify the correctness of the value of the multiplication result;
  • global “friend” operator function operator<<(), which overloads the output operator into the stream <<. The function is designed to display objects of class Int. The function is implemented for the purpose of demonstration;
  • global “friendly” operator function operator>>(), which overloads the operator >> to input from the stream. The function is intended for input of objects of class Int and is implemented for the purpose of demonstration.

To determine the maximum allowable and minimum allowable values of the int type, in the Int class constants INT16_MIN and INT16_MAX are used. Optionally, you can select other constants (for example, INT32_MIN, INT32_MAX).

The implementation of the class Int.

// Task. B.Straustrup
class Int
{
private:
  long value;

public:
  Int() { value = 0L; }

  // constructor with one parameter
  Int(long _value)
  {
    try // overflow check
    {
      if ((_value < INT16_MIN) || (_value > INT16_MAX))
        throw "Constructor. Exception: overflow.";
      value = _value;
    }
    catch (const char* e) // catch an exception
    {
      // handle the exception
      value = 0L;
      cout << e << endl;
    }
  }

  // Operator function which overloads the assignment operator =,
  // this function has two overloaded implementations
  // Implementation 1.
  Int& operator=(Int& t)
  {
    // Overflow check is not needed here,
    // since the value in t no longer contains overflow
    value = t.value;
    return *this;
  }

  // Implementation 2.
  Int& operator=(const long _value)
  {
    // In this implementation of the operator function, a check is required
    try {
      if ((_value < INT16_MIN) || (_value > INT16_MAX))
        throw "Assignment operator=(long). Exception overflow.";
    value = _value;
    }
    catch (const char* e) // catch an exception
    {
      cout << e << endl;
    }
    return *this;
  }

  // summation operator overloading +
  Int& operator+(Int i)
  {
    long t = value+i.value;
    try {
      if ((t < INT16_MIN) || (t > INT16_MAX)) // overflow check
        throw "Addition: overflow. ";
      value = t;
    }
    catch (const char* e) // catch an exception
    {
      cout << e << endl;
    }
    return *this;
  }

  // Overloading the multiplication operator,
  // overflow check needed here
  Int& operator*(Int i)
  {
    long t = value * i.value;
    try {
      if ((t < INT16_MIN) || (t > INT16_MAX))
        throw "Addition: overflow. ";
      value = (long)t;
    }
    catch (const char* e)
    {
      cout << e << endl;
    }
    return *this;
  }

  // Overloading operators <<, >>
  friend std::ostream& operator<<(std::ostream& stream, const Int& i);
  friend std::istream& operator>>(std::istream& stream, Int& i);
};

// Global function overloading the output operator <<
std::ostream& operator<<(std::ostream& stream, const Int& i)
{
  stream << i.value;
  return stream;
}

// Global function overloading the input operator >>
// here the parameter Int& i is not constant
std::istream& operator>>(std::istream& stream, Int& i)
{
  long t = i.value; // save the old value

  try {
    stream >> i.value;
    if (i.value > INT16_MAX)
      throw "Input exception: overflow.";
    return stream;
  }
  catch (const char* e)
  {
    // Exception handling. Restore old value
    i.value = t;
    cout << e << endl;
  }
}

void main()
{
  // Test for Int class
  Int i = 500000; // an exception is thrown in the constructor
  Int t = 300; // an exception is not generated

  cout << "i = " << i << endl;
  cout << "t = " << t << endl;

  cout << "i = t" << endl;
  i = t; // invoke the operator function operator=(Int&)
  cout << "i = " << i << endl;

  i = 500; //
  cout << "i = " << i << endl;

  cout << endl << "Input i: ";
  cin >> i;
  cout << "After input: i = " << i << endl;

  // operator function operator=(int)
  cout << "--------------------" << endl;
  cout << "i = 50000" << endl;
  i = 50000;
  cout << "i = " << i << endl;

  i = t = 3000;
  cout << "-----------------" << endl;
  cout << "i = t = 3000" << endl;
  cout << "i = " << i << endl;
  cout << "t = " << t << endl;

  cout << "------------" << endl;
  cout << "25000+15000 = 40000" << endl;
  i = 25000;
  t = 15000;
  t = t + i;
  cout << "t = " << t << endl;
  cout << "------------" << endl;

  cout << "i = 5; t = 220;" << endl;
  i = 5;
  t = 220;
  cout << t * i << endl;
}

In this example, other functions can be implemented in the Int class.