## Chapter 6: Classes

## Chapter Goals

- To be able to implement your own classes
- To master the separation of interface and implementation
- To understand the concept of encapsulation
- To design and implement accessor and mutator member functions
- To understand object construction
- To learn how to distribute a program over multiple source files

## Discovering Classes

- If you find yourself defining a number of related variables that all refer to the same concept, define a class that abstracts the concept and contains these variables as data fields.
- Suppose you are reading information about computers:
  - Model Name
  - Price
  - Score between 0 and 100
- Sample data:

  >     ACMA P600
  >     995
  >     77

  >     Alaris Nx868
  >     798
  >     57

- Sample code excerpt:

  >     if (next_score / next_price > best_score / best_price)
  >     {
  >        best_name = next_name;
  >        best_score = next_score;
  >        best_price = next_price;
  >     }

- Each of these sets of variables describes a product (a best product, and the next product read in). We need to develop a `Product` class.

## Discovering Classes (`bestval.cpp`)

## Interface

- To define a class, we first need to specify an interface.
- The interface consists of all member functions we want to apply to objects of that type.
- The interface is specified in the class definition.
- Example: Product class member functions:
  - Make a new product.
  - Read in a product object.
  - Compare two products and find out which one is better.
  - Print a product.
- Product class header:

  >     class Product
  >     {
  >     public:
  >        Product();
  >        void read();
  >        bool is_better_than(Product b) const;
  >        void print() const;
  >     private:
  >        implementation details
  >     };

## Interface (Syntax 6.1 : Class Definition)

Syntax 6.1 : Class Definitions
    class Class_name
    {
    public:
       constructor declarations
       member function declarations
    private:
       data fields
    };
Example: |
    class Point
    {
    public:
       Point (double xval, double yval);
       void move(double dx, double dy);
       double get_x() const;
       double get_y() const;
    private:
       double x;
       double y;
    };
Purpose: | Define the interface and data fields of a class.

## Interface

- The first member function is a constructor: the function that is used to initialize new objects.
- This constructor has no parameters so it is called a default constructor.
- Default constructors are automatically used when you construct an object without parameters.

  >     Product best; /* default construction */

- Every class should have a default constructor.
- The `read()` member function is a mutator function - an operation that modifies the object.
- The last two member functions are accessor functions - functions that query the object for some information without changing it.
- The keyword `const` indicates that the implicit parameter object is not modified by the member function.

## Interface (`product1.cpp`)

## Encapsulation

- Classes are broken into `public` and `private` sections.
- The data items are defined in the `private` sections of the class definition.

  >     class Product
  >     {
  >     public:
  >        Product();
  >        void read();
  >        bool is_better_than(Product b) const;
  >        void print() const;
  >     private:
  >        string name;
  >        double price;
  >        int score;
  >     };

- Only constructors and member functions can access `private` data.
- Hiding data is called encapsulation.
- Encapsulation forces indirect access to the data, guaranteeing that it cannot accidentally be put in an incorrect state.
- Example:

  >     Time liftoff(19, 30, 0);
  >     /* liftoff is delayed by six hours */
  >     /* won't compile, but suppose it did */
  >     liftoff.hours = liftoff.hours + 6;

  Does this mean liftoff is at 25:30:00?

## Member Functions

- Each member function advertised in the class interface must be implemented separately.
- A `Class_name``::` prefix makes it clear that we are defining a member function for that class.

  >     void Product::read()
  >     {
  >        cout << "Please enter the model name: ";
  >        getline(cin, name);
  >        cout << "Please enter the price: ";
  >        cin >> price;
  >        cout << "Please enter the score: ";
  >        cin >> score;
  >        string remainder; /* read the remainder of the line */
  >        getline(cin, remainder);
  >     }

- It is perfectly legal to have member functions in other classes as well; it is important to specify exactly which function goes with which class.
- A member function is called `object``.function_name()`.

  >     next.read();

## Member Functions (`const`)

