Click here to Skip to main content
15,905,566 members
Please Sign up or sign in to vote.
1.00/5 (1 vote)
See more:
When searching for exception handling I found this program and then some questions appeared in my mind: (pleas see and help me with this)
//---------------------------------------------------------------------------
#include <vcl.h>
#pragma hdrstop
#include <limits>
#include <conio.h>
#include <iostream.h>
//---------------------------------------------------------------------------
#pragma argsused
class INt{
    int val;
    public:
        class Overflow {};
        class Zerodivide {};
        class CannotMakePositive {};
        INt(): val(0) {}
        INt(int i): val(i) {}
        INt operator -();

        friend const INt operator +(const INt &a, const INt &b)  {
            INt t = a;
            if (a.val > 0 && b.val > 0 && a.val > INT_MAX - b.val ||
                a.val < 0 && b.val < 0 && a.val < -INT_MAX - b.val)
            throw    Overflow();
            t = t + b;
            return t;
        }
        friend const INt operator -(const INt &a, const INt &b)  {
            INt t = a;
            if (a.val > 0 && b.val > 0 && a.val > -INT_MAX - b.val ||
                a.val < 0 && b.val < 0 && a.val < -INT_MAX - b.val)
            throw    Overflow();
            t.val = t.val- b.val;
            return t;
        }
        friend const INt operator *(const INt &a, const INt &b)
        throw (Overflow) {
            long long t = (long long)b.val * (long long)a.val;
                if (t > INT_MAX || t < -INT_MAX)
                throw Overflow();
            return t;
        }
        friend const INt operator /(const INt &a, const INt &b)  {
            INt t = a;
            if (b.val == 0)
                throw Zerodivide();
            t.val = a.val / b.val;
            return t.val;
        }
};
 INt INt::operator -()
{
    if (val == -INT_MIN)
        throw CannotMakePositive();
    return INt(-val);
}
int main(int argc, char* argv[])
{
    INt d1(INT_MAX);
    INt d2(-20);
    INt d3(-INT_MIN);
    try {

        d1 * d2;
    }
    catch(INt::Overflow) {
        cout << "Overflow" << endl;
    }
    try {
        d1 / 0;
    }
    catch(INt::Zerodivide) {
        cout << "Divide by zero" << endl;
    }
    try {
        -d3;
    }
    catch(INt::CannotMakePositive) {
        cout << "Can not make positive" << endl;
    }
    getch();
    return 0;
}

The questions are:
1. What are the classes Overflow, Zerodivide and CannotMakePositive for?
and do they receive an inheritance from class INt?
2. in this code:
C#
friend const INt operator *(const INt &a, const INt &b)
        throw (Overflow){
            long long t = (long long)b.val * (long long)a.val;
                if (t > INT_MAX || t < -INT_MIN)
                throw Overflow();
            return t;
        }

what does it mean when throw (Overflow) is at that position (before body function of operator). The operator should return an object type INt but variable t is type long long. Why?

Hope my question are clear to you.
Thanks in advanced!
Posted
Updated 15-Jan-11 2:16am
v4

Here is a link on c++ exception handling[^]

Overflow, Zerodivide and CannotMakePositive are C++ classes, and in this case they are used to convey information about error conditions in the form of exceptions.

A simplistic explaination is that throw breaks off the normal execution flow. Execution will continue inside the closest catch block for the closest match for the thrown type.

long long t = (long long)b.val * (long long)a.val;


The result of an integer multiplication may owerflow - the result could be larger than what fits inside a 4 byte integer. So the code uses long long, 8 byte integers. the result of multiplying two 4 byte integers will allways fit inside an 8 byte integer. The code then checks that the result is inside the valid range for a 4 byte int, and if it's not throws an instance of an Overflow object created using Overflow();.

On return t the compiler looks for a way to convert the long long t to a INt using the best matching constructor for INt matching with INt(int i): val(i) {}. You should see a warning though ...

Regards
Espen Harlinn
 
Share this answer
 
Comments
Dalek Dave 17-Jan-11 3:34am    
Comprehensive Answer.
Espen Harlinn 17-Jan-11 9:20am    
Thanks Dalek!
No, the only role of these classes is to define a type for exception object. A C++ exception can be thrown with arbitrary type, in your case e.g. Overflow. The statement throw Overflow(); creates an object of type Overflow and passes it to underlying exception system. The exception handler for client code which uses INt can catch exceptions of specified types, as done in your main procedure (which does not catch by reference, btw...).

With regard to second question, this is a bit more compicated. If an exception is thrown as in your example, the program flow never reaches the return statement, so the operator * never returns. The control is given over to the exception system which seeks the next exception handler in scope... Well, this is more complicated then it seems at the first glance, so I recommend some reading on exceptions and exception handling first...
 
Share this answer
 
Comments
Dalek Dave 17-Jan-11 3:34am    
Good Answer.
throw (Overflow)

means, that function can thwor Overflow exception.
 
Share this answer
 
Comments
Dalek Dave 17-Jan-11 3:34am    
That does seem a little obvious.
Aescleal 17-Jan-11 10:13am    
Actually, it doesn't. What it means is "if the function throws anything but overflow the compiler's going to terminate the process" or rather call std::unexpected which will call std::terminate which will kill the process. C++ exception specifications don't mean what most sane people think they mean... :-)

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900