Exercises

  1. 10.6 (Memory Allocation and Deallocation Operators) Compare and contrast dynamic memory allocation and deallocation operators new, new [], delete and delete[].

  2. 10.7 (Overloading the Parentheses Operator) One nice example of overloading the function call operator () is to allow another form of double-array subscripting popular in some programming languages. Instead of saying

    
    chessBoard[row][column]
    

    for an array of objects, overload the function call operator to allow the alternate form

    
    chessBoard(row, column)
    

    Create a class DoubleSubscriptedArray that has similar features to class Array in Figs. 10.1010.11. At construction time, the class should be able to create a DoubleSubscriptedArray of any number of rows and columns. The class should supply operator() to perform double-subscripting operations. For example, in a 3-by-5 DoubleSubscriptedArray called chessBoard, the user could write chessBoard(1, 3) to access the element at row 1 and column 3. Remember that operator() can receive any number of arguments. The underlying representation of the DoubleSubscriptedArray could be a single-subscripted array of integers with rows * columns number of elements. Function operator() should perform the proper pointer arithmetic to access each element of the underlying array. There should be two versions of operator()—one that returns int& (so that an element of a DoubleSubscriptedArray can be used as an lvalue) and one that returns int. The class should also provide the following operators: ==, !=, =, << (for outputting the DoubleSubscriptedArray in row and column format) and >> (for inputting the entire DoubleSubscriptedArray contents).

  3. 10.8 (Complex Class) Consider class Complex shown in Figs. 10.1410.16. The class enables operations on so-called complex numbers. These are numbers of the form realPart + imaginaryPart * i, where i has the value

    1
    1. Modify the class to enable input and output of complex numbers via overloaded >> and << operators, respectively (you should remove the toString function from the class).

    2. Overload the multiplication operator to enable multiplication of two complex numbers as in algebra.

    3. Overload the == and != operators to allow comparisons of complex numbers.

    After doing this exercise, you might want to read about the Standard Library’s complex class (from header <complex>).

    Fig. 10.14 Complex class definition.

    Alternate View
    
     1   // Fig. 10.14: Complex.h
     2   // Complex class definition.
     3   #include <string>
     4
     5   #ifndef COMPLEX_H
     6   #define COMPLEX_H
     7
     8   class Complex {
     9   public:
    10      explicit Complex(double = 0.0, double = 0.0); // constructor
    11      Complex operator+(const Complex&) const; // addition
    12      Complex operator-(const Complex&) const; // subtraction
    13      std::string toString() const;
    14   private:
    15      double real; // real part
    16      double imaginary; // imaginary part
    17   };
    18
    19   #endif
    

    Fig. 10.15 Complex class member-function definitions.

    Alternate View
    
     1   // Fig. 10.15: Complex.cpp
     2   // Complex class member-function definitions.
     3   #include <string>
     4   #include "Complex.h" // Complex class definition
     5   using namespace std;
     6
     7   // Constructor
     8   Complex::Complex(double realPart, double imaginaryPart)
     9      : real{realPart}, imaginary{imaginaryPart} { }
    10
    11   // addition operator
    12   Complex Complex::operator+(const Complex& operand2) const {
    13      return Complex{real + operand2.real, imaginary + operand2.imaginary};
    14   }
    15
    16   // subtraction operator
    17   Complex Complex::operator-(const Complex& operand2) const {
    18      return Complex{real - operand2.real, imaginary - operand2.imaginary};
    19   }
    20
    21   // return string representation of a Complex object in the form: (a, b)
    22   string Complex::toString() const {
    23      return "("s + to_string(real) + ", "s + to_string(imaginary) + ")"s;
    24   }
    

    Fig. 10.16 Complex class test program.

    Alternate View
    
    25   // Fig. 10.16: fig10_16.cpp
    26   // Complex class test program.
    27   #include <iostream>
    28   #include "Complex.h"
    29   using namespace std;
    30
    31   int main() {
    32      Complex x;
    33      Complex y{4.3, 8.2};
    34      Complex z{3.3, 1.1};
    35
    36      cout << "x: " << x.toString() << "
    y: " << y.toString()
    37         << "
    z: " << z;
    38
    39      x = y + z;
    40      cout << "
    
    x = y + z:
    " << x.toString() << " = " << y.toString()
    41         << " + " << z.toString();
    42
    43      x = y - z;
    44      cout << "
    
    x = y - z:
    " << x.toString() << " = " << y.toString()
    45         << " - " << z.toString() << endl;
    46   }
    
    
    x: (0, 0)
    y: (4.3, 8.2)
    z: (3.3, 1.1)
    
    x = y + z:
    (7.6, 9.3) = (4.3, 8.2) + (3.3, 1.1)
    
    x = y - z:
    (1, 7.1) = (4.3, 8.2) - (3.3, 1.1)
    
  4. 10.9 (HugeInteger Class) A machine with 32-bit integers can represent integers in the range of approximately –2 billion to +2 billion. This fixed-size restriction is rarely troublesome, but there are applications in which we would like to be able to use a much wider range of integers. This is what C++ was built to do, namely, create powerful new data types. Consider class HugeInteger of Figs. 10.1710.19, which is similar to the HugeInteger class in Exercise 9.14. Study the class carefully, then respond to the following:

    1. Describe precisely how it operates.

    2. What restrictions does the class have?

    3. Overload the * multiplication operator.

    4. Overload the / division operator.

    5. Overload all the relational and equality operators.

    [Note: We do not show an assignment operator or copy constructor for class HugeInteger, because the assignment operator and copy constructor provided by the compiler are capable of copying the entire array data member properly.]

    Fig. 10.17 HugeInteger class definition.

    Alternate View
    
     1   // Fig. 10.17: HugeInteger.h
     2   // HugeInteger class definition.
     3   #ifndef HugeInteger_H
     4   #define HugeInteger_H
     5
     6   #include <array>
     7   #include <iostream>
     8   #include <string>
     9
    10   class HugeInteger {
    11      friend std::ostream& operator<<(std::ostream&, const HugeInteger&);
    12   public:
    13      static const int digits{40}; // maximum digits in a HugeInteger
    14
    15      HugeInteger(long = 0); // conversion/default constructor
    16      HugeInteger(const std::string&); // conversion constructor
    17
    18      // addition operator; HugeInteger + HugeInteger
    19      HugeInteger operator+(const HugeInteger&) const;
    20
    21      // addition operator; HugeInteger + int
    22      HugeInteger operator+(int) const;
    23
    24      // addition operator;
    25      // HugeInteger + string that represents large integer value
    26      HugeInteger operator+(const std::string&) const;
    27   private:
    28      std::array<short, digits> integer{};// default init to 0s
    29   };
    30
    31   #endif
    

    Fig. 10.18 HugeInteger member-function and friend-function definitions.

    Alternate View
    
     1   // Fig. 10.18: HugeInteger.cpp
     2   // HugeInteger member-function and friend-function definitions.
     3   #include <cctype> // isdigit function prototype
     4   #include "HugeInteger.h" // HugeInteger class definition
     5   using namespace std;
     6
     7   // default constructor; conversion constructor that converts
     8   // a long integer into a HugeInteger object
     9   HugeInteger::HugeInteger(long value) {
    10      // place digits of argument into array
    11      for (int j{digits - 1}; value != 0 && j >= 0; j--) {
    12         integer[j] = value % 10;
    13         value /= 10;
    14      }
    15   }
    16
    17   // conversion constructor that converts a character string
    18   // representing a large integer into a HugeInteger object
    19   HugeInteger::HugeInteger(const string& number) {
    20      // place digits of argument into array
    21      int length{number.size()};
    22
    23      for (int j{digits - length}, k{0}; j < digits; ++j, ++k) {
    24         if (isdigit(number[k])) {// ensure that character is a digit
    25            integer[j] = number[k] - '0';
    26         }
    27      }
    28   }
    29
    30   // addition operator; HugeInteger + HugeInteger
    31   HugeInteger HugeInteger::operator+(const HugeInteger& op2) const {
    32      HugeInteger temp; // temporary result
    33      int carry = 0;
    34
    35      for (int i{digits - 1}; i >= 0; i--) {
    36         temp.integer[i] = integer[i] + op2.integer[i] + carry;
    37
    38         // determine whether to carry a 1
    39         if (temp.integer[i] > 9) {
    40            temp.integer[i] %= 10; // reduce to 0-9
    41            carry = 1;
    42         }
    43         else { // no carry
    44            carry = 0;
    45         }
    46      }
    47
    48      return temp; // return copy of temporary object
    49   }
    50
    51   // addition operator; HugeInteger + int
    52   HugeInteger HugeInteger::operator+(int op2) const {
    53      // convert op2 to a HugeInteger, then invoke
    54      // operator+ for two HugeInteger objects
    55      return *this + HugeInteger(op2);
    56   }
    57
    58   // addition operator;
    59   // HugeInteger + string that represents large integer value
    60   HugeInteger HugeInteger::operator+(const string& op2) const {
    61      // convert op2 to a HugeInteger, then invoke
    62      // operator+ for two HugeInteger objects
    63      return *this + HugeInteger(op2);
    64   }
    65
    66   // overloaded output operator
    67   ostream& operator<<(ostream& output, const HugeInteger& num) {
    68      int i;
    69
    70      // skip leading zeros
    71      for (i = 0; (i < HugeInteger::digits) && (0 == num.integer[i]); ++i) { }
    72
    73      if (i == HugeInteger::digits) {
    74         output << 0;
    75      }
    76      else {
    77         for (; i < HugeInteger::digits; ++i) {
    78            output << num.integer[i];
    79         }
    80      }
    81
    82      return output;
    83   }
    

    Fig. 10.19 HugeInteger test program.

    Alternate View
    
     1   // Fig. 10.19: fig10_19.cpp
     2   // HugeInteger test program.
     3   #include <iostream>
     4   #include "HugeInteger.h"
     5   using namespace std;
     6
     7   int main() {
     8      HugeInteger n1{7654321};
     9      HugeInteger n2{7891234};
    10      HugeInteger n3{"99999999999999999999999999999"};
    11      HugeInteger n4{"1"};
    12      HugeInteger n5;
    13
    14      cout << "n1 is " << n1 << "
    n2 is " << n2
    15         << "
    n3 is " << n3 << "
    n4 is " << n4
    16         << "
    n5 is " << n5 << "
    
    ";
    17
    18      n5 = n1 + n2;
    19      cout << n1 << " + " << n2 << " = " << n5 << "
    
    ";
    20
    21      cout << n3 << " + " << n4 << "
    = " << (n3 + n4) << "
    
    ";
    22
    23      n5 = n1 + 9;
    24      cout << n1 << " + " << 9 << " = " << n5 << "
    
    ";
    25
    26      n5 = n2 + "10000";
    27      cout << n2 << " + " << "10000" << " = " << n5 << endl;
    28   }
    
    
    n1 is 7654321
    n2 is 7891234
    n3 is 99999999999999999999999999999
    n4 is 1
    n5 is 0
    
    7654321 + 7891234 = 15545555
    
    99999999999999999999999999999 + 1
    = 100000000000000000000000000000
    
    7654321 + 9 = 7654330
    
    7891234 + 10000 = 7901234
    
  5. 10.10 (RationalNumber Class) Create a RationalNumber(fractions) class like the one in Exercise 9.6. Provide the following capabilities:

    1. Create a constructor that prevents a 0 denominator in a fraction, reduces or simplifies fractions that are not in reduced form and avoids negative denominators.

    2. Overload the addition, subtraction, multiplication and division operators for this class.

    3. Overload the relational and equality operators for this class.

  6. 10.11 (Polynomial Class) Develop class Polynomial. The internal representation of a Polynomial is an array of terms. Each term contains a coefficient and an exponent—e.g., the term

    2x4

    has the coefficient 2 and the exponent 4. Develop a complete class containing proper constructor and destructor functions as well as set and get functions. The class should also provide the following overloaded operator capabilities:

    1. Overload the addition operator (+) to add two Polynomials.

    2. Overload the subtraction operator (-) to subtract two Polynomials.

    3. Overload the assignment operator to assign one Polynomial to another.

    4. Overload the multiplication operator (*) to multiply two Polynomials.

    5. Overload the addition assignment operator (+=), subtraction assignment operator (-=), and multiplication assignment operator (*=).

  7. 10.12 (DollarAmount Class Enhancement) Enhance class DollarAmount from Exercise 5.32 with overloaded addition (+), subtraction (-), multiplication (*) and division (/) operators.

  8. 10.13 (DollarAmount Class Enhancement) Enhance class DollarAmount from Exercise 10.12 to make the overloaded addition, subtraction and multiplication operators commutative.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset