Chapter 13 Introduction to Classes

13.1 Procedural and Object-Oriented Programming

Concept:
  • Procedural programming centers on the procedures or actions within a program.

  • Object-oriented programming (OOP) revolves around objects, which are created from abstract data types that bundle data and functions.

  • Two primary programming methods exist: procedural programming and object-oriented programming (OOP).

  • In a procedural program, data (stored in variables/structures) and the functions that operate on that data are separate. The main focus is on creating these functions.

  • A key challenge in procedural programming arises when data structures change. This forces modifications to all functions that operate on that data, which can lead to bugs.

  • OOP was developed to address this issue. It centers on creating objects, which are self-contained software entities that combine both data and procedures.

    • Attributes: The data contained within an object.
    • Member Functions: The procedures an object can perform. (Also called methods in other languages).
  • OOP introduces key concepts to solve the problems of procedural programming:

    • Encapsulation: The bundling of data and code into a single object.
    • Data Hiding: An object’s ability to conceal its internal data from outside code. Only the object’s own member functions can directly access its data, protecting it from accidental corruption.
  • The member functions of an object provide a public interface, allowing outside code to interact with the object’s data indirectly and safely.

  • This is analogous to driving a car: the driver uses a simple interface (steering wheel, pedals) without needing to know the complex internal mechanics. The interface protects the car’s engine and makes it easy to use.

Object Reusability

  • OOP promotes object reusability. An object is not a standalone program but a component that can be used by any program needing its services.

  • For example, a programmer can create a specialized 3D graphics object that other developers can then use in their own applications without needing to understand the complex math involved.

Classes and Objects

  • An object is created from a class. A class is a programmer-defined blueprint that specifies the attributes and member functions a type of object will have.

  • A class is not an object itself, but a description of one.

  • An object is an instance of a class. When a program runs, it uses the class to create one or more objects in memory.

  • Each object created from a class is a separate entity with its own set of attributes, as specified by the class blueprint.

  • For example, a procedural rectangle program would have separate variables for width and length and separate functions to manipulate them.

  • In an OOP approach, we would create a Rectangle class that encapsulates both the data (width, length) and the functions (setWidth, getArea, etc.) into a single unit.

Using a Class You Already Know

  • The string class is a familiar example. To use it, you must include the <string> header file.

  • Defining a string object is an example of creating an instance of the string class.

string cityName;
  • You can assign data to the object’s attributes.
cityName = "Charleston";
  • The string class provides member functions to operate on the object’s data. You call these functions using the dot operator (.).

  • The length member function returns the number of characters in the string.

int strSize;
strSize = cityName.length();   
  • The append member function adds text to the end of the existing string.
cityName.append(" South Carolina");

13.2 Introduction to Classes

Concept:
  • In C++, a class is the primary construct for creating objects. It is similar to a structure but with enhanced features.

Writing a Class

  • A class is a programmer-defined data type composed of variables and functions. The general format for a class declaration is:
class  ClassName 
{
   declaration;
};
  • By default, all members of a class are private, meaning they cannot be accessed by code outside the class.
class Rectangle
{
   double width;   
   double length;  
};                  
  • This default privacy enforces data hiding, a core principle of OOP.

Access Specifiers

  • C++ uses the keywords private and public as access specifiers to control how class members can be accessed.

    • private members can only be accessed by member functions of the same class.
    • public members can be accessed by code outside the class.
  • The general format using access specifiers is:

class ClassName 
{
   private:
   public:
};

Public Member Functions

  • To allow controlled access to private member variables, you create public member functions that operate on them.

  • For our Rectangle class, we can declare public functions to set and get the width and length, and to calculate the area.

  • The function declarations, or prototypes, are placed inside the class declaration.

class Rectangle
{
   private:
     double width;
     double length;
   public:
     void setWidth(double);
     void setLength(double);
     double getWidth() const;
     double getLength() const;
     double getArea() const;
};
  • In this structure, the private variables (width, length) are protected. Outside code must use the public functions to interact with the object’s data.

Using const with Member Functions

  • The const keyword appearing after a member function’s parentheses indicates that the function will not modify the object’s data.
double getWidth() const;
  • This is a safety feature. If you accidentally write code inside a const function that changes member data, the compiler will report an error.

  • The const keyword must be used in both the function declaration (prototype) and its definition.

Placement of public and privateMembers

  • There is no strict rule about ordering public and private sections.

  • However, for consistency and readability, most programmers group all members with the same access specification together.

Defining Member Functions

  • The definitions of member functions are typically written outside the class declaration.

  • To associate a function definition with its class, you must use the class name and the scope resolution operator (::).

void Rectangle::setWidth(double w)
{
   width = w;
}
  • The general format for a member function header defined outside the class is:
ReturnType ClassName::functionName(ParameterList)
  • The class name and scope resolution operator are essential; without them, the function would not be recognized as a member of the class.

Accessors and Mutators

  • It’s common practice to make member variables private and provide public functions to access them.

    • An accessor is a member function that gets a value from a member variable but does not change it. These are often called “getter” functions.
    • A mutator is a member function that stores a value in a member variable or changes its value. These are often called “setter” functions.
  • In the Rectangle class:

    • getWidth and getLength are accessors.
    • setWidth and setLength are mutators.

Using const with Accessors

  • Accessor functions, by definition, should not change an object’s data.

  • It is a good programming practice to mark all accessor functions as const to prevent accidental modifications and reduce bugs.

double Rectangle::getWidth() const
{
   return width;
}

The Importance of Data Hiding

  • Data hiding is crucial in large-scale software development.

  • When other programmers use your classes, making data private and accessible only through public member functions ensures your class is used as intended and prevents its data from being corrupted.

13.3 Defining an Instance of a Class

Concept:
  • A class declaration is just a blueprint. Class objects must be defined to be created in memory.

Defining an Instance of a Class

  • Class objects are defined similarly to variables, using the class name as the data type. This process is called instantiation.

  • The general format is:

ClassName objectName;
  • For example, to create an object (an instance) of the Rectangle class named box:
Rectangle box;

Accessing an Object’s Members

  • The dot operator (.) is used to access an object’s public members, such as calling its member functions.

  • To set the width of the box object, you call its setWidth member function:

box.setWidth(12.7);
  • Other examples include:
box.setLength(4.8);      
x = box.getWidth();      
cout << box.getLength(); 
cout << box.getArea();   
  • Inside a member function, the dot operator is not needed to access the member variables of the calling object.

A Class Demonstration Program

  • The following program demonstrates the complete Rectangle class and its usage.

🗊 Program 13-1

 #include <iostream>
 using namespace std;

 class Rectangle
 {
     private:
         double width;
         double length;
     public:
         void setWidth(double);
         void setLength(double);
         double getWidth() const;
         double getLength() const;
         double getArea() const;
 };


 void Rectangle::setWidth(double w)
 {
     width = w;
 }


 void Rectangle::setLength(double len)
 {
     length = len;
 }


 double Rectangle::getWidth() const
 {
     return width;
 }


 double Rectangle::getLength() const
 {
     return length;
 }


 double Rectangle::getArea() const
 {
     return width * length;
 }


 int main()
 {
     Rectangle box;      
     double rectWidth;   
     double rectLength;  

     cout << "This program will calculate the area of a\n";
     cout << "rectangle. What is the width? ";
     cin >> rectWidth;
     cout << "What is the length? ";
     cin >> rectLength;

     box.setWidth(rectWidth);
     box.setLength(rectLength);

     cout << "Here is the rectangle's data:\n";
     cout << "Width: " << box.getWidth() << endl;
     cout << "Length: " << box.getLength() << endl;
     cout << "Area: " << box.getArea() << endl;
     return 0;
 }

💻 Program Output








  • When a Rectangle object like box is defined, its member variables are uninitialized and hold garbage values.

  • An object’s state refers to the data stored in its attributes at any given moment. The program uses mutator functions (setWidth, setLength) to change the state of the box object.

  • You can create multiple instances of the same class. Each object will have its own set of member variables in memory.

🗊 Program 13-2

 #include <iostream>
 using namespace std;

                   Lines 6 through 62 have been left out. 


 int main()
 {
     double number;       
     double totalArea;    
     Rectangle kitchen;   
     Rectangle bedroom;   
     Rectangle den;       

     cout << "What is the kitchen's length? ";
     cin >> number;                             
     kitchen.setLength(number);                 
     cout << "What is the kitchen's width? ";
     cin >> number;                             
     kitchen.setWidth(number);                  

     cout << "What is the bedroom's length? ";
     cin >> number;                             
     bedroom.setLength(number);                 
     cout << "What is the bedroom's width? ";
     cin >> number;                             
     bedroom.setWidth(number);                  

     cout << "What is the den's length? ";
     cin >> number;                             
     den.setLength(number);                     
     cout << "What is the den's width? ";
     cin >> number;                             
     den.setWidth(number);                      

     totalArea = kitchen.getArea() + bedroom.getArea() +
                den.getArea();

     cout << "The total area of the three rooms is "
          << totalArea << endl;

     return 0;
 }

💻 Program Output








  • In Program 13-2, kitchen, bedroom, and den are three distinct Rectangle objects, each with its own length and width.

Avoiding Stale Data

  • Data is considered stale if it depends on other data and is not updated when that other data changes.

  • In the Rectangle class, the area is calculated by the getArea function rather than being stored in a member variable.

  • If area were a member variable, it would become stale every time width or length changed.

  • As a design principle, avoid storing calculated data in member variables. Instead, provide a member function to perform the calculation and return the result.

Pointers to Objects

  • You can define pointers that hold the memory address of a class object.
Rectangle myRectangle;
Rectangle *rectPtr = nullptr;
rectPtr = &myRectangle;
  • To access an object’s members through a pointer, use the -> operator.
rectPtr->setWidth(12.5);
rectPtr->setLength(4.8);
  • Pointers are commonly used to dynamically allocate objects using the new operator.

  • Remember to use the delete operator to free the memory allocated for the object when it is no longer needed.

