a class consists of variables, called fields , together with functions , called methods ,
DESCRIPTION
A CLASS CONSISTS OF VARIABLES, CALLED FIELDS , TOGETHER WITH FUNCTIONS , CALLED METHODS , THAT ACT ON THOSE FIELDS. USER’S VIEW OF A CLASS: METHOD INTERFACES (= PRECONDITION + POSTCONDITION + METHOD HEADING) DEVELOPER’S VIEW OF A CLASS: FIELDS AND METHOD DEFINITIONS. - PowerPoint PPT PresentationTRANSCRIPT
CHAPTER 1
CLASSES IN C++
A CLASS CONSISTS OF VARIABLES,CALLED FIELDS, TOGETHER WITHFUNCTIONS, CALLED METHODS, THAT ACT ON THOSE FIELDS.
class MyClass{
public:MyClass( ){
...} // default constructorbool myMethod1 (int score){
...} // method myMethod1
private:string myField1;int myField2;
} // class MyClass
AN OBJECT IS A VARIABLE WHOSETYPE IS A CLASS.
AN OBJECT HAS THE FIELDS ANDCAN CALL THE METHODS OF ITSCLASS.
AN OBJECT IS SOMETIMES CALLEDAN INSTANCE OF ITS CLASS.
MyClass myObject1, myObject2;
if (myObject1.myMethod1 (47))cout << myObject2.myMethod1 (8);
USER’S VIEW OF A CLASS:
METHOD INTERFACES
(= PRECONDITION + POSTCONDITION
+ METHOD HEADING)
DEVELOPER’S VIEW OF A CLASS:
FIELDS AND METHOD DEFINITIONS
USER’S VIEW:public class FullName{
// Postcondition: This FullName object has been// initialized from s.public FullName (String s);
// Precondition: This FullName object contains// at least one blank.// Postcondition: The String of characters before// the first blank in this FullName// object has been returned.public String firstName( );
} // class FullName
DEVELOPER’S VIEW:class FullName{ public: FullName (string s) { fullName = s; } string firstName() { blankPos1 = fullName.find (BLANK); return fullName.substr (0, blankPos1); } // method firstName private: int blankPos1; string fullName; const static char BLANK = ' '; // const static OK for integer types}; // class FullName
PRINCIPLE OF DATA ABSTRACTION:
A USER’S CODE SHOULD NOTACCESS THE IMPLEMENTATIONDETAILS OF THE CLASS USED.
BEST-PAID EMPLOYEE IN A COMPANY?
CREATE A CLASS CALLED Employee.
THE INFORMATION AVAILABLE ON EACH EMPLOYEE CONSISTS OF THE EMPLOYEE’S NAME AND GROSS PAY.
THE Employee CLASS
USER’S VIEW
THE Employee CLASS: USER’S VIEW
// Postcondition: this Employee's name has been set to // “” and gross pay to 0.00. Employee( );
THE Employee CLASS: USER’S VIEW
// Postcondition: This Employee's name has been set to // “” and gross pay to 0.00. Employee( );
NOTE: IN THE ABOVE POSTCONDITION, AND IN
THE POSTCONDITIONS THAT FOLLOW, “this
Employee” REFERS TO THE CALLING OBJECT: THE
OBJECT THAT CALLED THE METHOD.
THE Employee CLASS: USER’S VIEW
// Postcondition: The name and gross pay of this // Employee been read in. void readInto( );
THE Employee CLASS: USER’S VIEW// Postcondition: true has been returned if this // Employee is the sentinel. Otherwise, // false has been returned. bool isSentinel( ) const;
NOTE: THE RESERVED WORD const AT THE END
OF THE METHOD HEADING MEANS THAT THE
DEFINITION OF THE METHOD IS NOT ALLOWED
TO MODIFY THE CALLING OBJECT.
THE Employee CLASS: USER’S VIEW
// Postcondition: true has been returned if this // Employee's gross pay is greater than// that of otherEmployee. Otherwise, false // has been returned. bool makesMoreThan (const Employee& otherEmployee) const;
THE Employee CLASS: USER’S VIEW
// Postcondition: true has been returned if this // Employee's gross pay is greater than// that of otherEmployee. Otherwise, false // has been returned. bool makesMoreThan (const Employee& otherEmployee) const;
DEFINITION NOT ADDRESS OF ARGUMENT ALLOWED TO MODIFY SENT, NOT A COPYARGUMENT OF ARGUMENT(PROVIDES SECURITY) (SAVES TIME AND SPACE)
THE Employee CLASS: USER’S VIEW
// Postcondition: this Employee contains a copy of // otherEmployee. void getCopyOf (const Employee& otherEmployee);
// Postcondition: this Employee's name and gross pay // have been written out. void printOut( ) const;
Employee OBJECTSEmployee employee1, employee2;
employee1.readInto( );
employee2.readInto( );
if (employee1.makesMoreThan (employee2))employee1.printOut( );
elseemployee2.printOut( );
THE Employee CLASS: DEVELOPER’S VIEW
employee1.h (THE HEADER FILE)
#ifndef EMPLOYEE#define EMPLOYEE#include <string> // declares string classusing namespace std;
class Employee{
THE Employee CLASS: DEVELOPER’S VIEW
employee1.h (continued) public:
// Postcondition: this employee's name has // been set to "" and gross pay
// to 0.00. Employee( );
// method interfaces for other methods
THE Employee CLASS: DEVELOPER’S VIEW
employee1.h (continued) private: string name; double grossPay; const static double
GROSS_PAY_SENTINEL; const static string EMPTY_STRING; const static string NAME_SENTINEL;
}; // Employee#endif
THE Employee CLASS: DEVELOPER’S VIEW
employee1.cpp (THE SOURCE FILE )
#include <iostream> #include <iomanip> // declares output formatting objects#include "employee1.h" // declares Employee class
THE Employee CLASS: DEVELOPER’S VIEW
employee1.cpp (continued )
Employee::Employee( ) { name = EMPTY_STRING; grossPay = 0.00;} // default constructor
scope-resolution employee1.cpp (continued ) operator (the readInto method in
void Employee::readInto( ) the Employee class) { const string NAME_AND_PAY_PROMPT = "Please enter a name and gross pay, to quit, enter ";
cout << NAME_AND_PAY_PROMPT << NAME_SENTINEL << " "
<< GROSS_PAY_SENTINEL; cin >> name >> grossPay; } // readInto
employee1.cpp (continued ) // definitions of other employee methods ...
const string Employee::EMPTY_STRING = "";const string Employee::NAME_SENTINEL = "*";const double Employee::GROSS_PAY_SENTINEL =
-1.0;
APPLICATION:
FIND THE BEST PAID EMPLOYEE
IN A COMPANY.
The Company Class: User’s View
// Postcondition: this Company has been initialized.Company( );
// Postcondition: this Company’s best‑paid employee// has been determined.void findBestPaid( ); // Postcondition: this Company’s best‑paid employee// has been printed out.void printBestPaid( ) const;
THE Company CLASS: DEVELOPER’S VIEW
SEE LAB 1
EXERCISE: TO GET THINGS STARTED,
THE main FUNCTION MUST DEFINE A
Company OBJECT. PROVIDE THAT
DEFINITION. WHAT FILE (employee1.h,
employee1.cpp, company1.h, company1.cpp)
MUST BE INCLUDED IN THE CLASS
THAT HAS THE main FUNCTION?
INHERITANCE
INHERITANCE IS THE ABILITY TODEFINE A NEW CLASS THATINCLUDES ALL THE FIELDS ANDSOME OR ALL OF THE METHODS OFAN EXISTING CLASS.
EXISTING CLASS = SUPERCLASS = BASE CLASS
NEW CLASS = SUBCLASS = DERIVED CLASS
SUPERCLASS
SUBCLASS
THE SUBCLASS MAY DECLARE NEWFIELDS AND METHODS, AND MAYOVERRIDE EXISTING METHODS BYGIVING THEM METHODDEFINITIONS THAT DIFFER FROMTHOSE IN THE SUPERCLASS.
EXAMPLE: FIND THE BEST-PAID HOURLY EMPLOYEE
INPUT: NAME, HOURS WORKED, PAY RATE
MODIFY Employee CLASS?
THE OPEN-CLOSED PRINCIPLE
EVERY CLASS SHOULD BE
OPEN: EXTENDIBLE THROUGH INHERITANCE
CLOSED: STABLE FOR EXISTING APPLICATIONS
IN PARTICULAR, THE Employee
CLASS SHOULD BE STABLE FORTHE EXISTING APPLICATION OFFINDING THE BEST-PAIDEMPLOYEE IN A COMPANY.
AND EXTENDIBLE FOR THIS NEWAPPLICATION!
THE NEW CLASS WILL BE
HourlyEmployee
A SUBCLASS OF Employee. WHICH
Employee METHODS WILL BE
OVERRIDDEN?
// Postcondition: this HourlyEmployee's name, hours// worked and pay rate have been// read in, and the gross pay has been// calculated.void readInto( );
// Postcondition: true has been returned if this// HourlyEmployee contains the// sentinels. Otherwise, false has// been returned.bool isSentinel( ) const;
THE makesMoreThan, getCopyOf and
printOut METHODS ARE UNTOUCHED,
AND MAY BE CALLED AS IS BY ANY
HourlyEmployee OBJECT
AFTER ALL, AN HourlyEmployee IS ANIS AN
Employee!
WHAT FIELDS?
FOR THE NEW INFORMATION:
hoursWorked, payRate
WHAT ABOUT name AND grossPay?
ACCORDING TO THE DEFINITION
OF INHERITANCE, THE HourlyEmployee
CLASS AUTOMATICALLY “INHERITS”
THESE TWO FIELDS.
BUT HOW?
TO ALLOW SUBCLASS OBJECTS TO
ACCESS SUPERCLASS FIELDS, THOSE
FIELDS SHOULD BE GIVEN THE
protected LEVEL OF PROTECTION.
private IS TOO RESTRICTIVE (SUPERCLASS ONLY)
public IS TOO LAX (ANY CLASS’S CODE CAN ACCESS THE FIELD)
SO, IN THE Employee CLASS, WE
CHANGE THE PROTECTION LEVEL
FOR THOSE TWO FIELDS:
protected:
string name,
double grossPay;
THEN THOSE TWO FIELDS CAN BE
ACCESSED IN ANY Employee CLASS
METHOD, AND IN ANY METHOD IN ANY
SUBCLASS OF Employee.
HERE IS THE DECLARATION OF THE
HourlyEmployee CLASS (THE POST-
CONDITIONS WERE GIVEN ABOVE):
class HourlyEmployee : public Employee{ public: HourlyEmployee( ); void readInto( ); bool isSentinel( ) const;
protected: int hoursWorked; double payRate;
const static int HOUR_WORKED_SENTINEL;const static double PAY_RATE_SENTINEL;
}; // HourlyEmployee
THE METHOD DEFINITIONS ARE JUST
WHAT YOU WOULD EXPECT. FOR
EXAMPLE, HERE IS THE DEFINITION
OF isSentinel:
bool HourlyEmployee::isSentinel( ) const { if (name == NAME_SENTINEL &&
hoursWorked == HOURS_WORKED_SENTINEL && payRate == PAY_RATE_SENTINEL) return true; return false; } // isSentinel
WE CREATED THIS HourlyEmployee
CLASS FOR THE APPLICATION OF
FINDING THE BEST-PAID HOURLYEMPLOYEE IN A COMPANY. CAN THE
ORIGINAL Company CLASS USE THE
HourlyEmployee CLASS FOR THIS
NEW APPLICATION?
NO, BECAUSE THE Company CLASS
MAKES NO MENTION OF AN
HourlyEmployee OBJECT. SO WE WILL
DEFINE Company2, A SUBCLASS OF
Company.
HERE IS THE DECLARATION OF THE
Company2 CLASS:
class Company2 : public Company { public: // This Company2 object has been initialized. Company2( ); // Postcondition: The hourly employee with
// the highest gross pay has // been determined. Ties have // been ignored.
void findBestPaid( ); }; // Company2
HOW DOES Company2’s findBestPaid
METHOD DIFFER FROM Company’s
findBestPaid METHOD? WE HAVE
HourlyEmployee employee;
INSTEAD OF
Employee employee;
THIS RAISES TWO QUESTIONS
ABOUT THE FOLLOWING CODE IN
THE findBestPaid METHOD: if (employee.makesMoreThan (bestPaid))
bestPaid.getCopyOf (employee);
1. HOW DID THE HourlyEmployee
OBJECT employee GET ITS grossPay
FIELD INITIALIZED? ANSWER: IMPLICITLY, THE DEFINI-
TION OF ANY SUBCLASS CONSTRUC-
TOR AUTOMATICALLY STARTS WITH
A CALL TO THE SUPERCLASS’S
DEFAULT CONSTRUCTOR.
THE DEFINITION
HourlyEmployee employee;
INVOKES THE HourlyEmployeeCLASS’S DEFAULT CONSTRUCTOR,WHICH AUTOMATICALLY INVOKESTHE Employee CLASS’S DEFAULTCONSTRUCTOR, WHICHINITIALIZES grossPay (AND name).
2. THE getCopyOf METHOD, WHICHIS NOT OVERRIDDEN, REQUIRESAN ARGUMENT OF TYPE Employee.BUT THE GIVEN ARGUMENT IS OFTYPE HourlyEmployee. WHY ISTHIS LEGAL?
ANSWER: BASICALLY, BECAUSE ANHourlyEmployee IS ALSO AN Employee.FORMALLY,
SUBCLASS SUBSTITUTION RULE
WHENEVER A SUPERCLASSOBJECT IS CALLED FOR IN ANEXPRESSION, A SUBCLASSOBJECT MAY BE SUBSTITUTED.
BECAUSE THE getCopyOf METHOD
CALLS FOR AN Employee
ARGUMENT, AN HourlyEmployee
ARGUMENT MAY BE SUBSTITUTED.
OPERATOR OVERLOADING
IDENTIFIERS SUCH AS getCopyOf,
makesMoreThan, readInto, AND printOut
ARE USER-DEFINED NAMES FOR
COMMON OPERATORS, NAMELY, = > >> <<
C++ ALLOWS A CLASS TO
OVERLOAD OPERATORS, THAT IS,
TO DEFINE THOSE OPERATORS AS
METHODS IN THE CLASS. FOR
EXAMPLE, HERE IS THE METHOD
INTERFACE FOR THE OVERLOADED
OPERATOR > IN THE Employee
CLASS:
// Postcondition: true has been returned if this // Employee's gross pay is greater than // otherEmployee's gross pay. Otherwise, // false has been returned. bool operator>(const Employee& otherEmployee)const; THE HEADING HAS operator> INSTEAD OF makesMoreThan
WHEN THE OPERATOR IS INVOKED,
THE PARENTHESES ARE OMITTED. SO,
FOR EXAMPLE, WE WOULD HAVE
if (employee > bestPaid) INSTEAD OF
if (employee.makesMoreThan (bestPaid))
THE BODY OF THE DEFINITION
OF operator> IN THE Employee CLASS IS
IDENTICAL TO THAT OF THE
EARLIER DEFINITION OF
makesMoreThan: bool Employee::operator> (const Employee& otherEmployee) const { return grossPay > otherEmployee.grossPay; } // overloading >
THE OVERLOADING OF operator=,
TO REPLACE getCopyOf, IS SIMILAR.
SEE LAB 3. THE OVERLOADING OF THE
INSERTION OPERATOR, operator>>,
AND THE EXTRACTION OPERATOR, operator<<, IS SLIGHTLY MORE
DELICATE.
LET’S CONSIDER operator<<.
THAT OPERATOR IS A METHOD IN
THE ostream CLASS, NOT IN THE
Employee CLASS.
THE QUESTION IS: HOW CAN WE ALLOW AN ostream
OBJECT, SUCH AS cout, TO ACCESS
THE FIELDS IN THE Employee
CLASS WHEN cout INVOKES
operator<<?
WE COULD MAKE THOSE FIELDS
public, BUT THEN ANY OBJECT IN
ANY CLASS COULD ACCESS THOSE
FIELDS, AND THIS WOULD MAKE IT
EASY FOR USERS TO VIOLATE THE
PRINCIPLE OF DATA ABSTRACTION.
INSTEAD, C++ ALLOWS A GIVEN
CLASS TO SPECIFY WHICH METHODS
IN ANOTHER CLASS CAN ACCESS
ALL OF THE MEMBERS (public, private,
AND protected) OF THE GIVEN CLASS.
TO ALLOW operator<< TO ACCESS
THE Employee CLASS’S MEMBERS, WE
INCLUDE THE FOLLOWING IN THE
DECLARATION OF Employee: friend ostream& operator<< (ostream& stream, const Employee& employee);
THE DEFINITION OF operator<< IN THE
Employee CLASS IS ALMOST
IDENTICAL TO THE EARLIER
DEFINITION OF printOut, EXCEPT
THAT operator<< RETURNS A VALUE:
ostream& operator<< (ostream& stream, const Employee& employee) {
cout << employee.name << " $" << setiosflags(ios::fixed) << setprecision (2) << employee.grossPay << endl;
return stream; } // overloading <<
WHEN AN OPERATOR RETURNS
A REFERENCE TO THE SAME TYPE AS
THE CALLING OBJECT, WE CAN
CHAIN INVOCATIONS OF THE
OPERATOR.
FOR EXAMPLE, cout << BEST_PAID_MESSAGE << bestPaid; THE FIRST CALL TO << PRINTS OUT A
MESSAGE AND RETURNS A
REFERENCE TO AN ostream OBJECT.
THAT OBJECT CALLS THE
BEFRIENDED VERSION OF << DEFINED
IN THE PREVIOUS SLIDES.
EXERCISE: RECALL THE HEADING FORTHE OVERLOADED VERSION OFoperator<<:
friend ostream& operator<< (ostream& stream, const Employee& employee);
BASED ON THAT HEADING, DETERMINETHE HEADING FOR THE OVERLOADEDVERSION OF operator>> IN THE EmployeeCLASS.