Transcript operator

Chapter 14
Object-Oriented Software
Development
Dale/Weems/Headington
1
Chapter 14 Topics






Structured Programming vs. Object-Oriented
Programming
Operator Overloading
Using Inheritance to Create a New C++ class
Type
Using Composition (Containment) to Create a
New C++ class Type
Static vs. Dynamic Binding of Operations to
Objects
Virtual Member Functions
2
Two Programming Paradigms
Structural (Procedural)
PROGRAM
Object-Oriented
PROGRAM
OBJECT
FUNCTION
Operations
FUNCTION
Data
OBJECT
OBJECT
FUNCTION
Operations
Operations
Data
Data
3
Object-Oriented Programming
Language Features
1. Data abstraction
2. Encapsulation
3. Inheritance of properties
4. Dynamic binding of operations to objects
4
OOP Terms
C++ Equivalents
Object
Class object or class instance
Instance variable
Private data member
Method
Public member function
Message passing
Function call ( to a public
member function )
5
What is an object?
OBJECT
Operations
Data
set of methods
(public member functions)
internal state
(values of private data members)
6
Operator Overloading
7
Complex Number

Domain:
X

= a + bi  Real and Imaginary parts
Operations: x, y, and z complex
•
•
•
•
•
•
- x negate
z = x+y
z=x–y
z = c*x where c is a scalar
Output a complex number;
Read a complex number;
8
Class Complex Number:
Specification
class complex {
private:
double Real, Im;
public:
complex();
complex (double R, double I);
complex negate (void);
// Negation
complex add (const complex & Y);
// Addition
complex sub (const complex & Y);
// Subtraction
bool IsEqual (const complex & Y) const ; // equality
complex ScalarMult (const double& c);
void output ( ); // outputs Real and Im to cout
void input ( ); // reads from cin into Real and Im
};
9
Operator Overloading

Only C++ built-in operators can be overloaded

Overloaded operator obeys the precedence, associativity,
and number of operands dictated by the built-in operator

When an operator is overloaded as a member function, the
object associated with the operator is the left-most operand
example: X + Y <=> X.operator + (Y)
=> left-most operand must be an object of the class of
which the operator is a member.
If that is not the case, instead of using a member operator
use a friend operator.
10
Complex ADT





Multiplication of a Complex by a Scalar
c * X = (c * X.Real, c * X.Im)
Note: In C++, c * X would be translated to
c.operator * (X)
The left-most operand of an overloaded operator must
be an object of the class being defined.
=> can not overload the * for complex scalar
multiplication
Solution: use a friend function
11
Overloading Operators

Stream I/O operators
complex X, Y;
cin >> X;
// Left-most operand is Not an object
cin >> X >> Y; // of type complex
cout << “Here is a complex number” << X;
cout << X << Y << endl;
12
Class Complex: Specification
class complex {
private:
double Real, Im;
public:
complex();
complex (double R, double I);
complex operator - (void);
// Negation
complex operator +(const complex & Y);
// Addition
complex operator - (const complex & Y);
// Subtraction
bool operator == (const complex & Y) const ;
// equality
friend complex operator * (const double& c, const complex& X);
friend istream& operator >> (istream& istr, complex& X);
friend ostream& operator << (ostream& ostr, const complex& X);
};
13
Class Complex: Implementation
complex:: complex(double R, double I) { // The Constructor
Real = R; Im = I;
}
complex complex:: operator - (void) {
// returns the value complex(-Real, -Im)
return complex( -Real, - Im );
}
complex complex::operator + (const complex& Y) {
// returns the value complex(Real + Y.Real, Im + Y.Im)
complex temp;
temp.Real = Real+Y.Real;
temp.Im = Im + Y.Im;
return temp
}
14
complex complex::operator - (const complex& Y)
{
complex temp;
temp.Real = Real - Y.Real;
temp.Im = Im - Y.Im;
return temp
}
Client code
….
complex A(2,3) , B(5, 7), C;
B = -A; equivalent to B = operator-(A);
C = A + B;
equivalent to C = A.operator+(B);
C = A - B;
equivalent to C = A.operator - (B);
15
Friend Functions/Operators
complex operator * (const double& c, const complex& X)
{
complex temp;
temp.Real = c* X.Real;
temp.Im = c * X.Im;
return temp
}





