A CLASS CONSISTS OF VARIABLES, CALLED FIELDS , TOGETHER WITH FUNCTIONS , CALLED METHODS ,

Post on 19-Feb-2016

26 views 0 download

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 Presentation

Transcript of A CLASS CONSISTS OF VARIABLES, CALLED FIELDS , TOGETHER WITH FUNCTIONS , CALLED METHODS ,

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.