Lessons Home

Classes and Exceptions Handling

 

Introduction

Exceptions are an integral and unavoidable part of the operating system and programming. One way you can handle them is to create classes whose behaviors are prepared to deal with abnormal behavior. There are two main ways you can involve classes with exception handling routines: classes that are involved in exceptions of their own operations and classes that are specially written to handle exceptions for other classes.

Transferring Exceptions to Classes

You can create a class that is not specifically oriented towards exceptions, as any of the classes we have used so far. The simplest way to take care of exceptions in classes is to use any normal class and handle its exceptions. Such a class appears like one of the classes we have used already, except that exceptions of its abnormal behavior are taken care of. If concerned with exceptions, the minimum thing you can do in your program is to make it "aware' of eventual exceptions. This can be taken care of by including transactions or other valuable processing in a try block, followed by a three-dot catch as in catch(...). The catch in this case is prepared to handle any exception that could occur. Here is an example of a simple class:

//---------------------------------------------------------------------------

#include <iostream>

#include <iomanip>

using namespace std;

//---------------------------------------------------------------------------



const double PriceShirt = 0.99;

const double PricePants = 1.75;



struct TCleaningOrder

{

    int NumberOfShirts;

    int NumberOfPants;

    int NumberOfMisc;

};

int main(int argc, char* argv[])

{

    TCleaningOrder Order;

    double TotalPriceShirts, TotalPricePants;

    double PriceMisc, TotalPriceMisc;

    double TotalOrder;



    cout << " - Georgetown Cleaning Services -\n";

    cout << "  - Customer Order Processing -\n";



    try {

        cout << "Number of\n";

        cout << "Shirts: ";

        cin >> Order.NumberOfShirts;

        cout << "Pairs of Paints: ";

        cin >> Order.NumberOfPants;

        cout << "Misc. Items(if none, type 0): ";

        cin >> Order.NumberMisc;



        // If there are miscalleanous items,...

        if(Order.NumberOfMisc > 0)

        {

            // let the user determine the price of this misc item

            cout << "Enter the price of each miscellanous item: ";

            cin >> PriceMisc;

            TotalPriceMisc = Order.NumberOfMisc * PriceMisc;

        }

        else

            TotalPriceMisc = 0.00;



        TotalPriceShirts = Order.NumberOfShirts * PriceShirt;

        TotalPricePants  = Order.NumberOfPants  * PricePants;

        TotalOrder = TotalPriceShirts + TotalPricePants + TotalPriceMisc;



        cout << setiosflags(ios::fixed) << setprecision(2);

        cout << " - Georgetown Cleaning Services -";

        cout << "\n -  Customer Receipt  -"; 

        cout << "\n============================";

        cout << "\n Item\tNumber\tPrice";

        cout << "\n----------------------------";

        cout << "\n Shirts\t" << Order.NumberOfShirts

             << "\t$" <<  TotalPriceShirts;

        cout << "\n Pants\t" << Order.NumberOfPants

             << "\t$" << TotalPricePants;

        cout << "\n Misc\t" << Order.NumberOfMisc

             << "\t$" << TotalPriceMisc;

        cout << "\n============================";

        cout << "\n Total Order:\t$" << TotalOrder;

    }

    catch(...)

    {

        cout << "\nSomething went wrong - Too Bad";

    }

    

    return 0;

}

//---------------------------------------------------------------------------

 

 

 

Nevertheless, we have learned so far to catch exceptions and to throw them to a section that can handle them. One of the problems that could occur in a program is the clerk not entering valid numbers, which would imply that we want the compiler to multiply strings by constant numbers. Therefore, we can examine each number that the clerk would type and handle its exception in case of an invalid number.

The simplest way you can check an integer is through the use of the isdigit() function. The only problem we will have at this time is that the isdigit() function checks only one digit or character. Here is one attempt at addressing the problem:

//---------------------------------------------------------------------------

#include <iostream>

#include <iomanip>

using namespace std;

//---------------------------------------------------------------------------

// Constant prices of items, set by the store management

const double PriceShirt = 0.99;

const double PricePants = 1.75;



// Create an order object

struct TCleaningOrder

{

    int NumberOfShirts;

    int NumberOfPants;

    int NumberOfMisc;

};

//---------------------------------------------------------------------------

int main(int argc, char* argv[])