🗊 Program 13-3

 #include <iostream>
 using namespace std;

          Lines 6 through 62 have been left out.


 int main()
 {
     double number;                 
     double totalArea;              
     Rectangle *kitchen = nullptr;  
     Rectangle *bedroom = nullptr;  
     Rectangle *den = nullptr;      

     kitchen = new Rectangle;
     bedroom = new Rectangle;
     den = new Rectangle;

     cout << "What is the kitchen's length? ";
     cin >> number;                          
     kitchen->setLength(number);             
     cout << "What is the kitchen's width? ";
     cin >> number;                          
     kitchen->setWidth(number);              

     cout << "What is the bedroom's length? ";
     cin >> number;                          
     bedroom->setLength(number);             
     cout << "What is the bedroom's width? ";
     cin >> number;                          
     bedroom->setWidth(number);              

     cout << "What is the den's length? ";
     cin >> number;                          
     den->setLength(number);                 
     cout << "What is the den's width? ";
     cin >> number;                          
     den->setWidth(number);                  

     totalArea = kitchen->getArea() + bedroom->getArea() +
                den->getArea();

     cout << "The total area of the three rooms is "
          << totalArea << endl;

     delete kitchen;
     delete bedroom;
     delete den;
     kitchen = nullptr;    
     bedroom = nullptr;    
     den = nullptr;        

     return 0;
 }

Using Smart Pointers to Allocate Objects

  • C++ 11 introduced smart pointers, like unique_ptr, which automatically manage dynamically allocated memory.

  • This helps prevent memory leaks because the memory is automatically deleted when it’s no longer in use.

  • To use unique_ptr, you must include the <memory> header file.

  • The syntax to define a unique_ptr for a Rectangle object is:

#include <memory>
unique_ptr<Rectangle> rectanglePtr(new Rectangle);
  • Once defined, a unique_ptr can be used like a regular pointer with the -> operator.

  • No delete statement is needed, as the smart pointer handles memory deallocation automatically when it goes out of scope.

🗊 Program 13-4

 #include <iostream>
 #include <memory>
 using namespace std;

        Lines 8 through 64 have been left out. 


 int main()
 {
     double number;           
     double totalArea;        

     unique_ptr<Rectangle> kitchen(new Rectangle);
     unique_ptr<Rectangle> bedroom(new Rectangle);
     unique_ptr<Rectangle> den(new Rectangle);

     cout << "What is the kitchen's length? ";
     cin >> number;                           
     kitchen->setLength(number);              
     cout << "What is the kitchen's width? ";
     cin >> number;                           
     kitchen->setWidth(number);               

     cout << "What is the bedroom's length? ";
     cin >> number;                           
     bedroom->setLength(number);              
     cout << "What is the bedroom's width? ";
     cin >> number;                           
     bedroom->setWidth(number);               

     cout << "What is the den's length? ";
     cin >> number;                           
     den->setLength(number);                  
     cout << "What is the den's width? ";
     cin >> number;                           
     den->setWidth(number);                   

     totalArea = kitchen->getArea() + bedroom->getArea() +
                den->getArea();

     cout << "The total area of the three rooms is "
          << totalArea << endl;

     return 0;
 }

Checkpoint

  1. 13.1 True or False: You must declare all private members of a class before the public members.

  2. 13.2 Assume RetailItem is the name of a class, and the class has a void member function named setPrice, which accepts a double argument. Which of the following shows the correct use of the scope resolution operator in the member function definition?

    1. RetailItem::void setPrice(double p)

    2. void RetailItem::setPrice(double p)

  3. 13.3 An object’s private member variables are accessed from outside the object by which of the following?

    1. public member functions

    2. any function

    3. the dot operator

    4. the scope resolution operator

  4. 13.4 Assume RetailItem is the name of a class, and the class has a void member function named setPrice, which accepts a double argument. If soap is an instance of the RetailItem class, which of the following statements properly uses the soap object to call the setPrice member function?

    1. RetailItem::setPrice(1.49);

    2. soap::setPrice(1.49);

    3. soap.setPrice(1.49);

    4. soap:setPrice(1.49);

  5. 13.5 Complete the following code skeleton to declare a class named Date. The class should contain variables and functions to store and retrieve a date in the form 4/2/2018.

    class Date
    {
         private:
         public:
    }

13.4 Why Have Private Members?

Concept:
  • An object should protect its important data by making it private and providing a public interface for access.
  • Making member variables private protects critical data from being accidentally modified or used improperly.

  • When a member is private, the only way to access it from outside the class is through a public member function.

  • These public functions act as a controlled interface to the object’s data.

  • A major benefit of this approach is that mutator functions can perform data validation before storing a value in a private member variable.

  • For example, the setWidth function can be modified to ensure that only non-negative values are assigned to the width member.

void Rectangle::setWidth(double w)
{
   if (w >= 0)
      width = w;
   else
   {
      cout << "Invalid width\n";
      exit(EXIT_FAILURE);
   }
}
  • This ensures that only acceptable data is stored in the object’s attributes, maintaining the object’s integrity.

13.5 Focus on Software Engineering: Separating Class Specification from Implementation

Concept:
  • It is standard practice to store class declarations in header (.h) files and member function definitions in implementation (.cpp) files.
  • A more conventional way to structure C++ programs is to separate class components into different files:

    • Class Specification File: A header file (e.g., Rectangle.h) that contains the class declaration.
    • Class Implementation File: A .cpp file (e.g., Rectangle.cpp) that contains the definitions of the class’s member functions.
    • Main Program File: A .cpp file (e.g., main.cpp) that uses the class to solve a problem.
  • Any program that uses the class must #include the class’s header file. The implementation .cpp file is then compiled and linked with the main program to create an executable.

Contents of Rectangle.h (Version 1)
 #ifndef RECTANGLE_H
 #define RECTANGLE_H


 class Rectangle
 {
     private:
         double width;
         double length;
     public:
         void setWidth(double);
         void setLength(double);
         double getWidth() const;
         double getLength() const;
         double getArea() const;
 };

 #endif
  • The #ifndef RECTANGLE_H and #define RECTANGLE_H preprocessor directives form an include guard.
    • An include guard prevents the header file from being included more than once in the same program, which would cause compilation errors.
    • ifndef stands for “if not defined.” If the constant RECTANGLE_H is not defined, the code up to #endif is processed, and RECTANGLE_H is defined.
    • On subsequent inclusion attempts, the constant will already be defined, and the preprocessor will skip the file’s contents.
Contents of Rectangle.cpp (Version 1)
 #include "Rectangle.h"   
 #include <iostream>      
 #include <cstdlib>       
 using namespace std;


 void Rectangle::setWidth(double w)
 {
     if (w >= 0)
         width = w;
     else
     {
         cout << "Invalid width\n";
         exit(EXIT_FAILURE);
     }
 }


 void Rectangle::setLength(double len)
 {
     if (len >= 0)
         length = len;
     else
     {
         cout << "Invalid length\n";
         exit(EXIT_FAILURE);
     }
 }


 double Rectangle::getWidth() const
 {
     return width;
 }


 double Rectangle::getLength() const
 {
     return length;
 }


 double Rectangle::getArea() const
 {
     return width * length;
 }
  • The implementation file must #include its corresponding specification file ("Rectangle.h").

    • Use double quotes (" ") for header files you have written, which are typically in the current project directory.
    • Use angle brackets (< >) for standard C++ library files, which are in the compiler’s include directory.
  • The following program uses the separated Rectangle class.

🗊 Program 13-5

 #include <iostream>
 #include "Rectangle.h"  
 using namespace std;

 int main()
 {
     Rectangle box;      
     double rectWidth;   
     double rectLength;  

     cout << "This program will calculate the area of a\n";
     cout << "rectangle. What is the width? ";
     cin >> rectWidth;
     cout << "What is the length? ";
     cin >> rectLength;

     box.setWidth(rectWidth);
     box.setLength(rectLength);

     cout << "Here is the rectangle's data:\n";
     cout << "Width: " << box.getWidth() << endl;
     cout << "Length: " << box.getLength() << endl;
     cout << "Area: " << box.getArea() << endl;
     return 0;
 }
  • To create an executable file from this multi-file project, the following steps are required:

    1. Compile the implementation file (Rectangle.cpp) into an object file (Rectangle.obj).
    2. Compile the main program file (Pr13–5.cpp) into its own object file (Pr13–5.obj).
    3. Link the object files (Rectangle.obj and Pr13–5.obj) together to create a final executable file (Pr13–5.exe).
  • Most modern Integrated Development Environments (IDEs) automate this compilation and linking process when you build a project.

  • This separation provides flexibility:

    • You can share your class with other programmers by giving them only the specification file and the compiled object file, keeping your source code private.
    • If you need to modify a member function, you only need to change and recompile the implementation file. Programs using the class only need to be re-linked, not completely recompiled.

13.6 Inline Member Functions

Concept:
  • When a member function’s body is defined inside a class declaration, it becomes an inline function.
  • For member functions with small bodies, it’s often more convenient to place the full definition inside the class declaration instead of just a prototype.

  • This approach is demonstrated below with the getWidth, getLength, and getArea functions in the Rectangle class.

Contents of Rectangle.h (Version 2)
 #ifndef RECTANGLE_H
 #define RECTANGLE_H

 class Rectangle
 {
     private:
        double width;
        double length;
     public:
        void setWidth(double);
        void setLength(double);

        double getWidth() const
            { return width; }

        double getLength() const
            { return length; }

        double getArea() const
            { return width * length; }
 };
 #endif
  • When a function is defined this way, it’s called an inline function.

  • The scope resolution operator (::) is not needed because the definition is already within the class’s scope.

  • Functions can be mixed; some can be inline while others are defined externally in the implementation file.

