--- tags: Programming Design title: Topic 7 Classes --- # <font color="#1D617A">Topic 7</font> Classes > Author: Benson Chiu (NTU IM) > Inspector: Ruby (NTU IM) ## <font color="#1D617A">7.1</font> A simple analogy - Driving a car - For people: Make the car go faster by pressing down on its accelerator pedal - Actually: **The pedal hides the complex machanisms** making the car faster - The pedal creates a **user-friendly interface** to the car's complex internal machanisms ![](https://i.imgur.com/37wYQB1.png =x200) - Performing a task in a program requires a **function** - **Functions:** describe the mechanisms that actually perform - Users can use the function directly without further knowledge into its machanism - The function is thus called ==**"Member Function"**== - Analogy - An engineering drawing of a car -> ==**Class**== - Every Car -> Every ==**Object**== - Many **cars** can be built from the same **engineering drawing** -> Many ==**objects**== can be built from the ==**same class**== - Capabilities a car provides -> ==**Attributes**== - E.g. Its color, the number of doors...... - **Every cars maintain its own attributes** --- ## <font color="#1D617A">7.2</font> Time Class ### Time class definition ```cpp= #include<iostream> #include<iomanip> using namespace std; class Time { public: Time(); //constructor void setTime( int, int, int ); //set hour, minute and second void printUniversal(); // print time in universal-time format void printStandard(); // print time in standard-time format private: int hour; // 0 ~ 23 (24-hrs format) int minute; //0 ~ 59 int second; //0 ~ 59 }; //Time constructor initializes each data member to zero. //Ensure all Time objects start in a consisitent state. Time::Time() { hour = minute = second = 0; } // set new Time value using the universal time; ensure that // the data remains consistent by setting invalid values to zero void Time::setTime( int h, int m, int s) { hour = ( h >= 0 && h < 24 ) ? h : 0; // validate hour minute = ( m >= 0 && m < 60 ) ? m : 0; //validate minute second = ( s >= 0 && s < 60 ) ? s : 0; //validate second } // print Time in universal format (HH:MM:SS) void Time::printUniversal() { cout << setfill('0') << setw(2) << hour << ":" << setw(2) << minute << ":" << setw(2) <<second; } //print Time in standard-time format (HH:MM:SS AM or PM) void Time::printStandard() { cout << (( hour == 0 || hour == 12) ? 12 : hour % 12 ) << ":" << setfill('0') << setw(2) << minute << ":" << setw(2) << second << ( hour < 12 ? " AM":" PM"); } int main() { Time t; // instantiate object t of class time // output Time object t's initial values cout << "The initial universal time is "; t.printUniversal(); //00:00:00 cout <<"\nThe initial standard time is "; t.printStandard(); //12:00:00 AM t.setTime(13, 27, 6); //change time //output Time object's new values cout << "\n\nUniversal after setTime is "; t.printUniversal(); //13:27:06 cout << "\nStandard time after setTime is "; t.printStandard(); // 1:27:06 AM t.setTime(99, 99, 99); //attempt invalid settings //output t's values after specifying invalid values cout << "\n\nAfter attempting invalid settings:" <<"\nUniversal time: "; t.printUniversal();//00:00:00 cout << "\nStandard time: "; t.printStandard(); //12:00:00 AM cout << endl; } ``` ### Expected output ![](https://i.imgur.com/8WME80h.png =x150) --- ### Code explanation #### 1. Defining the class ```cpp= class Time { public: Time(); //constructor void setTime( int, int, int ); //set hour, minute and second void printUniversal(); // print time in universal-time format void printStandard(); // print time in standard-time format private: int hour; // 0 ~ 23 (24-hrs format) int minute; //0 ~ 59 int second; //0 ~ 59 }; ``` - By convention, the name of the class begin with a **capital letter**, and **every subsequent word** starts with capital letter - E.g. `TimeZone, CreateAndDestroy` - Before the main function, we have to tell the compiler what **member functions** and **data members** belong to the class :::info Remember! The class definition terminates with a **semicolon (;)** ::: ---- #### 2. Declaring the `public` and `private` services - Access specifiers: `public:` and `private:` - `public:` to indicate they can be called by other function in the program (such as `int main()`) - `private:`are accessible only to member functions for the class for which which they're declared - **Data hiding**: declaring data members with access specifier `private` :::warning Generally, data members should be declared `private` and member functions should be declared `public` ::: --- #### 3. Class `Time`'s Constructor ```cpp= //Time constructor initializes each data member to zero. //Ensure all Time objects start in a consisitent state. Time::Time() { hour = minute = second = 0; } ``` --- #### 4. `setTime` Member function ```cpp= // set new Time value using the universal time, ensure that // the data remains consistent by setting invalid values to zero void Time::setTime( int h, int m, int s) { hour = ( h >= 0 && h < 24 ) ? h : 0; // validate hour minute = ( m >= 0 && m < 60 ) ? m : 0; //validate minute second = ( s >= 0 && s < 60 ) ? s : 0; //validate second } ``` ---- #### 5. `printUniversal` Member function ```cpp= // print Time in universal format (HH:MM:SS) void Time::printUniversal() { cout << setfill('0') << setw(2) << hour << ":" << setw(2) << minute << ":" << setw(2) <<second; } ``` ---- #### 6. `printStandard` Member function ```cpp= //print Time in standard-time format (HH:MM:SS AM or PM) void Time::printStandard() { cout << (( hour == 0 || hour == 12) ? 12 : hour % 12 ) << ":" << setfill('0') << setw(2) << minute << ":" << setw(2) << second << ( hour < 12 ? " AM":" PM"); } ``` --- #### 7. Defining Member Functions Outside the Class Definiton: Class Scope - When define a member function of a certain class **outside the definition of the class**, using `className :: funcName(...)` - "::" is called the **binary scope resolution operator** --- #### 8. Using Class `Time` ```cpp= Time sunset; //object of type time Time arrayOfTimes[5]; //array of 5 time objects Time &dinnerTime = sunset; //reference to a Time object Time *timePtr = &dinnerTime //pointer to a Time object ``` - Using the member function of the object - Case-1: Using the dot operator (.) - E.g. `t.printUniversal()` - Case-2: When it's a pointer to a object - E.g. `tPtr -> printUniversal` - Which equals to `(*tPtr).printUniversal()` --- ## <font color="#1D617A">7.3</font> Class Scope and Accessing Class Members ### <font color="#659DB4">Topic 1</font> Class Scope - Class's data members and member functions -> **Belongs to that class's scope** - Nonmember functions -> Belongs to **global namespace scope** - Class's member functions can be only overloaded by other member fuctions in the class - The class-scope variable will be hidden by the local variable in the local scope - To use the global variable in the local block, use the scope resolution operator (::) --- ### <font color="#659DB4">Topic 2</font> Accessing Class's members ```cpp= #include <iostream> using namespace std; class Count { public: //set the value of private data member x void setX(int value) { x = value; } //print the value of private data member x void print() { cout << x << endl; } private: int x; }; int main() { Count counter; //create counter object Count *counterPtr = &counter; //create pointer to counter Count &counterRef = counter; //create reference to counter cout << "Set x to 1 and print using the object's name: "; counter.setX( 1 ); counter.print(); cout << "Set x to 2 and print using a reference to an object: "; counterRef.setX( 2 ); counterRef.print(); cout << "Set x to 3 and print using a pointer to an object: "; counterPtr -> setX( 3 ); counterPtr -> print(); } ``` #### Catagarizing by the object types - Objects and reference to an object - `objName.member` - Pointer to an object - `objPtr -> member` --- ## <font color="#1D617A">7.4</font> Time Class: Separating Interface from Implementation ### Interface of a Class - Define and Standardize the ways in which things such as people and systems interact one another - The interface of a class describes $what$ service **a class's clients can use** and $how$ to **request services**, **==NOT==** $how$ the class carries out the service ### Seperating the Interface from Implementation ![](https://i.imgur.com/7SWzF86.png) #### 1. `Time.h` Defining a Class's Interface in a Header File ```cpp= #ifndef Time_h #define Time_h class Time { public: Time(); //constructor void setTime( int, int, int ); //set hour, minute and second void printUniversal(); // print time in universal-time format void printStandard(); // print time in standard-time format private: int hour; // 0 ~ 23 (24-hrs format) int minute; //0 ~ 59 int second; //0 ~ 59 }; #endif /* Time_h */ ``` #### 2. Preprocessor Wrappers ```cpp= //prevent multiple inclusions of header file #ifndef Time_h //ifndef = If not defined #define Time_h ....... #endif /* Time_h */ ``` #### 3. `Time.cpp` Defining member function to a Sperate Source-Code file ```cpp= #include <iostream> #include <iomanip> #include "Time.h" //include definiton of class Time from Time.h using namespace std; //Time constructor initializes each data member to zero. //Ensure all Time objects start in a consisitent state. Time::Time() { hour = minute = second = 0; } // set new Time value using the universal time; ensure that // the data remains consistent by setting invalid values to zero void Time::setTime( int h, int m, int s) { hour = ( h >= 0 && h < 24 ) ? h : 0; // validate hour minute = ( m >= 0 && m < 60 ) ? m : 0; //validate minute second = ( s >= 0 && s < 60 ) ? s : 0; //validate second } // print Time in universal format (HH:MM:SS) void Time::printUniversal() { cout << setfill('0') << setw(2) << hour << ":" << setw(2) << minute << ":" << setw(2) <<second; } //print Time in standard-time format (HH:MM:SS AM or PM) void Time::printStandard() { cout << (( hour == 0 || hour == 12) ? 12 : hour % 12 ) << ":" << setfill('0') << setw(2) << minute << ":" << setw(2) << second << ( hour < 12 ? " AM":" PM"); } ``` #### 4. Testing `Class Time` - **Driver program:** Seperate source-code file containing `int main()` to test our classes - It's essential for large software developers to put main function in an independent file, in case that the clients will see the back mechanism of the classes ```cpp= #include <iostream> #include <iomanip> #include "Time.h" //include definiton of class Time from Time.h using namespace std; int main() { Time t; // instantiate object t of class time // output Time object t's initial values cout << "The initial universal time is "; t.printUniversal(); //00:00:00 cout <<"\nThe initial standard time is "; t.printStandard(); //12:00:00 AM t.setTime(13, 27, 6); //change time //output Time object's new values cout << "\n\nUniversal after setTime is "; t.printUniversal(); //13:27:06 cout << "\nStandard time after setTime is "; t.printStandard(); // 1:27:06 AM t.setTime(99, 99, 99); //attempt invalid settings //output t's values after specifying invalid values cout << "\n\nAfter attempting invalid settings:" <<"\nUniversal time: "; t.printUniversal();//00:00:00 cout << "\nStandard time: "; t.printStandard(); //12:00:00 AM cout << endl; } ``` #### 5. The Compilation and Linking Process ![](https://i.imgur.com/DnmEQiv.png) - Two programmers - Class Implementation Programmers (GIP) - Create `Time.h` and `Time.cpp` - **Give `Time.h` to GCP** - Client Code Programmers (GCP) - Have to know the Time's **interface** to use the class - He/She is not given `Time.cpp` #### Remark: Quotes(`""`) v.s. Brackets(`<>`) - Quotes: Locate the header file **in the same directory** - E.g. `#include "Time.h"` in the case above - Brackets: Locate the header file in the **C++ Standard Library** - E.g. `#include<iostream>` --- ## <font color="#1D617A">7.5</font> Access Functions and Utility Functions 1. Access functions - Read and display data - Test the truth and the falsity of conditions / **predicate functions** 2. Utility functions - Also knowned as **helper functions** - It's a **private** member function ++that support the operation of the class's public member function++ --- ![](https://i.imgur.com/7rl1QAR.png =x75) ### Code *The code demonstrates the notion of **a utility function*** ```cpp= //SalesPerson.h #ifndef SALESP_H #define SALESP_H class SalesPerson { public: static const int monthsPerYear = 12; // months in one year SalesPerson(); // constructor void getSalesFromUser(); // Input sales from keyboard void setSales( int, double ); //Set sales for a specific month void printAnnualSales(); // summarize and print sales private: double totalAnnualSales(); // prototype for utility function double sales[ monthsPerYear ]; //12 monthly sales figures }; #endif ``` ```cpp= //SalesPerson.cpp #include <iostream> #include <cstdlib> #include <iomanip> #include "SalesPerson.h" //include SalesPerson class definition using namespace std; //initialize elements of array sales to 0.0 SalesPerson::SalesPerson() { for( int i = 0; i < monthsPerYear; i++) sales[i] = 0.0; } void SalesPerson::getSalesFromUser() { double salesFigure; for ( int i = 1; i <= monthsPerYear; i++ ) { cout<<"Enter sales amount for month "<<i<< ": "; cin >> salesFigure; setSales(i, salesFigure); } } // Set one of the 12 monthly sales figures; function subtracts // one from month value for proper subscript in sales array void SalesPerson::setSales(int month, double amount) { //test for valid month and amount values if (month >= 1 && month <= monthsPerYear && amount > 0 ) sales[ month - 1 ] = amount; //adjust for subscript 0-11 else //invalid month and amount value cout << "Invalid month or sales figure" << endl; } //print total annual sales void SalesPerson::printAnnualSales() { cout << setprecision(2) << fixed << "\n The total annual sales are: $" << totalAnnualSales() << endl; //call utility function } double SalesPerson::totalAnnualSales() { double total = 0.0; for( int i = 0; i < monthsPerYear; i++) total += sales[i]; return total; } ``` ```cpp= //main.cpp #include "SalesPerson.h" int main() { SalesPerson s; //create SalesPerson object s s.getSalesFromUser(); //note simple sequential code; there are s.printAnnualSales();//no control statements in main } ``` ### Expected Output ![](https://i.imgur.com/Mjg8h0d.png =x200)