{

    TCleaningOrder Order;

    double TotalPriceShirts, TotalPricePants;

    double PriceMisc, TotalPriceMisc;

    double TotalOrder;



    cout << " - Georgetown Cleaning Services -\n";

    cout << "  - Customer Order Processing -\n";



    try {

        cout << "Number of\n";

        cout << "Shirts: ";

        cin >> Order.NumberOfShirts;

        if( isdigit(Order.NumberOfShirts) )

            throw Order.NumberOfShirts;

        cout << "Pairs of Paints: ";

        cin >> Order.NumberOfPants;

        if( isdigit(Order.NumberOfPants) )

            throw Order.NumberOfPants;

        cout << "Misc. Items(if none, type 0): ";

        cin >> Order.NumberMisc;

        if( isdigit(Order.NumberOfMisc) )

            throw Order.NumberOfMisc;



        // If there are miscalleanous items,...

        if(Order.NumberMisc > 0)

        {

            // let the user determine the price of this misc item

            cout << "Enter the price of each miscellanous item: ";

            cin >> PriceMisc;

            TotalPriceMisc = Order.NumberOfMisc * PriceMisc;

        }

        else

            TotalPriceMisc = 0.00;



        TotalPriceShirts = Order.NumberOfShirts * PriceShirt;

        TotalPricePants  = Order.NumberOfPants  * PricePants;

        TotalOrder = TotalPriceShirts + TotalPricePants + TotalPriceMisc;



        cout << setiosflags(ios::fixed) << setprecision(2);

        cout << " - Georgetown Cleaning Services -";

        cout << "\n -  Customer Receipt  -"; 

        cout << "\n============================";

        cout << "\n Item\tNumber\tPrice";

        cout << "\n----------------------------";

        cout << "\n Shirts\t" << Order.NumberOfShirts

             << "\t$" <<  TotalPriceShirts;

        cout << "\n Pants\t" << Order.NumberOfPants

             << "\t$" << TotalPricePants;

        cout << "\n Misc\t" << Order.NumberMisc

             << "\t$" << TotalPriceMisc;

        cout << "\n============================";

        cout << "\n Total Order:\t$" << TotalOrder;

    }

    catch(const int n)

    {

        cout << n << " is not a valid number";

    }

    catch(...)

    {

        cout << "\nSomething went wrong - Too Bad";

    }

    

    return 0;

}

//---------------------------------------------------------------------------

Practical Learning: Introduction to Class' Exceptions

  1. Create a C++ Console Application.
  2. Save the first file as Main and save the project as Exceptional
  3. Change the content of the Main.cpp file as follows:
     
    //---------------------------------------------------------------------------
    
    #include <iostream>
    
    using namespace std;
    
    //---------------------------------------------------------------------------
    
    
    
    class TCalculator
    
    {
    
    public:
    
        double Operand1;
    
        double Operand2;
    
        char Operator;
    
    };
    
    //---------------------------------------------------------------------------
    
    int main(int argc, char* argv[])
    
    {
    
        TCalculator Calc;
    
        double Result;
    
    
    
        // Request two numbers from the user
    
        cout << "This program allows you to perform an operation on two numbers\n";
    
        cout << "To proceed, enter two numbers\n";
    
    
    
        try {
    
    	cout << "First Number:  ";
    
    	cin >> Calc.Operand1;
    
    	cout << "Operator:      ";
    
    	cin >> Calc.Operator;
    
    	cout << "Second Number: ";
    
    	cin >> Calc.Operand2;
    
    
    
    	// Make sure the user typed a valid operator
    
    	if(Calc.Operator != '+' && Calc.Operator != '-' &&
    
    	   Calc.Operator != '*' && Calc.Operator != '/')
    
    		throw Calc.Operator;
    
    	// Find out if the denominator is 0
    
    	if(Calc.Operator == '/')
    
    	    if(Calc.Operand2 == 0)
    
    		throw 0;
    
    
    
    	// Perform an operation based on the user's choice
    
    	switch(Calc.Operator)
    
    	{
    
    	case '+':
    
    		Result = Calc.Operand1 + Calc.Operand2;
    
    		break;
    
    
    
    	case '-':
    
    		Result = Calc.Operand1 - Calc.Operand2;
    
    		break;
    
    
    
    	case '*':
    
    		Result = Calc.Operand1 * Calc.Operand2;
    
    		break;
    
    
    
    	case '/':
    
    		Result = Calc.Operand1 / Calc.Operand2;
    
    		break;
    
    	}
    
    
    
    	// Display the result of the operation
    
    	cout << "\n" << Calc.Operand1 << " " << Calc.Operator << " "
    
    	     << Calc.Operand2 << " = " << Result;
    
        }
    
        catch(const char n)
    
        {
    
    	cout << "\nOperation Error: " << n << " is not a valid operator";
    
        }
    
        catch(const int p)
    
        {
    
    	cout << "\nBad Operation: Division by " << p << " not allowed";
    
        }
    
        
    
        return 0;
    
    }
    
    //---------------------------------------------------------------------------
  4. To test your program with two non-zero numbers. Here is an example:
     
    This program allows you to perform an operation on two numbers
    
    To proceed, enter
    
    First number: 1450
    
    Second number: 32
    
    
    
    1450 / 32 = 45.3125
    
    
    
    Press any key to continue...
  5. Return to your programming environment
  6. You can also use external functions that check and throw exceptions to other functions that can handle them. As an example, change the program as follows:
     
    //---------------------------------------------------------------------------
    
    #include <iostream>
    
    using namespace std;
    
    //---------------------------------------------------------------------------
    
    
    
    class TCalculator
    
    {
    
    public:
    
        double Operand1;
    
        double Operand2;
    
        char Operator;
    
    };
    
    //---------------------------------------------------------------------------
    
    double CalcResult(const double x, const char p, const double y)
    
    {
    
        double R;
    
    
    
        // Perform an operation based on the user's choice
    
        switch(p)
    
        {
    
        case '+':
    
    	R = x + y;
    
    	break;
    
    
    
        case '-':
    
    	R = x - y;
    
    	break;
    
    
    
        case '*':
    
    	R = x * y;
    
    	break;
    
    
    
        case '/':
    
             if( y == 0 )
    
                 throw 0;
    
    	R = x / y;
    
    	break;
    
        }
    
    
    
        return R;
    
    }
    
    //---------------------------------------------------------------------------
    
    int main(int argc, char* argv[])
    
    {
    
        TCalculator Calc;
    
        double Result;
    
    
    
        // Request two numbers from the user
    
        cout << "This program allows you to perform an operation of two numbers\n";
    
        cout << "To proceed, enter two numbers\n";
    
    
    
        try {
    
    	cout << "First Number:  ";
    
    	cin >> Calc.Operand1;
    
    	cout << "Operator:      ";
    
    	cin >> Calc.Operator;
    
    	cout << "Second Number: ";
    
    	cin >> Calc.Operand2;
    
    
    
    	// Make sure the user typed a valid operator
    
    	if(Calc.Operator != '+' && Calc.Operator != '-' &&
    
    	   Calc.Operator != '*' && Calc.Operator != '/')
    
    		throw Calc.Operator;
    
    
    
            Result = CalcResult(Calc.Operand1, Calc.Operator, Calc.Operand2);
    
    
    
    		// Display the result of the operation
    
    		cout << "\n" << Calc.Operand1 << " " << Calc.Operator << " "
    
    		     << Calc.Operand2 << " = " << Result << "\n\n";
    
        }
    
        catch(const char n)
    
        {
    
    	cout << "\nOperation Error: " << n << " is not a valid operator";
    
        }
    
        catch(const int p)
    
        {
    
    	cout << "\nBad Operation: Division by " << p << " not allowed";
    
        }
    
        
    
        cout << "\nPress any key to continue...";
    
        
    
        return 0;
    
    }
    
    //---------------------------------------------------------------------------
  7. Test it and return to your programming environment.
 

Introduction to Exceptions in Classes

Probably the most basic use of exceptions you can make of a class is to let a class handle its own exceptions and hand the result, reliable results, to its clients. You handle exceptions in a class by using its method member. The main difference between a regular function and a class’ member function is that a regular function may need arguments from external functions to carry intermediary assignments. A member function of a class can use the member variables of the same class as if they were passed as arguments. You can use this feature of classes to handle exceptions effectively. This allows each class' method to handle its own exception(s), if any.

We saw earlier that when an order is being processed, a clerk can enter an invalid number of items. Just like we did in the main() function, we can take care of this possible exception in a function where the order is being processed. Therefore, when solution to implement for this type of scenario is to declare a function that processes orders for the TCleaningOrder object. Here is an example:

#include <iostream>

#include <iomanip>



using namespace std;



// Constant prices of items, set by the store management

const double PriceShirt = 0.99;

const double PricePants = 1.75;



// Create an order object

struct TCleaningOrder

{

public:

    TCleaningOrder();

    ~TCleaningOrder();

    void ProcessOrder();

    void DisplayReceipt();

private:

    int NumberOfShirts;

    int NumberOfPants;

    int NumberOfMisc;

    double TotalPriceShirts;

    double TotalPricePants;

    double TotalPriceMisc;

    double TotalOrder;

};

//---------------------------------------------------------------------------

TCleaningOrder::TCleaningOrder()

    :  NumberOfShirts(0), NumberOfPants(0), NumberMisc(0)

{

}

//---------------------------------------------------------------------------

TCleaningOrder::~TCleaningOrder()

{

}

//---------------------------------------------------------------------------

void TCleaningOrder::ProcessOrder()

{

    double PriceMisc;



    try {

        cout << "Number of\n";

        cout << "Shirts: ";

        cin >> NumberOfShirts;

        if( isdigit(NumberOfShirts) )

            throw NumberOfShirts;

        cout << "Pairs of Paints: ";

        cin >> NumberOfPants;

        if( isdigit(NumberOfPants) )

            throw NumberOfPants;

        cout << "Misc. Items(if none, type 0): ";

        cin >> NumberMisc;

        if( isdigit(NumberOfMisc) )

            throw NumberOfMisc;



        // If there are miscalleanous items,...

        if(NumberMisc > 0)

        {

            // let the user determine the price of this misc item

            cout << "Enter the price of each miscellanous item: ";

            cin >> PriceMisc;

            TotalPriceMisc = NumberOfMisc * PriceMisc;

        }

        else

            TotalPriceMisc = 0.00;



        TotalPriceShirts = NumberOfShirts * PriceShirt;

        TotalPricePants  = NumberOfPants  * PricePants;

        TotalOrder = TotalPriceShirts + TotalPricePants + TotalPriceMisc;

    }

    catch(const int n)

    {

        cout << n << " is not a valid number";

    }

    catch(...)

    {

        cout << "\nSomething went wrong - Too Bad";

    }

}

//---------------------------------------------------------------------------

void TCleaningOrder::DisplayReceipt()

{

    cout << setiosflags(ios::fixed) << setprecision(2);

    cout << " - Georgetown Cleaning Services -";

    cout << "\n -  Customer Receipt  -";

    cout << "\n============================";

    cout << "\n Item\tNumber\tPrice";

    cout << "\n----------------------------";

    cout << "\n Shirts\t" << NumberOfShirts

         << "\t$" <<  TotalPriceShirts;

    cout << "\n Pants\t" << NumberOfPants

         << "\t$" << TotalPricePants;

    cout << "\n Misc\t" << NumberOfMisc

         << "\t$" << TotalPriceMisc;

    cout << "\n============================";

    cout << "\n Total Order:\t$" << TotalOrder;

}

//---------------------------------------------------------------------------

int main(int argc, char* argv[])