A friend function is a function defined outside of the class scope.
Note: there is no scope resolution
It is a friend function because in the class specification the keyword
“friend” is used in the prototype
A friend function of a class has access to the private members of the
class
Inside the function definition, the dot operator is required to access
the class data members.
Note that for a binary operation, two arguments are required
16
Overloaded Stream Input
Operator >>
istream& operator >> (istream& istr, complex& X)
{
// paramter istr represents an input stream such cin
// The two parameters are passed by reference because they are
// modified by the function
// The function returns a reference to an istream object so that input
// operations can be chained
istr >> X.Real >> X.Im ;
return istr ;
}
Example:
complex A, B ;
cin >> A >> B;
17
Overloaded Stream Output
Operator <<
ostream& operator << (ostream& ostr, const complex& X)
{
// The second parameter is passed by reference; but it is read-only
ostr << X.Real << X.Im ;
return ostr ;
}

Example: complex A, B;
……
cout << A << B;
18
Inheritance Hierarchy Among
Vehicles
vehicle
wheeled vehicle
car
two-door
boat
bicycle
four-door
Every car is a wheeled vehicle.
19
Inheritance

is a mechanism by which one class acquires
(inherits) the properties (both data and operations)
of another class

the class being inherited from is the Base Class
(Superclass)

the class that inherits is the Derived Class
(Subclass)

the derived class is then specialized by adding
properties specific to it
20
class Time Specification
// SPECIFICATION FILE
( time.h )
class Time
{
public :
void
void
void
Time ( int
Time ( ) ;
Set ( int hours , int minutes , int seconds ) ;
Increment ( ) ;
Write ( ) const ;
initHrs, int initMins, int initSecs ) ; // constructor
// default constructor
private :
int
int
int
};
hrs ;
mins ;
secs ;
21
21
Class Interface Diagram
Time class
Set
Increment
Private data:
hrs
Write
mins
Time
secs
Time
22
Using Inheritance to Add
Features
// SPECIFICATION FILE
( exttime.h)
#include “time.h”
enum ZoneType {EST, CST, MST, PST, EDT, CDT, MDT, PDT } ;
class ExtTime : public Time
// Time is the base class
{
public :
void
Set ( int hours, int minutes, int seconds ,
ZoneType timeZone ) ;
void
Write ( ) const ;
ExtTime ( int initHrs , int initMins , int initSecs ,
ZoneType initZone ) ;
// constructor
ExtTime ( ) ;
// default constructor
private :
ZoneType zone ;
};
// added data member
23 23
class ExtTime: public Time

says class Time is a public base class of the
derived class ExtTime

as a result, all public members of Time (except
constructors) are also public members of ExtTime

in this example, new constructors are provided,
new data member zone is added, and member
functions Set and Write are overridden
24
Class Interface Diagram
ExtTime class
Set
Set
Increment
Increment
Private data:
hrs
Write
Write
mins
ExtTime
Time
ExtTime
Time
secs
Private data:
zone
25
Client Code Using ExtTime
#include “exttime.h”
.
.
.
ExtTime
ExtTime
thisTime ( 8, 35, 0, PST ) ;
thatTime ;
// default constructor called
thatTime.Write( ) ;
cout << endl ;
// outputs 00:00:00 EST
thatTime.Set (16, 49, 23, CDT) ;
thatTime.Write( ) ;
// outputs 16:49:23 CDT
cout << endl ;
thisTime.Increment ( ) ;
thisTime.Increment ( ) ;
thisTime.Write ( ) ;
cout << endl ;
// outputs 08:35:02 PST
26
26
Constructor Rules for Derived Classes

at run time, the base class constructor is
implicitly called first, before the body of the
derived class’s constructor executes

if the base class constructor requires
parameters, they must be passed by the
derived class’s constructor
27
Implementation of ExtTime
Default Constructor
ExtTime :: ExtTime ( )
// Default Constructor
// Postcondition:
//
hrs == 0 && mins == 0 && secs == 0
//
(via an implicit call to base class default constructor )
//
{
&& zone == EST
zone = EST ;
}
28
Implementation of Another
ExtTime Class Constructor
ExtTime :: ExtTime ( /* in */
/* in */
/* in */
/* in */
int
initHrs,
int
initMins,
int
initSecs,
ZoneType initZone )
: Time (initHrs, initMins, initSecs) // constructor initializer
// Precondition: 0 <= initHrs <= 23 && 0 <= initMins <= 59
//
0 <= initSecs <= 59 && initZone is assigned
// Postcondition:
//
zone == initZone && Time set by base class constructor
{
zone = initZone ;
29
}
29
Implementation of
ExtTime::Set function
void ExtTime :: Set ( /* in */
/* in */
/* in */
/* in */
int
int
int
ZoneType
hours,
minutes,
seconds,
time Zone )
// Precondition: 0 <= hours <= 23 && 0 <= minutes <= 59
//
0 <= seconds <= 59 && timeZone is assigned
// Postcondition:
//
zone == timeZone && Time set by base class function
{
Time :: Set (hours, minutes, seconds);
zone = timeZone ;
}
30
30
Implementation of
ExtTime::Write Function
void ExtTime :: Write ( ) const
// Postcondition:
//
Time has been output in form HH:MM:SS ZZZ
//
where ZZZ is the time zone abbreviation
{
static string zoneString[8] =
{
“EST”, CST”, MST”, “PST”, “EDT”, “CDT”, “MDT”, “PDT”
};
Time :: Write ( ) ;
cout << ‘ ‘ << zoneString [zone] ;
}
31
31
Avoiding Multiple Inclusion of
Header Files