- When the keyword `const` is used in the declaration, it must also be placed in the member function definition.

  >     void Product::print() const
  >     {
  >        cout << name
  >           << " Price: " << price
  >           << " Score: " << score << "\n";
  >     }

- The keyword `const` indicates that the member function will not modify the object that called it.
- When you refer to a data field in a member function, it denotes the data field of the object for which the member function was called.

  >     best.print();

- The object to which a member function is applied is called the implicit parameter.
- A parameter explicitly mentions in the function definition is called an explicit parameter.

  >     bool Product::is_better_than(Product b) const
  >     {
  >        if (b.price == 0) return false;
  >        if (price == 0) return true;
  >        return score / price > b.score / b.price;
  >     }

## Member Functions (Syntax 6.2 : Member Function Definition)

Syntax 6.2 : Member Function Definition
    return_type Class_name::function_name(parameter1, ..., parametern) [const]opt
    {
       statements
    }
Example: |
    void Point::move(double dx, double dy)
    {
       x = x + dx; y = y + dy;
    }
    double Point::get_x() const
    {
       return x;
    }
Purpose: | Supply the implementation of a member function.

## Default Constructors

- The purpose of a constructor is to initialize all data fields of an object.
- A constructor always has the same name as the class.

  >     Product::Product()
  >     {
  >        price = 0;
  >        score = 0;
  >     }

- Most default constructors initialize the data fields to zero, but not always.
  - The `Time` class initializes to current time.
  - Non-numeric data (e.g. string data) may have another value.

## Default Constructors (Syntax 6.3 : Constructor Definition)

Syntax 6.3 : Constructor Definition
    Class_name::Class_name(parameter1, ..., parametern)
    {
       statements
    }
Example: |
    Point::Point(double xval, double yval)
    {
       x = xval; y = yval;
    }
Purpose: | Supply the implementation of a constructor.

## Default Constructors (`product2.cpp`)

## Constructors with Parameters

- It's possible to create a class with more than one constructor.

  >     Employee Fred; /* default construction */
  >     Employee Harry("Harry Hacker", 40000); /* alternate construction */

- All constructors have the same name as the class, but have different parameter lists.

  >     class Employee
  >     {
  >     public:
  >        Employee()
  >        Employee(string employee_name, double initial_salary);

  >        void set_salary(double new_salary);

  >        string get_name() const;
  >        double get_salary() const;
  >     private:
  >        string name;
  >        double salary;
  >     };

- Whenever two functions have the same name but are distinguished by their parameter types, the function name is overloaded.
- The second constructor sets the data fields of the new object based on the parameters.

  >     Employee::Employee(string employee_name, double initial_salary)
  >     {
  >        name = employee_name;
  >        salary = initial_salary;
  >     }

## Constructors with Parameters

- Sometimes a constructor gets more complex because one of the data fields is itself an object of another class with its own constructor.
- Example: suppose we modify the `Employee` class so that each `Employee` has scheduled work hours.

  >     class Employee
  >     {
  >     public:
  >        Employee(string employee_name, double initial_salary,
  >           int arrive_hour, int leave_hour);
  >        . . .
  >     private:
  >        string name;
  >        double salary;
  >        Time arrive;
  >        Time leave;
  >     };

  The constructor must initialize the time fields using the `Time()` constructor.

  >     Employee::Employee(string employee_name, double initial_salary,
  >        int arrive_hour, int leave_hour)
  >     {
  >        name = employee_name;
  >        salary = initial_salary;
  >        arrive = Time(arrive_hour, 0, 0);
  >        leave = Time(leave_hour, 0, 0);
  >     }

## Constructors with Parameters (Syntax 6.4 : Constructors with Field Initializer List)

Syntax 6.4 : Constructors with Field Initializer List
    Class_name::Class_name(parameters):field1(expression), ..., fieldn(expression)
    {
      statements
    }
Example: |
    Point::Point(double xval, double yval):
    x(xval), y(yval)
    {
    }
Purpose: | Supply the implementation of a constructor, initializing data fields before the body of the constructor.