{

    TCleaningOrder Order;



    cout << " - Georgetown Cleaning Services -\n";

    cout << "  - Customer Order Processing -\n";



    Order.ProcessOrder();

    clrscr();

    Order.DisplayReceipt();



    

    

    

    return 0;

}

//---------------------------------------------------------------------------

Practical Learning: Class' Methods and their Exceptions

  1. As an example, change the program as follows:
     
    //---------------------------------------------------------------------------
    
    #include <iostream>
    
    using namespace std;
    
    //---------------------------------------------------------------------------
    
    
    
    class TCalculator
    
    {
    
    public:
    
        TCalculator();
    
        void RequestOperands();
    
        void setOperation(const double x, const char p, const double y);
    
        double CalcResult() const;
    
        void DisplayResult() const;
    
    private:
    
        double Operand1;
    
        double Operand2;
    
        char Operator;
    
    };
    
    //---------------------------------------------------------------------------
    
    TCalculator::TCalculator()
    
    {
    
    }
    
    //---------------------------------------------------------------------------
    
    void TCalculator::RequestOperands()
    
    {
    
        try {
    
            cout << "First number: ";
    
            cin >> Operand1;
    
            cout << "Operator: ";
    
            cin >> Operator;
    
            cout << "Second number: ";
    
            cin >> Operand2;
    
    
    
            // Make sure the user typed a valid operator
    
    	    if(Operator != '+' && Operator != '-' &&
    
    	        Operator != '*' && Operator != '/')
    
    		        throw Operator;
    
    
    
            setOperation(Operand1, Operator, Operand2);
    
        }
    
        catch(const char c)
    
        {
    
            cout << "Bad Operator: " << c << " is not a valid operator";
    
        }
    
    }
    
    //---------------------------------------------------------------------------
    
    void TCalculator::setOperation(const double Num,
    
                                  const char c, const double Denom)
    
    {
    
        Operand1 = Num;
    
        Operator = c;
    
        Operand2 = Denom;
    
    }
    
    //---------------------------------------------------------------------------
    
    double TCalculator::CalcResult() const
    
    {
    
        double R;
    
    
    
        // Perform an operation based on the user's choice
    
        switch(Operator)
    
        {
    
        case '+':
    
    	R = Operand1 + Operand2;
    
    	break;
    
    
    
        case '-':
    
    	R = Operand1 - Operand2;
    
    	break;
    
    
    
        case '*':
    
    	R = Operand1 * Operand2;
    
    	break;
    
    
    
        case '/':
    
            try {
    
                if( Operand2 == 0 )
    
    		        throw "Division by zero not allowed";
    
    
    
    	        R = Operand1 / Operand2;
    
            }
    
            catch(const char *Str)
    
            {
    
                cout << "\nBad Operator: " << Str;
    
            }
    
            break;
    
        }
    
    
    
        return R;
    
    }
    
    //---------------------------------------------------------------------------
    
    void TCalculator::DisplayResult() const
    
    {
    
        double Result;
    
        CalcResult();
    
    
    
        Result = CalcResult();
    
        // Display the result of the operation
    
    	cout << "\n" << Operand1 << " " << Operator << " "
    
    	     << Operand2 << " = " << Result;
    
    }
    
    //---------------------------------------------------------------------------
    
    int main(int argc, char* argv[])
    
    {
    
        TCalculator Calc;
    
        double Number1, Number2, Result;
    
        char Oper;
    
    
    
        cout << "This program allows you to perform an operation on two numbers\n";
    
        cout << "To proceed, enter\n";
    
    
    
        Calc.RequestOperands();
    
        Calc.DisplayResult();
    
    
    
        cout << "\nPress any key to continue...";
    
        
    
        return 0;
    
    }
    
    //---------------------------------------------------------------------------
  2. Test the program and return to your programming environment

Exception-Oriented Classes

As in the earlier ProcessOrder() function, a method, and each necessary method, of a class can handle its own exceptions locally, perform the desired assignment, and send the result to the client that made the call. Alternatively, just like our main() function had been previously, you can create a member function of a class and let that function act as the central point of the class. Such a typical function is used to process transactions related to a class. To do this, implement the other member functions and let them throw the exceptions they encounter. While a member function is carrying its assignment, if it encounters an exception, it can throw it to the central function where the call was made. The central function would find the appropriate catch that can handle the exception. This scenario can be applied to set functions because a set function has the responsibility of checking or validating the value carried by its corresponding member variable. If the value is invalid, the set function can simply throw an exception and get out. Such a set function would look like this:

void TCleaningOrder::setShirts(const int Shirts)

{

    if( isdigit(Shirts) )

        throw Shirts;

    NumberOfShirts = Shirts;

}

This member function receives an argument and checks it. If the sent argument is not a valid digit, the setShirts() method throws an exception that carries the same argument that was sent. As you can see, and as we have done with throwing exceptions so far, the setShirts() method doesn't care who (that is, what) sent the wrong argument; it simply throws it back and stops there. On the other hand, if the argument that was sent is good, the setShirts() method assigns it to the NumberOfShirts member variable (remember that it is the setShirts() responsibility to control the value that its corresponding member variable, in this case NumberOfShirts, carries). The client function that sent the request (the request consisted of asking the setShirts() function to validate the character) will need to know what to do with the thrown exception.

Once a "central" function that passes arguments to other member methods that validate them, this "central" function doesn't need to throw any more exceptions, but since the others will likely or possibly throw exceptions, our "central function needs to be prepared to catch them and handle them appropriately. In the following example, the ProcessOrder() method acts as that "central" function:

//---------------------------------------------------------------------------

#include <iostream>

#include <iomanip>



using namespace std;

//---------------------------------------------------------------------------



// Constant prices of items, set by the store management

const double PriceShirt = 0.99;

const double PricePants = 1.75;



// Create an order object

struct TCleaningOrder

{

public:

    void setShirts(const int Shirts);

    int getShirts() { return NumberOfShirts; }

    void setPants(const int Pants);

    int getPants() { return NumberOfPants; }

    void setMisc(const int Misc);

    int getMisc() { return NumberOfMisc; }

    TCleaningOrder();

    ~TCleaningOrder();

    void ProcessOrder();

    void DisplayReceipt();

private:

    int NumberOfShirts;

    int NumberOfPants;

    int NumberOfMisc;

    double TotalPriceShirts;

    double TotalPricePants;

    double TotalPriceMisc;

    double TotalOrder;

};

//---------------------------------------------------------------------------

TCleaningOrder::TCleaningOrder()

    :  NumberOfShirts(0), NumberOfPants(0), NumberOfMisc(0)

{

}

//---------------------------------------------------------------------------

TCleaningOrder::~TCleaningOrder()

{

}

//---------------------------------------------------------------------------

void TCleaningOrder::setShirts(const int Shirts)

{

    if( isdigit(Shirts) )

        throw Shirts;

    NumberOfShirts = Shirts;

}

//---------------------------------------------------------------------------

void TCleaningOrder::setPants(const int Pants)

{

    if( isdigit(Pants) )

        throw Pants;

    NumberOfPants = Pants;

}

//---------------------------------------------------------------------------

void TCleaningOrder::setMisc(const int Misc)

{

    if( isdigit(Misc) )

        throw Misc;

    NumberOfMisc = Misc;

}

//---------------------------------------------------------------------------

void TCleaningOrder::ProcessOrder()

{

    double PriceMisc;

    int Shirts, Pants, Misc;



    try {

        cout << "Number of\n";

        cout << "Shirts: ";

        cin >> Shirts;

        setShirts(Shirts);

        cout << "Pairs of Paints: ";

        cin >> Pants;

        setPants(Pants);

        cout << "Misc. Items(if none, type 0): ";

        cin >> Misc;

        setMisc(Misc);



        // If there are miscalleanous items,...

        if(getMisc() > 0)

        {

            // let the user determine the price of this misc item

            cout << "Enter the price of each miscellanous item: ";

            cin >> PriceMisc;

            TotalPriceMisc = NumberOfMisc * PriceMisc;

        }

        else

            TotalPriceMisc = 0.00;



        TotalPriceShirts = NumberOfShirts * PriceShirt;

        TotalPricePants  = NumberOfPants  * PricePants;

        TotalOrder = TotalPriceShirts + TotalPricePants + TotalPriceMisc;

    }

    catch(const int n)

    {

        cout << n << " is not a valid number";

    }

    catch(...)

    {

        cout << "\nSomething went wrong - Too Bad";

    }

}

//---------------------------------------------------------------------------

void TCleaningOrder::DisplayReceipt()

{

    cout << setiosflags(ios::fixed) << setprecision(2);

    cout << " - Georgetown Cleaning Services -";

    cout << "\n -  Customer Receipt  -";

    cout << "\n============================";

    cout << "\n Item\tNumber\tPrice";

    cout << "\n----------------------------";

    cout << "\n Shirts\t" << NumberOfShirts

         << "\t$" <<  TotalPriceShirts;

    cout << "\n Pants\t" << NumberOfPants

         << "\t$" << TotalPricePants;

    cout << "\n Misc\t" << NumberOfMisc

         << "\t$" << TotalPriceMisc;

    cout << "\n============================";

    cout << "\n Total Order:\t$" << TotalOrder;

}

//---------------------------------------------------------------------------

int main(int argc, char* argv[])

{

    TCleaningOrder Order;



    cout << " - Georgetown Cleaning Services -\n";

    cout << "  - Customer Order Processing -\n";



    Order.ProcessOrder();

    clrscr();

    Order.DisplayReceipt();



    

    

    return 0;

}

//---------------------------------------------------------------------------

Practical Learning: Improving Class' Exceptions

For our exercise, we will create a member function for a Calculator class. We use this function to proces a calculation. We also prepare this function to handle various exceptions that can be (or would be) thrown by other functions. The exceptions can be thrown based on a wrong operand or a wrong operator. The class can be implemented in a program as follows (some functions, such as the get methods were added to allow external functions to communicate with the member variables of the class).

  1. Change the content of the file as follows:
     
    //---------------------------------------------------------------------------
    
    #include <iostream>
    
    using namespace std;
    
    //---------------------------------------------------------------------------
    
    
    
    class TCalculator
    
    {
    
    public:
    
        TCalculator();
    
    	TCalculator(char* Oper1, char Opr, char* Oper2);
    
        void RequestOperands();
    
        void setOperand1(const char* Oper1);
    
        double getOperand1() const;
    
        void setOperand2(const char *Oper2);
    
        double getOperand2() const;
    
        void setOperator(const char Opr);
    
        char getOperator() const;
    
        void setOperation(const char* x, const char p, const char* y);
    
        double CalcResult() const;
    
        void DisplayResult() const;
    
    private:
    
        double Operand1;
    
        double Operand2;
    
        char Operator;
    
    };
    
    //---------------------------------------------------------------------------
    
    TCalculator::TCalculator()
    
    {
    
    }
    
    //---------------------------------------------------------------------------
    
    TCalculator::TCalculator(char* Oper1, char Opr, char* Oper2)
    
    {
    
    	setOperand1(Oper1);
    
    	setOperator(Opr);
    
    	setOperand2(Oper2);
    
    }
    
    //---------------------------------------------------------------------------
    
    void TCalculator::RequestOperands()
    
    {
    
    
    
    	char Number1[40], Number2[40];
    
    	char Oper;
    
    
    
    	try {
    
    		cout << "To proceed, enter\n";
    
    		cout << "First Number: "; cin >> Number1;
    
    		cout << "An Operator: "; cin >> Oper;
    
    		cout << "Second Number: "; cin >> Number2;
    
    
    
    		setOperand1(Number1);
    
    		setOperator(Oper);
    
    		setOperand2(Number2);
    
    
    
    		CalcResult();
    
    	}
    
    	catch(const char n)
    
    	{
    
    		cout << "\nOperation Error: " << n << " is not a valid operator";
    
    	}
    
    	catch(const char *BadOperand)
    
    	{
    
    		cout << "\nError: " << BadOperand << " is not a valid number";
    
    	}
    
    	catch(const int n)
    
    	{
    
    		cout << "\nBad Operation: Division by " << n << " not allowed";
    
    	}
    
    }
    
    //---------------------------------------------------------------------------
    
    void TCalculator::setOperand1(const char* Oper1)
    
    {
    
    	for(unsigned int i = 0; i < strlen(Oper1); i++)
    
    		if( (!isdigit(Oper1[i])) && (Oper1[i] != '.') )
    
    			throw Oper1;
    
    	
    
    	Operand1 = atof(Oper1);
    
    }
    
    
    
    //---------------------------------------------------------------------------
    
    double TCalculator::getOperand1() const
    
    {
    
    	return Operand1;
    
    }
    
    
    
    //---------------------------------------------------------------------------
    
    void TCalculator::setOperand2(const char* Oper2)
    
    {
    
    	for(unsigned int i = 0; i < strlen(Oper2); i++)
    
    		if( (!isdigit(Oper2[i])) && (Oper2[i] != '.') )
    
    			throw Oper2;
    
    	
    
    	Operand2 = atof(Oper2);
    
    }
    
    
    
    //---------------------------------------------------------------------------
    
    double TCalculator::getOperand2() const
    
    {
    
    	return Operand2;
    
    }
    
    
    
    //---------------------------------------------------------------------------
    
    void TCalculator::setOperator(const char Symbol)
    
    {
    
    	if(Symbol != '+' && Symbol != '-' &&
    
    	   Symbol != '*' && Symbol != '/')
    
    		throw Symbol;
    
    
    
    	Operator = Symbol;
    
    }
    
    //---------------------------------------------------------------------------
    
    char TCalculator::getOperator() const
    
    {
    
    	return Operator;
    
    }
    
    //---------------------------------------------------------------------------
    
    void TCalculator::setOperation(const char* Oper1,
    
                            const char Opr, const char* Oper2)
    
    {
    
    	setOperand1(Oper1);
    
    	setOperator(Opr);
    
    	setOperand2(Oper2);
    
    }
    
    //---------------------------------------------------------------------------
    
    double TCalculator::CalcResult() const
    
    {
    
        double R;
    
    
    
        // Perform an operation based on the user's choice
    
        switch(Operator)
    
        {
    
        case '+':
    
    	    R = Operand1 + Operand2;
    
    	    break;
    
    
    
        case '-':
    
    	    R = Operand1 - Operand2;
    
    	    break;
    
    
    
        case '*':
    
    	    R = Operand1 * Operand2;
    
    	    break;
    
    
    
        case '/':
    
            try {
    
                if( Operand2 == 0 )
    
    		        throw "Division by zero not allowed";
    
    
    
    	        R = Operand1 / Operand2;
    
            }
    
            catch(const char *Str)
    
            {
    
                cout << "\nBad Operator: " << Str;
    
            }
    
            break;
    
        }
    
    
    
        return R;
    
    }
    
    //---------------------------------------------------------------------------
    
    void TCalculator::DisplayResult() const
    
    {
    
        double Result;
    
        CalcResult();
    
    
    
        Result = CalcResult();
    
        // Display the result of the operation
    
    	cout << "\n" << Operand1 << " " << Operator << " "
    
    	     << Operand2 << " = " << Result;
    
    }
    
    //---------------------------------------------------------------------------
    
    int main(int argc, char* argv[])
    
    {
    
        TCalculator Calc;
    
        double Number1, Number2, Result;
    
        char Oper;
    
    
    
        cout << "This program allows you to perform an operation on two numbers\n";
    
    
    
        Calc.RequestOperands();
    
        Calc.DisplayResult();
    
    
    
        cout << "\nPress any key to continue...";
    
        
    
        return 0;
    
    }
    
    //---------------------------------------------------------------------------
  2. Test the program and return to your programming environment.
  3. Just as done with the functions, you can show that a function throws one or more exceptions in its declaration. To do this, in the class, on the right side of the function that throws an exception, type the throw keyword followed by parentheses in which you would provide the type of exception that the following would throw.
    To apply this, change the function as follows:
     
    //---------------------------------------------------------------------------
    
    #include <iostream>
    
    using namespace std;
    
    //---------------------------------------------------------------------------
    
    
    
    class TCalculator
    
    {
    
    public:
    
        TCalculator();
    
    	TCalculator(char* Oper1, char Opr, char* Oper2);
    
        void RequestOperands();
    
        void setOperand1(const char* Oper1) throw(const char*);
    
        double getOperand1() const;
    
        void setOperand2(const char *Oper2) throw(const char*);
    
        double getOperand2() const;
    
        void setOperator(const char Opr) throw(const char);
    
        char getOperator() const;
    
        void setOperation(const char* x, const char p, const char* y);
    
        double CalcResult() const;
    
        void DisplayResult() const;
    
    private:
    
        double Operand1;
    
        double Operand2;
    
        char Operator;
    
    };
    
    //---------------------------------------------------------------------------
    
    TCalculator::TCalculator()
    
    {
    
    }
    
    //---------------------------------------------------------------------------
    
    TCalculator::TCalculator(char* Oper1, char Opr, char* Oper2)
    
    {
    
    	setOperand1(Oper1);
    
    	setOperator(Opr);
    
    	setOperand2(Oper2);
    
    }
    
    //---------------------------------------------------------------------------
    
    void TCalculator::RequestOperands()
    
    {
    
    	char Number1[40], Number2[40];
    
    	char Oper;
    
    
    
    	try {
    
    		cout << "To proceed, enter\n";
    
    		cout << "First Number: "; cin >> Number1;
    
    		cout << "An Operator: "; cin >> Oper;
    
    		cout << "Second Number: "; cin >> Number2;
    
    
    
    		setOperand1(Number1);
    
    		setOperator(Oper);
    
    		setOperand2(Number2);
    
    
    
    		CalcResult();
    
    	}
    
    	catch(const char n)
    
    	{
    
    		cout << "\nOperation Error: " << n << " is not a valid operator";
    
    	}
    
    	catch(const char *BadOperand)
    
    	{
    
    		cout << "\nError: " << BadOperand << " is not a valid number";
    
    	}
    
    	catch(const int n)
    
    	{
    
    		cout << "\nBad Operation: Division by " << n << " not allowed";
    
    	}
    
    }
    
    //---------------------------------------------------------------------------
    
    void TCalculator::setOperand1(const char* Oper1) throw(const char*)
    
    {
    
    	for(unsigned int i = 0; i < strlen(Oper1); i++)
    
    		if( (!isdigit(Oper1[i])) && (Oper1[i] != '.') )
    
    			throw Oper1;
    
    	
    
    	Operand1 = atof(Oper1);
    
    }
    
    //---------------------------------------------------------------------------
    
    double TCalculator::getOperand1() const
    
    {
    
    	return Operand1;
    
    }
    
    //---------------------------------------------------------------------------
    
    void TCalculator::setOperand2(const char* Oper2) throw(const char*)
    
    {
    
    	for(unsigned int i = 0; i < strlen(Oper2); i++)
    
    		if( (!isdigit(Oper2[i])) && (Oper2[i] != '.') )
    
    			throw Oper2;
    
    	
    
    	Operand2 = atof(Oper2);
    
    }
    
    
    
    //---------------------------------------------------------------------------
    
    double TCalculator::getOperand2() const
    
    {
    
    	return Operand2;
    
    }
    
    //---------------------------------------------------------------------------
    
    void TCalculator::setOperator(const char Symbol) throw(const char)
    
    {
    
    	if(Symbol != '+' && Symbol != '-' &&
    
    	   Symbol != '*' && Symbol != '/')
    
    		throw Symbol;
    
    
    
    	Operator = Symbol;
    
    }
    
    //---------------------------------------------------------------------------
    
    .
    
    .
    
    .
  4. Test the program and return to your programming environment.

 