Contents of Rectangle.cpp (Version 2)
 #include "Rectangle.h"    
 #include <iostream>       
 #include <cstdlib>        
 using namespace std;


 void Rectangle::setWidth(double w)
 {
     if (w >= 0)
        width = w;
     else
     {
        cout << "Invalid width\n";
        exit(EXIT_FAILURE);
     }
 }


 void Rectangle::setLength(double len)
 {
     if (len >= 0)
        length = len;
     else
     {
        cout << "Invalid length\n";
        exit(EXIT_FAILURE);
     }
 }

Inline Functions and Performance

  • A conventional function call has processing overhead, such as storing arguments and a return address on the stack.

  • While this overhead is small, it can become significant if a function is called many times, such as inside a loop.

  • Inline functions are handled differently by the compiler. Through a process called inline expansion, the compiler replaces the function call with the actual code of the function.

    • Benefit: This eliminates the function call overhead, which can improve performance.
    • Drawback: This can increase the size of the final executable program because the function’s code is duplicated at each call site.

Checkpoint

  1. 13.6 Why would you declare a class’s member variables private?

  2. 13.7 When a class’s member variables are declared private, how does code outside the class store values in, or retrieve values from, the member variables?

  3. 13.8 What is a class specification file? What is a class implementation file?

  4. 13.9 What is the purpose of an include guard?

  5. 13.10 Assume the following class components exist in a program:

    BasePay class declaration

    BasePay member function definitions

    Overtime class declaration

    Overtime member function definitions

    In what files would you store each of these components?

  6. 13.11 What is an inline member function?

13.7 Constructors

Concept:
  • A constructor is a special member function that is automatically called when a class object is created (instantiated).
  • A constructor is a member function that shares the same name as its class.

  • It is automatically executed when an object of the class is created and is typically used for initialization.

  • Key characteristics of a constructor:

    • It has the same name as the class.
    • It has no return type, not even void.
    • It cannot be called explicitly and cannot return a value.
  • The following program demonstrates a simple constructor.

🗊 Program 13-6

 #include <iostream>
 using namespace std;


 class Demo
 {
 public:
     Demo();    
 };

 Demo::Demo()
 {
     cout << "Welcome to the constructor!\n";
 }


 int main()
 {
     Demo demoObject; 

     cout << "This program demonstrates an object\n";
     cout << "with a constructor.\n";
     return 0;
 }

💻 Program Output




  • The constructor is called automatically at the point where the object is defined.

  • The primary purpose of a constructor is to initialize an object’s attributes to valid starting values, preventing them from holding garbage data.

  • It’s good practice to provide a constructor for every class you create.

  • The Rectangle class below is improved with a constructor that initializes width and length to 0.0.

Contents of Rectangle.h (Version 3)
 #ifndef RECTANGLE_H
 #define RECTANGLE_H

 class Rectangle
 {
    private:
       double width;
       double length;
    public:
       Rectangle();               
       void setWidth(double);
       void setLength(double);

       double getWidth() const
          { return width; }

       double getLength() const
          { return length; }

       double getArea() const
          { return width * length; }
 };
 #endif
Contents of Rectangle.cpp (Version 3)
 #include "Rectangle.h"   
 #include <iostream>   
 #include <cstdlib>    
 using namespace std;


 Rectangle::Rectangle()
 {
     width = 0.0;
     length = 0.0;
 }


 void Rectangle::setWidth(double w)
 {
     if (w >= 0)
         width = w;
     else
     {
         cout << "Invalid width\n";
         exit(EXIT_FAILURE);
     }
 }


 void Rectangle::setLength(double len)
 {
     if (len >= 0)
         length = len;
     else
     {
         cout << "Invalid length\n";
         exit(EXIT_FAILURE);
     }
 }

🗊 Program 13-7

 #include <iostream>
 #include "Rectangle.h" 
 using namespace std;

 int main()
 {
     Rectangle box;    

     cout << "Here is the rectangle's data:\n";
     cout << "Width: " << box.getWidth() << endl;
     cout << "Length: " << box.getLength() << endl;
     cout << "Area: " << box.getArea() << endl;
     return 0;
 }

💻 Program Output





Using Member Initialization Lists

  • As an alternative to assignment statements inside the constructor’s body, you can use a member initialization list.

  • This technique initializes members in the function header, following a colon (:).

  • Many programmers prefer this method as it can sometimes be more efficient.

Rectangle::Rectangle() :
width(0.0), length(0.0)
{
}
  • Initializations in the list occur before any statements in the constructor’s body are executed.

In-Place Member Initialization

  • C++ 11 introduced in-place initialization, which allows you to initialize a member variable directly in its declaration statement, just like a regular variable.
class Rectangle
{
private:
   double width = 0.0;
   double length = 0.0;
public:
};

The Default Constructor

  • A default constructor is a constructor that takes no arguments.

  • If you do not provide any constructor for a class, C++ automatically generates a default constructor that does nothing.

Default Constructors and Dynamically Allocated Objects

  • When an object is dynamically allocated with the new operator, its default constructor is automatically called.
Rectangle *rectPtr = nullptr;
rectPtr = new Rectangle; 

13.8 Passing Arguments to Constructors

Concept:
  • Constructors can have parameters, allowing you to pass arguments to them when an object is created.
  • A constructor can be designed to accept arguments, which allows you to provide initial values for member variables at the time an object is defined.

  • Arguments are passed in parentheses following the object’s name in the definition statement.

Rectangle box(10.0, 12.0); 
  • The following version of the Rectangle class includes a constructor that accepts arguments for width and length.
Contents of Rectangle.h (Version 4)
 #ifndef RECTANGLE_H
 #define RECTANGLE_H

 class Rectangle
 {
     private:
         double width;
         double length;
     public:
         Rectangle(double, double);   
         void setWidth(double);
         void setLength(double);

         double getWidth() const
             { return width; }

         double getLength() const
             { return length; }

         double getArea() const
             { return width * length; }
 };
 #endif
Contents of Rectangle.cpp (Version 4)
 #include "Rectangle.h"   
 #include <iostream>      
 #include <cstdlib>       
 using namespace std;


 Rectangle::Rectangle(double w, double len)
 {
     width = w;
     length = len;
 }


 void Rectangle::setWidth(double w)
 {
     if (w >= 0)
         width = w;
     else
     {
         cout << "Invalid width\n";
         exit(EXIT_FAILURE);
     }
 }


 void Rectangle::setLength(double len)
 {
     if (len >= 0)
         length = len;
     else
     {
         cout << "Invalid length\n";
         exit(EXIT_FAILURE);
     }
 }

🗊 Program 13-8

 #include <iostream>
 #include <iomanip>
 #include "Rectangle.h"
 using namespace std;

 int main()
 {
     double houseWidth,   
            houseLength;  

     cout << "In feet, how wide is your house? ";
     cin >> houseWidth;

     cout << "In feet, how long is your house? ";
     cin >> houseLength;

     Rectangle house(houseWidth, houseLength);

     cout << setprecision(2) << fixed;
     cout << "The house is " << house.getWidth()
         << " feet wide.\n";
     cout << "The house is " << house.getLength()
         << " feet long.\n";
     cout << "The house is " << house.getArea()
         << " square feet in area.\n";
     return 0;
 }

💻 Program Output






  • The following Sale class provides another example of a constructor that accepts arguments.
Contents of Sale.h (Version 1)
 #ifndef SALE_H
 #define SALE_H

 class Sale
 {
 private:
    double itemCost;    
    double taxRate;     
 public:
    Sale(double cost, double rate)
       { itemCost = cost;
         taxRate = rate; }

    double getItemCost() const
       { return itemCost; }

    double getTaxRate() const
       { return taxRate; }

    double getTax() const
       { return (itemCost * taxRate); }

    double getTotal() const
       { return (itemCost + getTax()); }
 };
 #endif

🗊 Program 13-9

 #include <iostream>
 #include <iomanip>
 #include "Sale.h"
 using namespace std;

 int main()
 {
    const double TAX_RATE = 0.06; 
    double cost;                  

    cout << "Enter the cost of the item: ";
    cin >> cost;

    Sale itemSale(cost, TAX_RATE);

    cout << fixed << showpoint << setprecision(2);

    cout << "The amount of sales tax is $"
         << itemSale.getTax() << endl;
    cout << "The total of the sale is $";
    cout << itemSale.getTotal() << endl;
    return 0;
 }

💻 Program Output




Using Default Arguments with Constructors

  • Like regular functions, constructors can have default arguments.

  • If an argument is omitted when the object is created, the default value specified in the parameter list is used automatically.

Contents of Sale.h (Version 2)
 #ifndef SALE_H
 #define SALE_H

 class Sale
 {
 private:
    double itemCost;   
    double taxRate;    
 public:
    Sale(double cost, double rate = 0.05)
       { itemCost = cost;
         taxRate = rate; }

    double getItemCost() const
       { return itemCost; }

    double getTaxRate() const
       { return taxRate; }

    double getTax() const
       { return (itemCost * taxRate); }

    double getTotal() const
       { return (itemCost + getTax()); }
 };
 #endif

🗊 Program 13-10

 #include <iostream>
 #include <iomanip>
 #include "Sale.h"
 using namespace std;

 int main()
 {
     double cost;  

     cout << "Enter the cost of the item: ";
     cin >> cost;

     Sale itemSale(cost);

     cout << fixed << showpoint << setprecision(2);

     cout << "The amount of sales tax is $"
          << itemSale.getTax() << endl;
     cout << "The total of the sale is $";
     cout << itemSale.getTotal() << endl;
     return 0;
 }

💻 Program Output




More about the Default Constructor

  • If a constructor has default arguments for all of its parameters, it also serves as the default constructor because it can be called with no arguments.
Sale(double cost = 0.0, double rate = 0.05) 
   { itemCost = cost;
     taxRate = rate; }