- The syntax above is an alternate, and more efficient, way to initialize data field, but many programmers find it confusing.
- This syntax is necessary to construct objects of classes that don't have a default constructor.

## Accessing Data Fields

- Only member functions of a class are allowed to access the private data fields of objects of that class.

  >     void raise_salary(Employee& e, double percent)
  >     {
  >        e.salary = e.salary * (1 + percent / 100 ); /* Error */
  >     }

- Data fields must be accessed by accessor and mutator functions.

  >     void raise_salary(Emplyee & e, double percent)
  >     {
  >        double new_salary = e.get_salary() * (1 + percent / 100);
  >        e.set_salary(new_salary);
  >     }

## Accessing Data Fields

- Not every data member needs accessor functions (the `Product` class did not have a `get_score()` function).
- Not every `get_` function needs a matching `set_` (the `Time` class can`get_minutes()` but not `set_minutes()`).
- Remember that implementation is supposed to be hidden - just because a class has member functions named `get_` or `set_` does not necessarily explain how the class is designed.

  >     Time::Time(int hour, int min, int sec)
  >     {
  >        time_in_secs = 60 * 60 * hour + 60 * min + sec;
  >     }

  >     int Time::get_minutes() const
  >     {
  >        return (time_in_secs / 60) % 60;
  >     }

  >     int Time::seconds_from(Time t) const
  >     {
  >        return time_in_secs - t.time_in_secs;
  >     }

## Comparing Member Functions with Nonmember Functions

- Consider the nonmember function

  >     void raise_salary(Employee& e, double percent)
  >     {
  >        double new_salary = e.get_salary()
  >           * (1 + percent / 100);
  >        e.set_salary(new_salary);
  >     }

  versus the memeber function

  >     void Employee::raise_salary(double percent)
  >     {
  >        salary = salary * (1 + percent / 100);
  >     }

- A nonmember function is called with two explicit parameters.

  >     raise_salary(harry, 7);

- A member function is called using the dot notation, with one explicit parameter and one implicit parameter.

  >     harry.raise_salary(7);

- A member function can invoke another member function on the implicit parameter without using the dot notation.

  >     void Employee::print() const
  >     {
  >        cout << "Name: " << get_name()
  >           << "Salary: " << get_salary()
  >           << "\n";
  >     }

## Comparing Member Functions with Nonmember Functions

- Member functions automatically (by default) pass the implicit parameter by reference.
- Nonmember functions automatically (by default) pass their parameters by value.

| Explicit Parameter | Implicit Parameter
Value Parameter (not changed) | Default Example: `void print(Employee)` | Use `const` Example: `void Employee::print()const`
Reference Parameter (can be changed) | Use & Example: `void raiseSalary(Employee & e, double p)` | Default Example: `void Employee::raiseSalary(double p)`

## Separate Compilation

- When your code gets large or you work in a team, you will want to split your code into separate source files.
  - Saves time: instead of recompiling the entire program, only recompile files that have been changed.
  - Group work: separate programmers work on separate files.
- The h eader file (e.g.`Product.h`) contains:
  - definitions of constants
  - definitions of classes
  - declarations of nonmember functions
  - declarations of global variables
- The source file (e.g.`Product.cpp`) contains
  - definitions of member functions
  - definitions of nonmember functions
  - definitions of global variables

## Separate Compilation (`product.h`)

## Separate Compilation (`product.cpp`)

## Separate Compilation (`prodtest.cpp`)

## Separate Compilation

- Special code for the compiler must be put in a header file to prevent the file from being compiled twice.

  >     #ifndef PRODUCT_H
  >     #define PRODUCT_H
  >     . . .
  >     #endif

- The source file includes its own header file.

  >     #include "Product.h"

- The source file does not contain a main function because many programs may use this class.
- Shared constants are placed in the header file.
- To share global variables among source files, declare them in a header file as extern.

  >     extern GraphicWindow cwin;

  The source file contains the definition.

  >     GraphicWindow cwin;