Separating the Object from its Implementation

As we did in previous lessons, you don't need to keep a class and its source file in the same file. You can separate the header and the C++ source in separate files. This is done in the same way you would do by creating a unit.

Practical Learning: Creating a Class

  1. Create a new C++ Console Application.
  2. Create a folder called Exceptional2
  3. Save Unit1 as Main and save the project as Exceptions
  4. To create a new class, on the main menu, click File -> New... or File -> New -> Other...
  5. From the New property sheet of the New Object dialog box, double-click Unit
  6. Save the class as Calculator
  7. Click the Calculator.h tab and change the content of the file as follows:
     
    //---------------------------------------------------------------------------
    
    #ifndef CalculatorH
    
    #define CalculatorH
    
    //---------------------------------------------------------------------------
    
    class TCalculator
    
    {
    
    public:
    
        TCalculator();
    
        TCalculator(char* Oper1, char Opr, char* Oper2);
    
        void RequestOperands();
    
        void setOperand1(const char* Oper1) throw(const char*);
    
        double getOperand1() const;
    
        void setOperand2(const char *Oper2) throw(const char*);
    
        double getOperand2() const;
    
        void setOperator(const char Opr) throw(const char);
    
        char getOperator() const;
    
        void setOperation(const char* x, const char p, const char* y);
    
        double CalcResult() const;
    
        void DisplayResult() const;
    
    private:
    
        double Operand1;
    
        double Operand2;
    
        char Operator;
    
    };
    
    //---------------------------------------------------------------------------
    
    #endif
  8. Click the Calculator.cpp tab and change its content as follows:
     
    //---------------------------------------------------------------------------
    
    #include <iostream>
    
    using namespace std;
    
    
    
    #include "Calculator.h"
    
    //---------------------------------------------------------------------------
    
    TCalculator::TCalculator()
    
    {
    
    }
    
    //---------------------------------------------------------------------------
    
    TCalculator::TCalculator(char* Oper1, char Opr, char* Oper2)
    
    {
    
    	setOperand1(Oper1);
    
    	setOperator(Opr);
    
    	setOperand2(Oper2);
    
    }
    
    //---------------------------------------------------------------------------
    
    void TCalculator::RequestOperands()
    
    {
    
    	char Number1[40], Number2[40];
    
    	char Oper;
    
    
    
    	try {
    
    		cout << "To proceed, enter\n";
    
    		cout << "First Number: "; cin >> Number1;
    
    		cout << "An Operator: "; cin >> Oper;
    
    		cout << "Second Number: "; cin >> Number2;
    
    
    
    		setOperand1(Number1);
    
    		setOperator(Oper);
    
    		setOperand2(Number2);
    
    
    
    		CalcResult();
    
    	}
    
    	catch(const char n)
    
    	{
    
    		cout << "\nOperation Error: " << n << " is not a valid operator";
    
    	}
    
    	catch(const char *BadOperand)
    
    	{
    
    		cout << "\nError: " << BadOperand << " is not a valid number";
    
    	}
    
    	catch(const int n)
    
    	{
    
    		cout << "\nBad Operation: Division by " << n << " not allowed";
    
    	}
    
    }
    
    //---------------------------------------------------------------------------
    
    void TCalculator::setOperand1(const char* Oper1) throw(const char*)
    
    {
    
    	for(unsigned int i = 0; i < strlen(Oper1); i++)
    
    		if( (!isdigit(Oper1[i])) && (Oper1[i] != '.') )
    
    			throw Oper1;
    
    	
    
    	Operand1 = atof(Oper1);
    
    }
    
    //---------------------------------------------------------------------------
    
    double TCalculator::getOperand1() const
    
    {
    
    	return Operand1;
    
    }
    
    //---------------------------------------------------------------------------
    
    void TCalculator::setOperand2(const char* Oper2) throw(const char*)
    
    {
    
    	for(unsigned int i = 0; i < strlen(Oper2); i++)
    
    		if( (!isdigit(Oper2[i])) && (Oper2[i] != '.') )
    
    			throw Oper2;
    
    	
    
    	Operand2 = atof(Oper2);
    
    }
    
    
    
    //---------------------------------------------------------------------------
    
    double TCalculator::getOperand2() const
    
    {
    
    	return Operand2;
    
    }
    
    //---------------------------------------------------------------------------
    
    void TCalculator::setOperator(const char Symbol) throw(const char)
    
    {
    
    	if(Symbol != '+' && Symbol != '-' &&
    
    	   Symbol != '*' && Symbol != '/')
    
    		throw Symbol;
    
    
    
    	Operator = Symbol;
    
    }
    
    //---------------------------------------------------------------------------
    
    char TCalculator::getOperator() const
    
    {
    
    	return Operator;
    
    }
    
    //---------------------------------------------------------------------------
    
    void TCalculator::setOperation(const char* Oper1,
    
                            const char Opr, const char* Oper2)
    
    {
    
    	setOperand1(Oper1);
    
    	setOperator(Opr);
    
    	setOperand2(Oper2);
    
    }
    
    //---------------------------------------------------------------------------
    
    double TCalculator::CalcResult() const
    
    {
    
        double R;
    
    
    
        // Perform an operation based on the user's choice
    
        switch(Operator)
    
        {
    
        case '+':
    
    	    R = Operand1 + Operand2;
    
    	    break;
    
    
    
        case '-':
    
    	    R = Operand1 - Operand2;
    
    	    break;
    
    
    
        case '*':
    
    	    R = Operand1 * Operand2;
    
    	    break;
    
    
    
        case '/':
    
            try {
    
                if( Operand2 == 0 )
    
    		        throw "Division by zero not allowed";
    
    
    
    	        R = Operand1 / Operand2;
    
            }
    
            catch(const char *Str)
    
            {
    
                cout << "\nBad Operator: " << Str;
    
            }
    
            break;
    
        }
    
    
    
        return R;
    
    }
    
    //---------------------------------------------------------------------------
    
    void TCalculator::DisplayResult() const
    
    {
    
        double Result;
    
        CalcResult();
    
    
    
        Result = CalcResult();
    
        // Display the result of the operation
    
    	cout << "\n" << Operand1 << " " << Operator << " "
    
    	     << Operand2 << " = " << Result;
    
    }
    
    //---------------------------------------------------------------------------
  9. Click the Main.cpp tab and change its content as follows:
     
    //---------------------------------------------------------------------------
    
    #include <iostream>
    
    using namespace std;
    
    #include "Calculator.h"
    
    //---------------------------------------------------------------------------
    
    int main(int argc, char* argv[])
    
    {       
    
        TCalculator Calc;
    
        double Number1, Number2, Result;
    
        char Oper;
    
    
    
        cout << "This program allows you to perform an operation on two numbers\n";
    
    
    
        Calc.RequestOperands();
    
        Calc.DisplayResult();
    
    
    
        return 0;
    
    }
    
    //---------------------------------------------------------------------------
  10. Test the program
 

Previous Copyright © 2000-2016, FunctionX, Inc. Next