Classes with No Default Constructor

  • If all of a class’s constructors require arguments, then the class has no default constructor.

  • In this case, you must provide the required arguments whenever you create an object of that class, or a compiler error will occur.

13.9 Destructors

Concept:
  • A destructor is a member function that is automatically called when an object is destroyed.
  • A destructor is a member function that has the same name as the class, preceded by a tilde (~). For example, ~Rectangle.

  • Destructors are automatically called when an object goes out of scope or is explicitly deleted.

  • They are used to perform cleanup tasks, such as freeing memory that was dynamically allocated by the object.

  • Key characteristics of a destructor:

    • It has the same name as the class, prefixed with ~.
    • It has no return type.
    • It cannot accept arguments and therefore has no parameter list.

🗊 Program 13-11

 #include <iostream>
 using namespace std;

 class Demo
 {
 public:
     Demo();     
     ~Demo();    
 };

 Demo::Demo()
 {
     cout << "Welcome to the constructor!\n";
 }

 Demo::~Demo()
 {
     cout << "The destructor is now running.\n";
 }


 int main()
 {
     Demo demoObject;  

     cout << "This program demonstrates an object\n";
     cout << "with a constructor and destructor.\n";
     return 0;
 }

💻 Program Output





  • The following ContactInfo class provides a practical example where the constructor allocates memory and the destructor frees it.
Contents of ContactInfo.h (Version 1)
 #ifndef CONTACTINFO_H
 #define CONTACTINFO_H
 #include <cstring>   

 class ContactInfo
 {
 private:
     char *name;  
     char *phone; 
 public:
     ContactInfo(char *n, char *p)
     { 
         name = new char[strlen(n) + 1];
         phone = new char[strlen(p) + 1];

         strcpy(name, n);
         strcpy(phone, p); }

     ~ContactInfo()
     { delete [] name;
       delete [] phone; }

     const char *getName() const
     { return name; }

    const char *getPhoneNumber() const
    { return phone; }
 };
 #endif

🗊 Program 13-12

 #include <iostream>
 #include "ContactInfo.h"
 using namespace std;

 int main()
 {
     ContactInfo entry("Kristen Lee", "555-2021");

     cout << "Name: " << entry.getName() << endl;
     cout << "Phone Number: " << entry.getPhoneNumber() << endl;
     return 0;
 }

💻 Program Output



Destructors and Dynamically Allocated Class Objects

  • When an object that was dynamically allocated with new is destroyed using the delete operator, its destructor is automatically called.
ContactInfo *objectPtr = new ContactInfo("Kristen Lee", "555-2021");
delete objectPtr; 
  • If you use a smart pointer like unique_ptr, delete is not necessary; the object is destroyed and the destructor is called automatically when the smart pointer goes out of scope.

Checkpoint

  1. 13.12 Briefly describe the purpose of a constructor.

  2. 13.13 Briefly describe the purpose of a destructor.

  3. 13.14 A member function that is never declared with a return data type, but that may have arguments is which of the following?

    1. The constructor

    2. The destructor

    3. Both the constructor and the destructor

    4. Neither the constructor nor the destructor

  4. 13.15 A member function that is never declared with a return data type and can never have arguments is which of the following?

    1. The constructor

    2. The destructor

    3. Both the constructor and the destructor

    4. Neither the constructor nor the destructor

  5. 13.16 Destructor function names always start with ____________________.

    1. A number

    2. Tilde character (~)

    3. A data type name

    4. None of the above

  6. 13.17 A constructor that requires no arguments is called ____________________.

    1. A default constructor

    2. An overloaded constructor

    3. A null constructor

    4. None of the above

  7. 13.18 True or False: Constructors are never declared with a return data type.

  8. 13.19 True or False: Destructors are never declared with a return type.

  9. 13.20 True or False: Destructors may take any number of arguments.

13.10 Overloading Constructors

Concept:
  • A class can have multiple constructors, a feature known as overloading.
  • Like regular functions, constructors can be overloaded. This means a class can have more than one constructor, as long as each has a different parameter list.

  • Overloading allows you to create objects in various ways. For example, you might have one constructor to create a default object and another to create an object with specific initial values.

  • The InventoryItem class below has three overloaded constructors.

Contents of InventoryItem.h
 #ifndef INVENTORYITEM_H
 #define INVENTORYITEM_H
 #include <string>
 using namespace std;

 class InventoryItem
 {
 private:
    string description;   
    double cost;          
    int units;            
 public:
    InventoryItem()
       { 
         description = "";
         cost = 0.0;
         units = 0; }

    InventoryItem(string desc)
       { 
         description = desc;

         cost = 0.0;
         units = 0; }

    InventoryItem(string desc, double c, int u)
       { 
         description = desc;
         cost = c;
         units = u; }

    void setDescription(string d)
       { description = d; }

    void setCost(double c)
       { cost = c; }

    void setUnits(int u)
       { units = u; }

    string getDescription() const
       { return description; }

    double getCost() const
       { return cost; }

    int getUnits() const
       { return units; }
 };
 #endif

🗊 Program 13-13

 #include <iostream>
 #include <iomanip>
 #include "InventoryItem.h"

 int main()
 {
    InventoryItem item1;
    item1.setDescription("Hammer");   
    item1.setCost(6.95);              
    item1.setUnits(12);               

    InventoryItem item2("Pliers");

    InventoryItem item3("Wrench", 8.75, 20);

    cout << "The following items are in inventory:\n";
    cout << setprecision(2) << fixed << showpoint;

    cout << "Description: " << item1.getDescription() << endl;
    cout << "Cost: $" << item1.getCost() << endl;
    cout << "Units on Hand: " << item1.getUnits() << endl << endl;

    cout << "Description: " << item2.getDescription() << endl;
    cout << "Cost: $" << item2.getCost() << endl;
    cout << "Units on Hand: " << item2.getUnits() << endl << endl;

    cout << "Description: " << item3.getDescription() << endl;
    cout << "Cost: $" << item3.getCost() << endl;
    cout << "Units on Hand: " << item3.getUnits() << endl;
    return 0;
 }

💻 Program Output











Constructor Delegation

  • In C++ 11 and later, one constructor can call another constructor in the same class. This is known as constructor delegation.

  • This feature is useful for reducing redundant code when multiple constructors share common initialization logic.

  • The default constructor for the Contact class below delegates its work to the parameterized constructor by calling it with empty strings.

class Contact
{
private:
   string name;
   string email;
   string phone;
public:
   Contact() : Contact("", "", "")
   { }
   Contact(string n, string e, string p)
   { name = n;
     email = e;
     phone = p;
   }
};

Only One Default Constructor and One Destructor

  • A class may have only one default constructor. This is because the compiler needs to know which constructor to call when an object is defined without any arguments.

  • Similarly, a class may have only one destructor. Since destructors do not take arguments, the compiler would have no way to distinguish between them if more than one existed.

Other Overloaded Member Functions

  • Other member functions, not just constructors, can also be overloaded.

  • This allows you to provide multiple ways to perform the same operation. For instance, a setCost function could be overloaded to accept a double or a string.

void  setCost(double c)
   {  cost = c; }
void  setCost(string c)
   {  cost = stod(c); }

13.11 Private Member Functions

Concept:
  • A private member function can only be called from another member function of the same class.
  • Sometimes, a class requires helper functions for its own internal operations that should not be accessible to code outside the class.

  • Such functions should be declared as private.

  • This prevents them from being called at the wrong time or in the wrong context, which helps maintain the integrity of the object’s state.

  • In the example below, the ContactInfo class uses the private functions initName and initPhone to modularize the logic within its constructor. These functions are private because they should only be called by the constructor.

Contents of ContactInfo.h (Version 2)
 #ifndef CONTACTINFO_H
 #define CONTACTINFO_H
 #include <cstring>   

 class ContactInfo
 {
 private:
    char *name;   
    char *phone;  

    void initName(char *n)
    { name = new char[strlen(n) + 1];
      strcpy(name, n); }

    void initPhone(char *p)
    { phone = new char[strlen(p) + 1];
      strcpy(phone, p); }
 public:
    ContactInfo(char *n, char *p)
    { 
      initName(n);

      initPhone(n); }

    ~ContactInfo()
    { delete [] name;
      delete [] phone; }

    const char *getName() const
    { return name; }

    const char *getPhoneNumber() const
    { return phone; }
 };
 #endif

13.12 Arrays of Objects

Concept:
  • You can define and use arrays whose elements are class objects.
  • Just like with any other data type, you can create arrays of class objects.

  • To define an array of objects, use the same syntax as for other array types. The default constructor will be called for each object in the array.

const int ARRAY_SIZE = 40;
InventoryItem inventory[ARRAY_SIZE];
  • To call a constructor that requires arguments for objects in an array, you must provide an initializer list.

  • For a constructor with one argument, the list can be simple:

InventoryItem inventory[] = {"Hammer", "Wrench", "Pliers"};
  • For a constructor with multiple arguments, the initializer for each element must be in the form of a function call:
InventoryItem inventory[] = { InventoryItem("Hammer", 6.95, 12),
                              InventoryItem("Wrench", 8.75, 20),
                              InventoryItem("Pliers", 3.75, 10) };
  • It is not necessary to call the same constructor for every element in the array. You can mix and match initializers.
InventoryItem inventory[] = { "Hammer",
                              InventoryItem("Wrench", 8.75, 20),
                              "Pliers" };
  • If you provide fewer initializers than the array size, the default constructor will be called for the remaining elements.

  • Key rules for using initializer lists with object arrays:

    • If the class has no default constructor, you must provide an initializer for every object in the array.
    • If the initializer list is shorter than the array, the default constructor is used for the rest of the objects.
    • For multi-argument constructors, use the function-call syntax in the initializer list.

Accessing Members of Objects in an Array

  • To access the members of an object in an array, use the subscript operator ([]) to select the object, followed by the dot operator (.) to access the member.
inventory[2].setUnits(30);
  • The following program demonstrates creating and using an array of InventoryItem objects.

🗊 Program 13-14

 #include <iostream>
 #include <iomanip>
 #include "InventoryItem.h"
 using namespace std;

 int main()
 {
    const int NUM_ITEMS = 5;
    InventoryItem inventory[NUM_ITEMS] = {
                   InventoryItem("Hammer", 6.95, 12),
                   InventoryItem("Wrench", 8.75, 20),
                   InventoryItem("Pliers", 3.75, 10),
                   InventoryItem("Ratchet", 7.95, 14),
                   InventoryItem("Screwdriver", 2.50, 22) };

    cout << setw(14) <<"Inventory Item"
         << setw(8) << "Cost" << setw(8)
         << setw(16) << "Units on Hand\n";
    cout << "-------------------------------------\n";

    for (int i = 0; i < NUM_ITEMS; i++)
    {
       cout << setw(14) << inventory[i].getDescription();
       cout << setw(8) << inventory[i].getCost();
       cout << setw(7) << inventory[i].getUnits() << endl;
    }

    return 0;
 }

💻 Program Output








Checkpoint

  1. 13.21 What will the following program display on the screen?

    #include <iostream>
    using namespace std;
    class Tank
    
    {
    private:
       int gallons;
    public:
       Tank()
          { gallons = 50; }
       Tank(int gal)
          { gallons = gal; }
       int getGallons()
          { return gallons; }
    };
    int main()
    {
       Tank storage[3] = { 10, 20 };
       for (int index = 0; index < 3; index++)
          cout << storage[index].getGallons() << endl;
       return 0;
    }
  2. 13.22 What will the following program display on the screen?

    #include <iostream>
    using namespace std;
    
    class Package
    {
    private:
       int value;
    public:
       Package()
          { value = 7; cout << value << endl; }
       Package(int v)
          { value = v; cout << value << endl; }
       ~Package()
          { cout << value << endl; }
    };
    int main()
    {
       Package obj1(4);
       Package obj2;
       Package obj3(2);
       return 0;
    }
  3. 13.23 In your answer for Checkpoint 13.22, indicate for each line of output whether the line is displayed by constructor https://www.google.com/search?q=%231, constructor https://www.google.com/search?q=%232, or the destructor.

  4. 13.24 Why would a member function be declared private?

  5. 13.25 Define an array of three InventoryItem objects.

  6. 13.26 Complete the following program so it defines an array of Yard objects. The program should use a loop to ask the user for the length and width of each Yard.

    #include <iostream>
    using namespace std;
    class Yard
    {
    private:
       int length, width;
    public:
       Yard()
          { length = 0; width = 0; }
       setLength(int len)
          { length = len; }
       setWidth(int w)
          { width = w; }
    };
    int main()
    {
    }

13.13 Focus on Problem Solving and Program Design: An OOP Case Study

  • This case study involves developing a class to model a bank account.

  • The class should be able to:

    • Store the account balance and number of transactions.
    • Handle deposits and withdrawals.
    • Calculate and add interest.
    • Report the balance, transaction count, and interest earned.

Private Member Variables

Table 13-4 lists the private member variables needed by the class.

Table 13-4 Private Member Variables
Variable Description
balance A double that holds the current account balance.
interestRate A double that holds the interest rate for the period.
interest A double that holds the interest earned for the current period.
transactions An integer that holds the current number of transactions.

Public Member Functions

Table 13-5 lists the public member functions needed by the class.

Table 13-5 Public Member Functions
Function Description
Constructor Takes arguments to be initially stored in the balance and interestRate members. The default value for the balance is zero, and the default value for the interest rate is 0.045.
setInterestRate Takes a double argument, which is stored in the interestRate member.
makeDeposit Takes a double argument, which is the amount of the deposit. This argument is added to balance.
withdraw Takes a double argument, which is the amount of the withdrawal. This value is subtracted from the balance, unless the withdrawal amount is greater than the balance. If this happens, the function reports an error.
calcInterest Takes no arguments. This function calculates the amount of interest for the current period, stores this value in the interest member, then adds it to the balance member.
getInterestRate Returns the current interest rate (stored in the interestRate member).
getBalance Returns the current balance (stored in the balance member).
getInterest Returns the interest earned for the current period (stored in the interest member).
getTransactions Returns the number of transactions for the current period (stored in the transactions member).

The Class Declaration

  • The following code shows the declaration for the Account class.
Contents of Account.h
 #ifndef ACCOUNT_H
 #define ACCOUNT_H

 class Account
 {
 private:
    double balance;          
    double interestRate;     
    double interest;         
    int transactions;        
 public:
    Account(double iRate = 0.045, double bal = 0)
       { balance = bal;
         interestRate = iRate;
         interest = 0;
         transactions = 0; }

    void setInterestRate(double iRate)
       { interestRate = iRate; }

    void makeDeposit(double amount)
       { balance += amount; transactions++; }

    void withdraw(double amount); 

    void calcInterest()
        { interest = balance * interestRate; balance += interest; }

    double getInterestRate() const
       { return interestRate; }

    double getBalance() const
       { return balance; }

    double getInterest() const
       { return interest; }

    int getTransactions() const
       { return transactions; }
 };
 #endif

The withdraw Member Function

  • The withdraw function is defined externally. It checks for sufficient funds before processing the withdrawal and returns true or false to indicate success.
Contents of Account.cpp
 #include "Account.h"

 bool Account::withdraw(double amount)
 {
    if (balance < amount)
       return false; 
    else
    {
       balance -= amount;
       transactions++;
       return true;
    }
 }

The Class’s Interface

  • The member variables are private to protect the integrity of the account data.

  • If they were public, errors could occur, such as:

    • A withdrawal for more than the current balance.
    • A deposit or withdrawal that doesn’t update the transaction count.
    • Incorrect interest calculations.
  • The public member functions provide a safe and controlled interface for manipulating the account.

Implementing the Class

  • The following program provides a menu-driven interface to test and use the Account class.

🗊 Program 13-15

 #include <iostream>
 #include <cctype>
 #include <iomanip>
 #include "Account.h"
 using namespace std;

 void displayMenu();
 void makeDeposit(Account &);
 void withdraw(Account &);

 int main()
 {
     Account savings;  
     char choice;      

     cout << fixed << showpoint << setprecision(2);

     do
     {
         displayMenu();
         cin >> choice;
         while (toupper(choice) < 'A' || toupper(choice) > 'G')
         {
             cout << "Please make a choice in the range "
                 << "of A through G:";
             cin >> choice;
         }

         switch(choice)
         {
         case 'a':
         case 'A': cout << "The current balance is $";
                  cout << savings.getBalance() << endl;
                   break;
         case 'b':
         case 'B': cout << "There have been ";
                   cout << savings.getTransactions()
                       << " transactions.\n";
                   break;
         case 'c':
         case 'C': cout << "Interest earned for this period: $";
                   cout << savings.getInterest() << endl;
                   break;
         case 'd':
         case 'D': makeDeposit(savings);
                   break;
         case 'e':
         case 'E': withdraw(savings);
                   break;
         case 'f':
         case 'F': savings.calcInterest();
                   cout << "Interest added.\n";
         }
     } while (toupper(choice) != 'G');

     return 0;
 }


 void displayMenu()
 {
     cout << "\n               MENU\n";
     cout << "-----------------------------------------\n";
     cout << "A) Display the account balance\n";
     cout << "B) Display the number of transactions\n";
     cout << "C) Display interest earned for this period\n";
     cout << "D) Make a deposit\n";
     cout << "E) Make a withdrawal\n";
     cout << "F) Add interest for this period\n";
     cout << "G) Exit the program\n\n";
     cout << "Enter your choice: ";
 }


 void makeDeposit(Account &acnt)
 {
     double dollars;

     cout << "Enter the amount of the deposit: ";
     cin >> dollars;
     cin.ignore();
     acnt.makeDeposit(dollars);
 }


 void withdraw(Account &acnt)
 {
     double dollars;

     cout << "Enter the amount of the withdrawal: ";
     cin >> dollars;
     cin.ignore();
     if (!acnt.withdraw(dollars))
          cout << "ERROR: Withdrawal amount too large.\n\n";
 }

💻 Program Output














































































13.14 Focus on Object-Oriented Programming: Simulating Dice with Objects

  • This section demonstrates how to create a Die class to simulate the rolling of dice with a variable number of sides.
Contents of Die.h
 #ifndef DIE_H
 #define DIE_H

 class Die
 {
 private:
      int sides; 
      int value; 

 public:
      Die(int = 6);   
      void roll();    
      int getSides(); 
      int getValue(); 
 };
 #endif
Contents of Die.cpp
 #include <cstdlib> 
 #include <ctime>   
 #include "Die.h"
 using namespace std;

 Die::Die(int numSides)
 {
     unsigned seed = time(0);

     srand(seed);

     sides = numSides;

     roll();
 }

 void Die::roll()
 {
   const int MIN_VALUE = 1; 

   value = (rand() % (sides - MIN_VALUE + 1)) + MIN_VALUE;
 }

 int Die::getSides()
 {
   return sides;
 }

 int Die::getValue()
 {
   return value;
 }
  • Synopsis of Class Members:

    • sides: An int to hold the number of sides on the die.
    • value: An int to hold the current face value of the die.
    • Constructor: Accepts the number of sides (defaulting to 6), seeds the random number generator, sets the number of sides, and performs an initial roll.
    • roll(): Simulates a die roll by generating a random number between 1 and the number of sides.
    • getSides(): Returns the number of sides.
    • getValue(): Returns the current value.
  • The following program demonstrates creating two Die objects with different numbers of sides and rolling them multiple times.

🗊 Program 13-16

 #include <iostream>
 #include "Die.h"
 using namespace std;

 int main()
 {
     const int DIE1_SIDES = 6;    
     const int DIE2_SIDES = 12;   
     const int MAX_ROLLS = 5;     

     Die die1(DIE1_SIDES);
     Die die2(DIE2_SIDES);

     cout << "This simulates the rolling of a "
          << die1.getSides() << " sided die and a "
          << die2.getSides() << " sided die.\n";

     cout << "Initial value of the dice:\n";
     cout << die1.getValue() << " "
          << die2.getValue() << endl;

     cout << "Rolling the dice " << MAX_ROLLS
          << " times.\n";
     for (int count = 0; count < MAX_ROLLS; count++)
     {
         die1.roll();
         die2.roll();

         cout << die1.getValue() << " "
              << die2.getValue() << endl;
     }
     return 0;
 }

💻 Program Output










13.15 Focus on Object-Oriented Design: The Unified Modeling Language (UML)

Concept:
  • The Unified Modeling Language (UML) offers a standard graphical notation for designing and depicting object-oriented systems.
  • A UML diagram is a helpful tool for designing a class.

  • The general layout is a box divided into three sections:

    1. Top Section: Class Name
    2. Middle Section: Member Variables (Attributes)
    3. Bottom Section: Member Functions (Operations)

Showing Access Specification in UML Diagrams

  • UML uses specific characters to indicate member access specification:
    • - (minus sign) indicates a private member.
    • + (plus sign) indicates a public member.

Data Type and Parameter Notation in UML Diagrams

  • UML provides notation to specify data types. The syntax is memberName : dataType, which is the reverse of C++ syntax.
    • Member Variable: - width : double
    • Function Return Type: + getLength() : double
    • Function Parameters: + setLength(len : double) : void

Showing Constructors and Destructors in a UML Diagram

  • Constructors are shown like other functions but without a return type.

  • The UML diagram in Figure 13-22 shows the design for an InventoryItem class, including overloaded constructors and member data types.

13.16 Focus on Object-Oriented Design: Finding the Classes and Their Responsibilities

Concept:
  • A primary step in creating an OO application is to identify the necessary classes and determine what each class is responsible for.

Finding the Classes

  • The first step in designing an OO application is to identify the classes needed to model the real-world objects in the problem.

  • A simple technique for finding classes involves these steps:

    1. Write a detailed description of the problem domain (the set of real-world objects and events related to the problem).
    2. Identify all the nouns in the description. Each noun is a potential class.
    3. Refine the list of nouns to keep only the classes that are relevant to the problem.

Identify All of the Nouns

  • After writing the problem domain description, list every noun and noun phrase. This list becomes the initial set of candidate classes.

Refine the List of Nouns

  • Not every noun will become a class. Refine the list by eliminating nouns based on the following criteria:
    1. Redundancy: Remove nouns that refer to the same concept (e.g., “car” and “foreign car” might both just be a Car class).
    2. Irrelevance: Remove nouns that represent items not essential to solving the specific problem (e.g., a “manager” class might be unnecessary if the application only generates quotes and doesn’t track who created them).
    3. Objects vs. Classes: Remove nouns that represent specific instances (objects) rather than a general category (class). For example, “Porsche” is an object of the Car class.
    4. Simple Values: Remove nouns that represent simple data types (like int or string) that can be stored as attributes within another class, rather than needing a class of their own (e.g., “name”, “address”, “year”).

Identifying a Class’s Responsibilities

  • Once classes are identified, determine their responsibilities. A class’s responsibilities are:

    • Things the class needs to know: These become the class’s attributes (member variables).
    • Actions the class needs to do: These become the class’s member functions.
  • To find these responsibilities, analyze the problem domain description and ask: “What must this class know?” and “What must this class do?”

  • For example, after analyzing the “Joe’s Automotive Shop” problem, we might identify three classes: Customer, Car, and ServiceQuote.

    • The Customer class is responsible for knowing a name, address, and phone number, and for doing things like setting and getting that information.
    • The Car class is responsible for knowing a make, model, and year.
    • The ServiceQuote class is responsible for knowing parts and labor charges and for doing calculations for sales tax and the total cost.

This Is Only the Beginning

  • Object-oriented design is an iterative process.

  • Your initial list of classes and responsibilities is a starting point. As your understanding of the problem deepens, you will likely refine and improve your design.

Checkpoint

  1. 13.27 What is a problem domain?

  2. 13.28 When designing an object-oriented application, who should write a description of the problem domain?

  3. 13.29 How do you identify the potential classes in a problem domain description?

  4. 13.30 What are a class’s responsibilities?

  5. 13.31 What two questions should you ask to determine a class’s responsibilities?

  6. 13.32 Will all of a class’s actions always be directly mentioned in the problem domain description?

  7. 13.33 Look at the following description of a problem domain:

    A doctor sees patients in her practice. When a patient comes to the practice, the doctor performs one or more procedures on the patient. Each procedure that the doctor performs has a description and a standard fee. As the patient leaves the practice, he or she receives a statement from the office manager. The statement shows the patient’s name and address, as well as the procedures that were performed, and the total charge for the procedures.

    Assume you are writing an application to generate a statement that can be printed and given to the patient.

    1. Identify all of the potential classes in this problem domain.

    2. Refine the list to include only the necessary class or classes for this problem.

    3. Identify the responsibilities of the class or classes that you identified in step B.

Review Questions and Exercises

Short Answer

  1. What is the difference between a class and an instance of the class?

  2. What is the difference between the following Person structure and Person class?

    struct Person
    {
       string name;
       int age;
    };
    class Person
    {
       string name;
       int age;
    };
  3. What is the default access specification of class members?

  4. Look at the following function header for a member function:

    void Circle::getRadius()

    What is the name of the function?

    Of, what class is the function a member?

  5. A contractor uses a blueprint to build a set of identical houses. Are classes analogous to the blueprint or the houses?

  6. What is a mutator function? What is an accessor function?

  7. Is it a good idea to make member variables private? Why or why not?

  8. Can you think of a good reason to avoid writing statements in a class member function that use cout or cin?

  9. Under what circumstances should a member function be private?

  10. What is a constructor? What is a destructor?

  11. What is a default constructor? Is it possible to have more than one default constructor?

  12. Is it possible to have more than one constructor? Is it possible to have more than one destructor?

  13. If a class object is dynamically allocated in memory, does its constructor execute? If so, when?

  14. When defining an array of class objects, how do you pass arguments to the constructor for each object in the array?

  15. What are a class’s responsibilities?

  16. How do you identify the classes in a problem domain description?

Fill-in-the-Blank

  1. The two common programming methods in practice today are ____________________ and ____________________.

  2. ____________________ programming is centered around functions or procedures.

  3. ____________________ programming is centered around objects.

  4. ____________________ is an object’s ability to contain and manipulate its own data.

  5. In C++, the ____________________ is the construct primarily used to create objects.

  6. A class is very similar to a(n) ____________________.

  7. A(n) ____________________ is a key word inside a class declaration that establishes a member’s accessibility.

  8. The default access specification of class members is ____________________.

  9. The default access specification of a struct in C++ is ____________________.

  10. Defining a class object is often called the ____________________ of a class.

  11. Members of a class object may be accessed through a pointer to the object by using the ____________________ operator.

  12. If you were writing the declaration of a class named Canine, what would you name the file it was stored in? ____________________

  13. If you were writing the external definitions of the Canine class’s member functions, you would save them in a file named ____________________.

  14. When a member function’s body is written inside a class declaration, the function is ____________________.

  15. A(n) ____________________ is automatically called when an object is created.

  16. A(n) ____________________ is a member function with the same name as the class.

  17. ____________________ are useful for performing initialization or setup routines in a class object.

  18. Constructors cannot have a(n) ____________________ type.

  19. A(n) ____________________ constructor is one that requires no arguments.

  20. A(n) ____________________ is a member function that is automatically called when an object is destroyed.

  21. A destructor has the same name as the class, but is preceded by a(n) ____________________ character.

  22. Like constructors, destructors cannot have a(n) ____________________ type.

  23. A constructor whose arguments all have default values is a(n) ____________________ constructor.

  24. A class may have more than one constructor, as long as each has a different ____________________.

  25. A class may only have one default ____________________ and one ____________________.

  26. A(n) ____________________ may be used to pass arguments to the constructors of elements in an object array.

Algorithm Workbench

  1. Write a class declaration named Circle with a private member variable named radius. Write set and get functions to access the radius variable, and a function named getArea that returns the area of the circle. The area is calculated as

    3.14159 * radius * radius
  2. Add a default constructor to the Circle class in Question 43. The constructor should initialize the radius member to 0.

  3. Add an overloaded constructor to the Circle class in Question 44. The constructor should accept an argument and assign its value to the radius member variable.

  4. Write a statement that defines an array of five objects of the Circle class in Question 45. Let the default constructor execute for each element of the array.

  5. Write a statement that defines an array of five objects of the Circle class in Question 45. Pass the following arguments to the elements’ constructor: 12, 7, 9, 14, and 8.

  6. Write a for loop that displays the radius and area of the circles represented by the array you defined in Question 47.

  7. If the items on the following list appeared in a problem domain description, which would be potential classes?

    Animal Medication Nurse
    Inoculate Operate Advertise
    Doctor Invoice Measure
    Patient Client Customer
  8. Look at the following description of a problem domain:

    The bank offers the following types of accounts to its customers: savings accounts, checking accounts, and money market accounts. Customers are allowed to deposit money into an account (thereby increasing its balance), withdraw money from an account (thereby decreasing its balance), and earn interest on the account. Each account has an interest rate.

    Assume you are writing an application that will calculate the amount of interest earned for a bank account.

    1. Identify the potential classes in this problem domain.

    2. Refine the list to include only the necessary class or classes for this problem.

    3. Identify the responsibilities of the class or classes.

True or False

  1. T F Private members must be declared before public members.

  2. T F Class members are private by default.

  3. T F Members of a struct are private by default.

  4. T F Classes and structures in C++ are very similar.

  5. T F All private members of a class must be declared together.

  6. T F All public members of a class must be declared together.

  7. T F It is legal to define a pointer to a class object.

  8. T F You can use the new operator to dynamically allocate an instance of a class.

  9. T F A private member function may be called from a statement outside the class, as long as the statement is in the same program as the class declaration.

  10. T F Constructors do not have to have the same name as the class.

  11. T F Constructors may not have a return type.

  12. T F Constructors cannot take arguments.

  13. T F Destructors cannot take arguments.

  14. T F Destructors may return a value.

  15. T F Constructors may have default arguments.

  16. T F Member functions may be overloaded.

  17. T F Constructors may not be overloaded.

  18. T F A class may not have a constructor with no parameter list, and a constructor whose arguments all have default values.

  19. T F A class may only have one destructor.

  20. T F When an array of objects is defined, the constructor is only called for the first element.

  21. T F To find the classes needed for an object-oriented application, you identify all of the verbs in a description of the problem domain.

  22. T F A class’s responsibilities are the things the class is responsible for knowing, and actions the class must perform.

Find the Errors

Each of the following class declarations or programs contain errors. Find as many as possible.

  1. class Circle:
    {
    private
       double centerX;
       double centerY;
       double radius;
    public
       setCenter(double, double);
       setRadius(double);
    }
  2. #include <iostream>
    using namespace std;
    
    Class Moon;
    {
    Private;
       double earthWeight;
       double moonWeight;
    Public;
       moonWeight(double ew);
          { earthWeight = ew; moonWeight = earthWeight / 6; }
       double getMoonWeight();
          { return moonWeight; }
    }
    int main()
    {
       double earth;
       cout >> "What is your weight? ";
       cin << earth;
       Moon lunar(earth);
       cout << "On the moon you would weigh "
            <<lunar.getMoonWeight() << endl;
       return 0;
    }
  3. #include <iostream>
    using namespace std;
    
    class DumbBell;
    {
       int weight;
    public:
       void setWeight(int);
    };
    void setWeight(int w)
    {
       weight = w;
    }
    int main()
    {
       DumbBell bar;
    
       DumbBell(200);
       cout << "The weight is " << bar.weight << endl;
       return 0;
    }
  4. class Change
    {
    public:
       int pennies;
       int nickels;
       int dimes;
       int quarters;
       Change()
          { pennies = nickels = dimes = quarters = 0; }
       Change(int p = 100, int n = 50, d = 50, q = 25);
    };
    void Change::Change(int p, int n, d, q)
    {
       pennies = p;
       nickels = n;
       dimes = d;
       quarters = q;
    }