often several program files use the same header file
containing typedef statements, constants, or class
type declarations--but, it is a compile-time error to
define the same identifier twice

this preprocessor directive syntax is used to avoid
the compilation error that would otherwise occur from
multiple uses of #include for the same header file
#ifndef Preprocessor_Identifier
#define Preprocessor_Identifier
.
.
.
#endif
32
Composition (or Containment)

is a mechanism by which the internal
data (the state) of one class includes
an object of another class
33
A TimeCard object has a Time object
#include “time.h”
class TimeCard
{
public:
void Punch ( /* in */ int
/* in */ int
/* in */ int
void Print ( ) const ;
TimeCard ( /* in */ long
/* in */ int
/* in */ int
/* in */ int
TimeCard ( ) ;
private:
long id ;
Time timeStamp ;
};
hours,
minutes,
seconds ) ;
idNum,
initHrs,
initMins,
initSecs ) ;
34
TimeCard Class
TimeCard has a Time object
Private data:
Punch
id
timeStamp
Print
.
.
.
TimeCard
TimeCard
Set
Increment
Write
.
.
.
Private data:
hrs
mins
secs
35
Implementation of TimeCard
Class Constructor
TimeCard :: TimeCard ( /* in */
/* in */
/* in */
/* in */
long
int
int
int
idNum,
initHrs,
initMins,
initSecs )
: timeStamp (initHrs, initMins, initSecs)
// constructor initializer
// Precondition: 0 <= initHrs <= 23 && 0 <= initMins <= 59
//
0 <= initSecs <= 59 && initNum is assigned
// Postcondition:
//
id == idNum && timeStamp set by its constructor
{
id = idNum ;
}
36
36
Order in Which Constructors are
Executed
Given a class X,

if X is a derived class its base class constructor
is executed first

next, constructors for member objects (if any)
are executed (using their own default
constructors if none is specified)

finally, the body of X’s constructor is executed
37
In C++ . . .
When the type of a formal parameter is a
parent class, the argument used can be:
the same type as the formal parameter,
or,
any descendant class type.
38
Static Binding

is the compile-time determination of which
function to call for a particular object based on
the type of the formal parameter

when pass-by-value is used, static binding
occurs
39
Static Binding Is Based on Formal
Parameter Type
void Print ( /* in */ Time someTime )
{
cout << “Time is “ ;
someTime.Write ( ) ;
cout << endl ;
}
CLIENT CODE
Time
ExtTime
startTime ( 8, 30, 0 ) ;
endTime (10, 45, 0, CST) ;
OUTPUT
Time is 08:30:00
Time is 10:45:00
Print ( startTime ) ;
Print ( endTime ) ;
40
Dynamic Binding

is the run-time determination of which function to
call for a particular object of a descendant class
based on the type of the argument

declaring a member function to be virtual
instructs the compiler to generate code that
guarantees dynamic binding
41
Virtual Member Function
// SPECIFICATION FILE
( time.h )
class TimeType
{
public :
. . .
virtual void Write ( ) const ;
// for dynamic binding
. . .
private :
int
int
int
hrs ;
mins ;
secs ;
};
42
Dynamic binding requires
pass-by-reference
void Print ( /* in */ Time & someTime )
{
cout << “Time is “ ;
someTime.Write ( ) ;
cout << endl ;
}
CLIENT CODE
Time
ExtTime
startTime ( 8, 30, 0 ) ;
endTime (10, 45, 0, CST) ;
OUTPUT
Time is 08:30:00
Time is 10:45:00 CST
Print ( startTime ) ;
Print ( endTime ) ;
43
Using virtual functions in C++

dynamic binding requires pass-by-reference
when passing a class object to a function

in the declaration for a virtual function, the
word virtual appears only in the base class

if a base class declares a virtual function, it
must implement that function, even if the body
is empty

a derived class is not required to re-implement
a virtual function. If it does not, the base class
version is used
44