Programming Challenges

  1. Date

    Design a class called Date. The class should store a date in three integers: month, day, and year. There should be member functions to print the date in the following forms:

    • 12/25/2018

    • December 25, 2018

    • 25 December 2018

    Demonstrate the class by writing a complete program implementing it.

    Input Validation: Do not accept values for the day greater than 31 or less than 1. Do not accept values for the month greater than 12 or less than 1.

    Solving the Employee Class Problem

  2. Employee Class

    Write a class named Employee that has the following member variables:

    • name—a string that holds the employee’s name

    • idNumber—a n int variable that holds the employee’s ID number

    • department—a string that holds the name of the department where the employee works

    • position—a string that holds the employee’s job title

    The class should have the following constructors:

    • A constructor that accepts the following values as arguments and assigns them to the appropriate member variables: employee’s name, employee’s ID number, department, and position.

    • A constructor that accepts the following values as arguments and assigns them to the appropriate member variables: employee’s name and ID number. The department and position fields should be assigned an empty string ("").

    • A default constructor that assigns empty strings ("") to the name, department, and position member variables, and 0 to the idNumber member variable.

    Write appropriate mutator functions that store values in these member variables and accessor functions that return the values in these member variables. Once you have written the class, write a separate program that creates three Employee objects to hold the following data:

    Name ID Number Department Position
    Susan Meyers 47899 Accounting Vice President
    Mark Jones 39119 IT Programmer
    Joy Rogers 81774 Manufacturing Engineer

    The program should store this data in the three objects and then display the data for each employee on the screen.

  3. Car Class

    Write a class named Car that has the following member variables:

    • yearModel—an int that holds the car’s year model

    • make—a string that holds the make of the car

    • speed—an int that holds the car’s current speed

    In addition, the class should have the following constructor and other member functions:

    • Constructor—The constructor should accept the car’s year model and make as arguments. These values should be assigned to the object’s yearModel and make member variables. The constructor should also assign 0 to the speed member variables.

    • Accessor—appropriate accessor functions to get the values stored in an object’s yearModel, make, and speed member variables

    • accelerate—The accelerate function should add 5 to the speed member variable each time it is called.

    • brake—The brake function should subtract 5 from the speed member variable each time it is called.

    Demonstrate the class in a program that creates a Car object, then calls the accelerate function five times. After each call to the accelerate function, get the current speed of the car and display it. Then, call the brake function five times. After each call to the brake function, get the current speed of the car and display it.

  4. Patient Charges

    Write a class named Patient that has member variables for the following data:

    • First name, middle name, last name

    • Address, city, state, and ZIP code

    • Phone number

    • Name and phone number of emergency contact

    The Patient class should have a constructor that accepts an argument for each member variable. The Patient class should also have accessor and mutator functions for each member variable.

    Next, write a class named Procedure that represents a medical procedure that has been performed on a patient. The Procedure class should have member variables for the following data:

    • Name of the procedure

    • Date of the procedure

    • Name of the practitioner who performed the procedure

    • Charges for the procedure

    The Procedure class should have a constructor that accepts an argument for each member variable. The Procedure class should also have accessor and mutator functions for each member variable.

    Next, write a program that creates an instance of the Patient class, initialized with sample data. Then, create three instances of the Procedure class, initialized with the following data:

    Procedure #1: Procedure #2: Procedure #3:

    Procedure name: Physical Exam

    Date: Today’s date

    Practitioner: Dr. Irvine

    Charge: 250.00

    Procedure name: X-ray

    Date: Today’s date

    Practitioner: Dr. Jamison

    Charge: 500.00

    Procedure name: Blood test

    Date: Today’s date

    Practitioner: Dr. Smith

    Charge: 200.00

    The program should display the patient’s information, information about all three of the procedures, and the total charges of the three procedures.

  5. RetailItem Class

    Write a class named RetailItem that holds data about an item in a retail store. The class should have the following member variables:

    • description—a string that holds a brief description of the item

    • unitsOnHand—an int that holds the number of units currently in inventory

    • price—a double that holds the item’s retail price

    Write a constructor that accepts arguments for each member variable, appropriate mutator functions that store values in these member variables, and accessor functions that return the values in these member variables. Once you have written the class, write a separate program that creates three RetailItem objects and stores the following data in them:

    Description Units On Hand Price
    Item #1 Jacket 12 59.95
    Item #2 Designer Jeans 40 34.95
    Item #3 Shirt 20 24.95
  6. Inventory Class

    Design an Inventory class that can hold information and calculate data for items in a retail store’s inventory. The class should have the following private member variables:

    Variable Name Description
    itemNumber An int that holds the item’s item number.
    quantity An int for holding the quantity of the items on hand.
    cost A double for holding the wholesale per-unit cost of the item
    totalCost A double for holding the total inventory cost of the item (calculated as quantity times cost).

    The class should have the following public member functions:

    Member Function Description
    Default Constructor Sets all the member variables to 0.
    Constructor #2 Accepts an item’s number, cost, and quantity as arguments. The function should copy these values to the appropriate member variables and then call the setTotalCost function.
    setItemNumber Accepts an integer argument that is copied to the itemNumber member variable.
    setQuantity Accepts an integer argument that is copied to the quantity member variable.
    setCost Accepts a double argument that is copied to the cost member variable.
    setTotalCost Calculates the total inventory cost for the item (quantity times cost) and stores the result in totalCost.
    getItemNumber Returns the value in itemNumber.
    getQuantity Returns the value in quantity.
    getCost Returns the value in cost.
    getTotalCost Returns the value in totalCost.

    Demonstrate the class in a driver program.

    Input Validation: Do not accept negative values for item number, quantity, or cost.

  7. TestScores Class

    Design a TestScores class that has member variables to hold three test scores. The class should have a constructor, accessor, and mutator functions for the test score fields and a member function that returns the average of the test scores. Demonstrate the class by writing a separate program that creates an instance of the class. The program should ask the user to enter three test scores, which are stored in the TestScores object. Then the program should display the average of the scores, as reported by the TestScores object.

  8. Circle Class

    Write a Circle class that has the following member variables:

    • radius—a double

    • pi—a double initialized with the value 3.14159

    The class should have the following member functions:

    • Default Constructor—a default constructor that sets radius to 0.0

    • Constructor—accepts the radius of the circle as an argument

    • setRadius—a mutator function for the radius variable

    • getRadius—an accessor function for the radius variable

    • getArea—returns the area of the circle, which is calculated as

      area = pi * radius * radius
    • getDiameter—returns the diameter of the circle, which is calculated as

      diameter = radius * 2
    • getCircumference—returns the circumference of the circle, which is calculated as

      circumference = 2 * pi * radius

    Write a program that demonstrates the Circle class by asking the user for the circle’s radius, creating a Circle object, then reporting the circle’s area, diameter, and circumference.

  9. Population

    In a population, the birth rate and death rate are calculated as follows:

    \begin{array}{l} {\text{Birth}\,\text{Rate}\, = \,\text{Number}\,\text{of}\,\text{Births}\, \div \,\text{Population}} \\ {\text{Death}\,\text{Rate}\, = \,\text{Number}\,\text{of}\,\text{Deaths}\, \div \,\text{Population}} \end{array}

    For example, in a population of 100,000 that has 8,000 births and 6,000 deaths per year, the birth rate and death rate are:

    \begin{array}{l} {\text{Birth}\,\text{Rate}\, = \,\text{8,000}\, \div \,\text{100,000}\, = \,\text{0}\text{.08}} \\ {\text{Death}\,\text{Rate}\, = \,\text{6,000}\, \div \,\text{100,000}\, = \,\text{0}\text{.06}} \end{array}

    Design a Population class that stores a population, number of births, and number of deaths for a period of time. Member functions should return the birth rate and death rate. Implement the class in a program.

    Input Validation: Do not accept population figures less than 1, or birth or death numbers less than 0.

  10. Number Array Class

    Design a class that has an array of floating-point numbers. The constructor should accept an integer argument and dynamically allocate the array to hold that many numbers. The destructor should free the memory held by the array. In addition, there should be member functions to perform the following operations:

    • Store a number in any element of the array

    • Retrieve a number from any element of the array

    • Return the highest value stored in the array

    • Return the lowest value stored in the array

    • Return the average of all the numbers stored in the array

    Demonstrate the class in a program.

  11. Payroll Class

    Design a PayRoll class that has data members for an employee’s hourly pay rate, number of hours worked, and total pay for the week. Write a program with an array of seven PayRoll objects. The program should ask the user for the number of hours each employee has worked, and will then display the amount of gross pay each has earned.

    Input Validation: Do not accept values greater than 60 for the number of hours worked.

  12. Coin Toss Simulator

    Write a class named Coin. The Coin class should have the following member variable:

    • A string named sideUp. The sideUp member variable will hold either “heads” or “tails” indicating the side of the coin that is facing up.

    The Coin class should have the following member functions:

    • A default constructor that randomly determines the side of the coin that is facing up (“heads” or “tails”) and initializes the sideUp member variable accordingly.

    • A void member function named toss that simulates the tossing of the coin. When the toss member function is called, it randomly determines the side of the coin that is facing up (“heads” or “tails”) and sets the sideUp member variable accordingly.

    • A member function named getSideUp that returns the value of the sideUp member variable.

    Write a program that demonstrates the Coin class. The program should create an instance of the class and display the side that is initially facing up. Then, use a loop to toss the coin 20 times. Each time the coin is tossed, display the side that is facing up. The program should keep count of the number of times heads is facing up and the number of times tails is facing up, and display those values after the loop finishes.

  13. Tossing Coins for a Dollar

    For this assignment, you will create a game program using the Coin class from Programming Challenge 12 (Coin Toss Simulator). The program should have three instances of the Coin class: one representing a quarter, one representing a dime, and one representing a nickel.

    When the game begins, your starting balance is $0. During each round of the game, the program will toss the simulated coins. When a coin is tossed, the value of the coin is added to your balance if it lands heads-up. For example, if the quarter lands heads-up, 25 cents is added to your balance. Nothing is added to your balance for coins that land tails-up. The game is over when your balance reaches $1 or more. If your balance is exactly $1, you win the game. You lose if your balance exceeds $1.

  14. Fishing Game Simulation

    For this assignment, you will write a program that simulates a fishing game. In this game, a six-sided die is rolled to determine what the user has caught. Each possible item is worth a certain number of fishing points. The points will not be displayed until the user has finished fishing, then a message is displayed congratulating the user depending on the number of fishing points gained.

    Here are some suggestions for the game’s design:

    • Each round of the game is performed as an iteration of a loop that repeats as long as the player wants to fish for more items.

    • At the beginning of each round, the program will ask the user whether he or she wants to continue fishing.

    • The program simulates the rolling of a six-sided die (use the Die class that was demonstrated in this chapter).

    • Each item that can be caught is represented by a number generated from the die. For example, 1 for “a huge fish,” 2 for “an old shoe,” 3 for “a little fish,” and so on.

    • Each item the user catches is worth a different amount of points.

    • The loop keeps a running total of the user’s fishing points.

    • After the loop has finished, the total number of fishing points is displayed, along with a message that varies depending on the number of points earned.

  15. Mortgage Payment

    Design a class that will determine the monthly payment on a home mortgage. The monthly payment with interest compounded monthly can be calculated as follows:

    \text{Payment} = \frac{\text{Loan} \times \frac{\text{Rate}}{12} \times \text{Term}}{\text{Term} - 1}

    where

    \text{Term} = \left( {1 + \frac{\text{Rate}}{12}} \right)^{12 \times \text{Years}}

    Payment = the monthly payment

    Loan = the dollar amount of the loan

    Rate = the annual interest rate

    Years = the number of years of the loan

    The class should have member functions for setting the loan amount, interest rate, and number of years of the loan. It should also have member functions for returning the monthly payment amount and the total amount paid to the bank at the end of the loan period. Implement the class in a complete program.

    Input Validation: Do not accept negative numbers for any of the loan values.

  16. Freezing and Boiling Points

    The following table lists the freezing and boiling points of several substances.

    Substance Freezing Point Boiling Point
    Ethyl alcohol -173 172
    Oxygen -362 -306
    Water 32 212

    Design a class that stores a temperature in a temperature member variable and has the appropriate accessor and mutator functions. In addition to appropriate constructors, the class should have the following member functions:

    • isEthylFreezing—This function should return the bool value true if the temperature stored in the temperature field is at or below the freezing point of ethyl alcohol. Otherwise, the function should return false.

    • isEthylBoiling—This function should return the bool value true if the temperature stored in the temperature field is at or above the boiling point of ethyl alcohol. Otherwise, the function should return false.

    • isOxygenFreezing—This function should return the bool value true if the temperature stored in the temperature field is at or below the freezing point of oxygen. Otherwise, the function should return false.

    • isOxygenBoiling—This function should return the bool value true if the temperature stored in the temperature field is at or above the boiling point of oxygen. Otherwise, the function should return false.

    • isWaterFreezing—This function should return the bool value true if the temperature stored in the temperature field is at or below the freezing point of water. Otherwise, the function should return false.

    • isWaterBoiling—This function should return the bool value true if the temperature stored in the temperature field is at or above the boiling point of water. Otherwise, the function should return false.

    Write a program that demonstrates the class. The program should ask the user to enter a temperature, then display a list of the substances that will freeze at that temperature, and those that will boil at that temperature. For example, if the temperature is -20 the class should report that water will freeze and oxygen will boil at that temperature.

  17. Cash Register

    Design a CashRegister class that can be used with the InventoryItem class discussed in this chapter. The CashRegister class should perform the following:

    1. Ask the user for the item and quantity being purchased.

    2. Get the item’s cost from the InventoryItem object.

    3. Add a 30 percent profit to the cost to get the item’s unit price.

    4. Multiply the unit price times the quantity being purchased to get the purchase subtotal.

    5. Compute a 6 percent sales tax on the subtotal to get the purchase total.

    6. Display the purchase subtotal, tax, and total on the screen.

    7. Subtract the quantity being purchased from the onHand variable of the InventoryItem class object.

    Implement both classes in a complete program. Feel free to modify the InventoryItem class in any way necessary.

    Input Validation: Do not accept a negative value for the quantity of items being purchased.

  18. A Game of 21

    For this assignment, you will write a program that lets the user play against the computer in a variation of the popular blackjack card game. In this variation of the game, two six-sided dice are used instead of cards. The dice are rolled, and the player tries to beat the computer’s hidden total without going over 21.

    Here are some suggestions for the game’s design:

    • Each round of the game is performed as an iteration of a loop that repeats as long as the player agrees to roll the dice, and the player’s total does not exceed 21.

    • At the beginning of each round, the program will ask the users whether they want to roll the dice to accumulate points.

    • During each round, the program simulates the rolling of two six-sided dice. It rolls the dice first for the computer, then it asks the user if he or she wants to roll. (Use the Die class demonstrated in this chapter to simulate the dice).

    • The loop keeps a running total of both the computer and the user’s points.

    • The computer’s total should remain hidden until the loop has finished.

    • After the loop has finished, the computer’s total is revealed, and the player with the most points without going over 21 wins.

  19. Trivia Game

    In this programming challenge, you will create a simple trivia game for two players. The program will work like this:

    • Starting with player 1, each player gets a turn at answering five trivia questions. (There are a total of 10 questions.) When a question is displayed, four possible answers are also displayed. Only one of the answers is correct, and if the player selects the correct answer, he or she earns a point.

    • After answers have been selected for all of the questions, the program displays the number of points earned by each player and declares the player with the highest number of points the winner.

    In this program, you will design a Question class to hold the data for a trivia question. The Question class should have member variables for the following data:

    • A trivia question

    • Possible answer #1

    • Possible answer #2

    • Possible answer #3

    • Possible answer #4

    • The number of the correct answer (1, 2, 3, or 4)

    The Question class should have appropriate constructor(s), accessor, and mutator functions.

    The program should create an array of 10 Question objects, one for each trivia question. Make up your own trivia questions on the subject or subjects of your choice for the objects.

Group Project

  1. Patient Fees

    1. This program should be designed and written by a team of students. Here are some suggestions:

      • One or more students may work on a single class.

      • The requirements of the program should be analyzed so that each student is given about the same workload.

      • The parameters and return types of each function and class member function should be decided in advance.

      • The program will be best implemented as a multi-file program.

    2. You are to write a program that computes a patient’s bill for a hospital stay. The different components of the program are

      • The PatientAccount class

      • The Surgery class

      • The Pharmacy class

      • The main program

        • The PatientAccount class will keep a total of the patient’s charges. It will also keep track of the number of days spent in the hospital. The group must decide on the hospital’s daily rate.

        • The Surgery class will have stored within it the charges for at least five types of surgery. It can update the charges variable of the PatientAccount class.

        • The Pharmacy class will have stored within it the price of at least five types of medication. It can update the charges variable of the PatientAccount class.

        • The student who designs the main program will design a menu that allows the user to enter a type of surgery and a type of medication, and check the patient out of the hospital. When the patient checks out, the total charges should be displayed.