SlideShare a Scribd company logo
32
Most read
54
Most read
101
Most read
www.cyberlabzone.com
C++ Programming
Topics for C++ Language
1.Introduction to C++ language
2.Structured/OO Programming
3.Memory Concepts
4.Arithmetic
5.Control Structure
6.Functions
7.Arrays
8.Pointers
9.Structures
10.Inheritance
11.Polymorphism
12.Multiple Inheritance
13.Templetes
14.Stacks/Queue
15.Exception Handling
16.Preprocessing
17.Unified Modeling Language
Introduction to C++ language
Course Description
 An introduction to the development of programs using C++.
 Emphasis is given to the development of program modules that can function
independently.
 Object-oriented design
 The theory of data structures and programming language design is continued.
Course Information
Computer Languages
 Machine language
 Generally consist of strings of numbers - Ultimately 0s and 1s -
Machine-dependent
 Example: +1300042774
+1400593419
 Assembly language
 English-like abbreviations for elementary operations
 Incomprehensible to computers - Convert to machine language
 Example: LOAD BASEPAY
ADD OVERPAY
STORE GROSSPAY
 High-level languages
 Similar to everyday English, use common mathematical notations
 Compiler/Interpreter
 Example:
grossPay = basePay + overTimePay
History of C and C++
 History of C
 Evolved from two other programming languages
 BCPL and B: “Typeless” languages
 Dennis Ritchie (Bell Lab): Added typing, other features
 1989: ANSI standard/ ANSI/ISO 9899: 1990
 History of C++
 Early 1980s: Bjarne Stroustrup (Bell Lab)
 Provides capabilities for object-oriented programming
 Objects: reusable software components
 Object-oriented programs
 Building block approach” to creating programs
 C++ programs are built from pieces called classes and functions
 C++ standard library: Rich collections of existing classes and functions
Structured/OO Programming
 Structured programming (1960s)
 Disciplined approach to writing programs
 Clear, easy to test and debug, and easy to modify
 E.g.Pascal:1971: Niklaus Wirth
 OOP
 “Software reuse”
 “Modularity”
 “Extensible”
 More understandable, better organized and easier to maintain than procedural
programming
Basics of a Typical C++
Environment
 C++ systems
 Program-development environment
 Language
 C++ Standard Library
 C++ program names extensions
 .cpp
 .cxx
 .cc
 .C
Basics of a Typical C++
Environment
Phases of C++ Programs:
1. Edit
2. Preprocess
3. Compile
4. Link
5. Load
6. Execute
Loader
Primary
Memory
Program is created in
the editor and stored
on disk.
Preprocessor program
processes the code.
Loader puts program
in memory.
CPU takes each
instruction and
executes it, possibly
storing new data
values as the program
executes.
Compiler
Compiler creates
object code and stores
it on disk.
Linker links the object
code with the libraries,
creates an executable
file and stores it on disk
Editor
Preprocessor
Linker
CPU
Primary
Memory
.
.
.
.
.
.
.
.
.
.
.
.
Disk
Disk
Disk
Disk
Disk
Basics of a Typical C++
Environment
 Common Input/output functions
 cin
 Standard input stream
 Normally keyboard
 cout
 Standard output stream
 Normally computer screen
 cerr
 Standard error stream
 Display error messages
 Comments: C’s comment /* .. */ OR Begin with // or
 Preprocessor directives: Begin with #
 Processed before compiling
A Simple Program: Printing a
Line of Text
 Standard output stream object
 std::cout
 “Connected” to screen
 <<
 Stream insertion operator
 Value to right (right operand) inserted into output stream
 Namespace
 std:: specifies that entity belongs to “namespace” std
 std:: removed through use of using statements
 Escape characters: 
 Indicates “special” character output
1 // Example 1
2 // A first program in C++.
3 #include <iostream>
4
5 // function main begins program execution
6 int main()
7 {
8 std::cout << "Welcome to C++!n";
9
10 return 0; // indicate that program ended successfully
11
12 } // end function main
Welcome to C++!
A Simple Program: Printing a
Line of Text
Escape Sequence Description
n Newline. Position the screen cursor to the
beginning of the next line.
t Horizontal tab. Move the screen cursor to the next
tab stop.
r Carriage return. Position the screen cursor to the
beginning of the current line; do not advance to the
next line.
a Alert. Sound the system bell.
 Backslash. Used to print a backslash character.
" Double quote. Used to print a double quote
character.
Memory Concepts
 Variable names
 Correspond to actual locations in computer's memory
 Every variable has name, type, size and value
 When new value placed into variable, overwrites previous value
 std::cin >> integer1;
 Assume user entered 45
 std::cin >> integer2;
 Assume user entered 72
 sum = integer1 + integer2;
integer1 45
integer1 45
integer2 72
integer1 45
integer2 72
sum 117
Arithmetic
 Arithmetic calculations
 * : Multiplication
 / : Division
 Integer division truncates remainder
7 / 5 evaluates to 1
 % : Modulus operator returns remainder
7 % 5 evaluates to 2
Operator(s) Operation(s) Order of evaluation (precedence)
() Parentheses Evaluated first. If the parentheses are nested, the
expression in the innermost pair is evaluated first. If
there are several pairs of parentheses “on the same level”
(i.e., not nested), they are evaluated left to right.
*, /, or % Multiplication Division
Modulus
Evaluated second. If there are several, they re
evaluated left to right.
+ or - Addition
Subtraction
Evaluated last. If there are several, they are
evaluated left to right.
Decision Making: Equality and
Relational Operators
 if structure
 Make decision based on truth or falsity of condition
 If condition met, body executed
 Else, body not executed
 Equality and relational operators
 Equality operators
 Same level of precedence
 Relational operators
 Same level of precedence
 Associate left to right
Decision Making: Equality and
Relational Operators
Standard algebraic
equality operator or
relational operator
C++ equality
or relational
operator
Example
of C++
condition
Meaning of
C++ condition
Relational operators
> > x > y x is greater than y
< < x < y x is less than y
 >= x >= y x is greater than or equal to y
 <= x <= y x is less than or equal to y
Equality operators
= == x == y x is equal to y
 != x != y x is not equal to y
Algorithms /pseudocode
 Computing problems
 Solved by executing a series of actions in a specific order
 Algorithm: a procedure determining
 Actions to be executed
 Order to be executed
 Example: recipe
 Program control
 Specifies the order in which statements are executed
 Pseudocode
 Artificial, informal language used to develop algorithms
 Similar to everyday English
Control Structures
 Sequential execution
 Statements executed in order
 Transfer of control
 Next statement executed not next one in sequence
 Structured programming – “goto”-less programming
 3 control structures to build any program
 Sequence structure
 Programs executed sequentially by default
 Selection structures
 if, if/else, switch
 Repetition structures
 while, do/while, for
Keywords
 C++ keywords
 Cannot be used as identifiers or variable names
C++ Keywords
Keywords common to the
C and C++ programming
languages
auto break case char const
continue default do double else
enum extern float for goto
if int long register return
short signed sizeof static struct
switch typedef union unsigned void
volatile while
C++ only keywords
asm bool catch class const_cast
delete dynamic_cast explicit false friend
inline mutable namespace new operator
private protected public reinterpret_cast
static_cast template this throw true
try typeid typename using virtual
wchar_t
Control Structures
 Flowchart
 Graphical representation of an algorithm
 Special-purpose symbols connected by arrows (flowlines)
 Rectangle symbol (action symbol)
 Any type of action
 Oval symbol
 Beginning or end of a program, or a section of code (circles)
Exercise: Find greater of three numbers
if/else Selection Structure
 Ternary conditional operator (?:)
 Three arguments (condition, value if true, value if false)
 Code could be written:
cout << ( grade >= 60 ? “Passed” : “Failed” );
truefalse
print “Failed” print “Passed”
grade >= 60
Condition Value if true Value if false
while Repetition Structure
 Repetition structure
 Counter-controlled
 While/do while loop: repeated until condition becomes false
 For: loop repeated until counter reaches certain value Flowchart
representation?
 Sentinel value
 Indicates “end of data entry”
 Sentinel chosen so it cannot be confused with regular input
 Example
int product = 2;
while ( product <= 1000 ) {
product = 2 * product;
cout << product;
}
Flowchart representation?
What is the output?
switch Multiple-Selection
Structure
 switch
 Test variable for multiple values
 Series of case labels and optional default case
switch ( variable ) {
case value1: // taken if variable == value1
statements
break; // necessary to exit switch
case value2:
case value3: // taken if variable == value2 or == value3
statements
break;
default: // taken if none matches
statements
break;
}
break and continue Statements
 break statement
 Immediate exit from while, for, do/while, switch
 Program continues with first statement after structure
 Common uses
 Escape early from a loop
 Skip the remainder of switch
Logical Operators
 Used as conditions in loops, if statements
 && (logical AND)
 true if both conditions are true
if ( gender == 1 && age >= 65 )
++seniorFemales;
 || (logical OR)
 true if either of condition is true
if ( semesterAverage >= 90 || finalExam >= 90 )
cout << "Student grade is A" << endl;
Logical Operators
 ! (logical NOT, logical negation)
 Returns true when its condition is false, & vice versa
if ( !( grade == sentinelValue ) )
cout << "The next grade is " << grade << endl;
Alternative:
if ( grade != sentinelValue )
cout << "The next grade is " << grade << endl;
Confusing Equality (==) and Assignment (=)
Operators
 Common error
 Does not typically cause syntax errors
 Aspects of problem
 Expressions that have a value can be used for decision
 Zero = false, nonzero = true
 Assignment statements produce a value (the value to be assigned)
if == was replaced with =
if ( payCode = 4 )
cout << "You get a bonus!" << endl;
What happens?
Confusing Equality (==) and Assignment (=)
Operators
 Lvalues
 Expressions that can appear on left side of equation
 Can be changed
x = 4;
 Rvalues
 Only appear on right side of equation
 Constants, such as numbers (i.e. cannot write 4 = x;)
 Lvalues can be used as rvalues, but not vice versa
Structured-Programming Summary
 Structured programming
 Programs easier to understand, test, debug and modify
 Rules for structured programming
 Only use single-entry/single-exit control structures
 Rules
1) Begin with the “simplest flowchart”
2) Any rectangle (action) can be replaced by two rectangles (actions) in sequence
3) Any rectangle (action) can be replaced by any control structure (sequence, if,
if/else, switch, while, do/while or for)
4) Rules 2 and 3 can be applied in any order and multiple times
Structured-Programming Summary
Representation of Rule 3 (replacing any rectangle with a control structure)
Rule 3
Rule 3Rule 3
Program Components in C++
 Modules: functions and classes
 Programs use new and “prepackaged” modules
 New: programmer-defined functions, classes
 Prepackaged: from the standard library
 Functions invoked by function call
 Function name and information (arguments) it needs
 Function definitions
 Only written once
 Hidden from other functions
Functions
 Functions
 Modularize a program
 Software reusability
 Call function multiple times
 Local variables
 Known only in the function in which they are defined
 All variables declared in function definitions are local variables
 Parameters
 Local variables passed to function when called
 Provide outside information
Math Library Functions
Perform common mathematical calculations
Include the header file <cmath>
Functions called by writing
functionName (argument); or
functionName (argument1, argument2, …);
Example
cout << sqrt( 900.0 );
All functions in math library return a double
Function arguments can be
Constants: sqrt( 4 );
Variables: sqrt( x );
Expressions:
 sqrt( sqrt( x ) ) ;
 sqrt( 3 - 6x );
Other functions
 ceil(x), floor(x), log10(x), etc.
Function Definitions
Function prototype
int square( int );
Calling/invoking a function
square(x);
Format for function definition
return-value-type function-name( parameter-list )
{
declarations and statements
}
Prototype must match function definition
Function prototype
double maximum( double, double, double );
Definition
double maximum( double x, double y, double z )
{
…
}
Function Definitions
 Example function
int square( int y )
{
return y * y;
}
 return keyword
 Returns data, and control goes to function’s caller
 If no data to return, use return;
 Function ends when reaches right brace
 Control goes to caller
 Functions cannot be defined inside other functions
Function Prototypes
 Function signature
 Part of prototype with name and parameters
 double maximum( double, double, double );
 Argument Coercion
 Force arguments to be of proper type
 Converting int (4) to double (4.0)
cout << sqrt(4)
 Conversion rules
 Arguments usually converted automatically
 Changing from double to int can truncate data
3.4 to 3
 Mixed type goes to highest type (promotion)
Function signature
Function Prototypes
Data types
long double
double
float
unsigned long int (synonymous with unsigned long)
long int (synonymous with long)
unsigned int (synonymous with unsigned)
int
unsigned short int (synonymous with unsigned short)
short int (synonymous with short)
unsigned char
char
bool (false becomes 0, true becomes 1)
Fig. 3.5 Promotion hierarc hy for built-in data types.
Header Files
 Header files contain
 Function prototypes
 Definitions of data types and constants
 Header files ending with .h
 Programmer-defined header files
#include “myheader.h”
 Library header files
#include <cmath>
Enumeration: enum
 Enumeration
 Set of integers with identifiers
enum typeName {constant1, constant2…};
 Constants start at 0 (default), incremented by 1
 Constants need unique names
 Cannot assign integer to enumeration variable
 Must use a previously defined enumeration type
 Example
enum Status {CONTINUE, WON, LOST};
Status enumVar;
enumVar = WON; // cannot do enumVar = 1
Storage Classes
 Variables have attributes
 Have seen name, type, size, value
 Storage class
 How long variable exists in memory
 Scope
 Where variable can be referenced in program
 Linkage
 For multiple-file program which files can use it
Storage Classes
 Automatic storage class
 Variable created when program enters its block
 Variable destroyed when program leaves block
 Only local variables of functions can be automatic
 Automatic by default
 keyword auto explicitly declares automatic
 register keyword
 Hint to place variable in high-speed register
 Good for often-used items (loop counters)
 Often unnecessary, compiler optimizes
 Specify either register or auto, not both
 register int counter = 1;
Storage Classes
 Static storage class
 Variables exist for entire program
 For functions, name exists for entire program
 May not be accessible, scope rules still apply
 auto and register keyword
 local variables in function
 register variables are kept in CPU registers
 static keyword
 Local variables in function
 Keeps value between function calls
 Only known in own function
 extern keyword
 Default for global variables/functions
 Globals: defined outside of a function block
 Known in any function that comes after it
Scope Rules
 Scope
 Portion of program where identifier can be used
 File scope
 Defined outside a function, known in all functions
 Global variables, function definitions and prototypes
 Function scope
 Can only be referenced inside defining function
 Only labels, e.g., identifiers with a colon (case:)
Scope Rules
 Block scope
 Begins at declaration, ends at right brace }
 Can only be referenced in this range
 Local variables, function parameters
 Local static variables still have block scope
 Storage class separate from scope
 Function-prototype scope
 Parameter list of prototype
 Names in prototype optional
 Compiler ignores
 In a single prototype, name can be used once
1 // Example 2
2 // A scoping example.
3 #include <iostream>
4
5 using std::cout;
6 using std::endl;
7
8 void useLocal( void ); // function prototype
9 void useStaticLocal( void ); // function prototype
10 void useGlobal( void ); // function prototype
11
12 int x = 1; // global variable
13
14 int main()
15 {
16 int x = 5; // local variable to main
17
18 cout << "local x in main's outer scope is " << x << endl;
19
20 { // start new scope
21
22 int x = 7;
23
24 cout << "local x in main's inner scope is " << x << endl;
25
26 } // end new scope
Local/global? Scope?
Local/global? Scope?
Local/global? Scope?
43 // useLocal reinitializes local variable x during each call
44 void useLocal( void )
45 {
46 int x = 25; // initialized each time useLocal is called
47
48 cout << endl << "local x is " << x
49 << " on entering useLocal" << endl;
50 ++x;
51 cout << "local x is " << x
52 << " on exiting useLocal" << endl;
53
54 } // end function useLocal
55
Local/global? Scope?
56 // useStaticLocal initializes static local variable x only the
57 // first time the function is called; value of x is saved
58 // between calls to this function
59 void useStaticLocal( void )
60 {
61 // initialized only first time useStaticLocal is called
62 static int x = 50;
63
64 cout << endl << "local static x is " << x
65 << " on entering useStaticLocal" << endl;
66 ++x;
67 cout << "local static x is " << x
68 << " on exiting useStaticLocal" << endl;
69
70 } // end function useStaticLocal
71
Local/global? Scope?
Recursion
 Recursive functions
 Functions that call themselves
 Can only solve a base case
 If not base case
 Break problem into smaller problem(s)
 Launch new copy of function to work on the smaller problem (recursive call/recursive
step)
 Slowly converges towards base case
 Function makes call to itself inside the return statement
 Eventually base case gets solved
 Answer works way back up, solves entire problem
Recursion
 Example: factorial
n! = n * ( n – 1 ) * ( n – 2 ) * … * 1
 Recursive relationship ( n! = n * ( n – 1 )! )
5! = 5 * 4!
4! = 4 * 3!…
 Base case (1! = 0! = 1)
Example Using Recursion:
Fibonacci Series
 Fibonacci series: 0, 1, 1, 2, 3, 5, 8...
 Each number sum of two previous ones
 Example of a recursive formula:
 fib(n) = fib(n-1) + fib(n-2)
 C++ code for Fibonacci function
long fibonacci( long n )
{
if ???? // base case
return ???;
else
???
}
Example Using Recursion:
Fibonacci Series
 Order of operations
 return fibonacci( n - 1 ) + fibonacci( n - 2 );
 Recursive function calls
 Each level of recursion doubles the number of function calls
 30th number = 2^30 ~ 4 billion function calls
 Exponential complexity
f( 3 )
f( 1 )f( 2 )
f( 1 ) f( 0 ) return 1
return 1 return 0
return +
+return
Recursion vs. Iteration
 Repetition
 Iteration: explicit loop
 Recursion: repeated function calls
 Termination
 Iteration: loop condition fails
 Recursion: base case recognized
 Both can have infinite loops
 Balance between performance (iteration) and good software engineering (recursion)
Inline Functions
 Inline functions
 Keyword inline before function
 Asks the compiler to copy code into program instead of making function call
 Reduce function-call overhead
 Compiler can ignore inline
 Good for small, often-used functions
 Example
inline double cube( const double s )
{ return s * s * s; }
 const tells compiler that function does not modify s
References and Reference
Parameters
 Call by value
 Copy of data passed to function
 Changes to copy do not change original
 Prevent unwanted side effects
 Call by reference
 Function can directly access data
 Changes affect original
 Reference parameter
 Alias for argument in function call
 Passes parameter by reference
 Use & after data type in prototype
 void myFunction( int &data )
 Read “data is a reference to an int”
 Function call format the same
 However, original can now be changed
References and Reference
Parameters
 Pointers
 Another way to pass-by-refernce
 References as aliases to other variables
 Refer to same variable
 Can be used within a function
int count = 1; // declare integer variable count
int &cRef = count; // create cRef as an alias for count
++cRef; // increment count (using its alias)
 References must be initialized when declared
 Otherwise, compiler error
 Dangling reference
 Reference to undefined variable
Default Arguments
 Function call with omitted parameters
 If not enough parameters, rightmost go to their defaults
 Default values
 Can be constants, global variables, or function calls
 Set defaults in function prototype
int myFunction( int x = 1, int y = 2, int z = 3 );
 myFunction(3)
 x = 3, y and z get defaults (rightmost)
 myFunction(3, 5)
 x = 3, y = 5 and z gets default
Unitary Scope Resolution
Operator
 Unary scope resolution operator (::)
 Access global variable if local variable has same name
 Not needed if names are different
 Use ::variable
 y = ::x + 3;
 Good to avoid using same names for locals and globals
Function Overloading
 Function overloading
 Functions with same name and different parameters
 Should perform similar tasks
 i.e., function to square ints and function to square floats
int square( int x) {return x * x;}
float square(float x) { return x * x; }
 Overloaded functions distinguished by signature
 Based on name and parameter types (order matters)
 Name mangling
 Encode function identifier with no. and types of parameters
 Type-safe linkage
 Ensures proper overloaded function called
Function Templates
 Compact way to make overloaded functions
 Generate separate function for different data types
 Format
 Begin with keyword template
 Formal type parameters in brackets <>
 Every type parameter preceded by typename or class (synonyms)
 Placeholders for built-in types (i.e., int) or user-defined types
 Specify arguments types, return types, declare variables
 Function definition like normal, except formal types used
Function Templates
 Example
template < class T > // or template< typename T >
T square( T value1 )
{
return value1 * value1;
}
 T is a formal type, used as parameter type
 Above function returns variable of same type as parameter
 In function call, T replaced by real type
 If int, all T's become ints
int x;
int y = square(x);
1 // Example 3
2 // Using a function template.
3 #include <iostream>
4
5 using std::cout;
6 using std::cin;
7 using std::endl;
8
9 // definition of function template maximum
10 template < class T > // or template < typename T >
11 T maximum( T value1, T value2, T value3 )
12 {
13 T max = value1;
14
15 if ( value2 > max )
16 max = value2;
17
18 if ( value3 > max )
19 max = value3;
20
21 return max;
22
23 } // end function template maximum
24
Formal type parameter T
placeholder for type of data to
be tested by maximum.
maximum expects all
parameters to be of the same
type.
25 int main()
26 {
27 // demonstrate maximum with int values
28 int int1, int2, int3;
29
30 cout << "Input three integer values: ";
31 cin >> int1 >> int2 >> int3;
32
33 // invoke int version of maximum
34 cout << "The maximum integer value is: "
35 << maximum( int1, int2, int3 );
36
37 // demonstrate maximum with double values
38 double double1, double2, double3;
39
40 cout << "nnInput three double values: ";
41 cin >> double1 >> double2 >> double3;
42
43 // invoke double version of maximum
44 cout << "The maximum double value is: "
45 << maximum( double1, double2, double3 );
46
maximum called with various
data types.
47 // demonstrate maximum with char values
48 char char1, char2, char3;
49
50 cout << "nnInput three characters: ";
51 cin >> char1 >> char2 >> char3;
52
53 // invoke char version of maximum
54 cout << "The maximum character value is: "
55 << maximum( char1, char2, char3 )
56 << endl;
57
58 return 0; // indicates successful termination
59
60 } // end main
Input three integer values: 1 2 3
The maximum integer value is: 3
Input three double values: 3.3 2.2 1.1
The maximum double value is: 3.3
Input three characters: A C B
The maximum character value is: C
Arrays
 Array
 Consecutive group of memory locations
 Same name and type (int, char, etc.)
 To refer to an element
 Specify array name and position number (index)
 Format: arrayname[ position number ]
 First element at position 0
 N-element array c
c[ 0 ], c[ 1 ] … c[ n - 1 ]
 Nth element as position N-1
Declaring Arrays
 When declaring arrays, specify
 Name
 Type of array
 Any data type
 Number of elements
 type arrayName[ arraySize ];
int c[ 10 ]; // array of 10 integers
float d[ 3284 ]; // array of 3284 floats
 Declaring multiple arrays of same type
 Use comma separated list, like regular variables
int b[ 100 ], x[ 27 ];
Examples Using Arrays
 Initializing arrays
 For loop
 Set each element
 Initializer list
 Specify each element when array declared
int n[ 5 ] = { 1, 2, 3, 4, 5 };
 If not enough initializers, rightmost elements 0
 If too many, syntax error
 To set every element to 0
int n[ 5 ] = { 0 };
 If array size omitted, initializers determine size
int n[] = { 1, 2, 3, 4, 5 };
 5 initializers, therefore 5 element array
 static int array[3]; ??
Examples Using Arrays
 Strings
 Arrays of characters
 All strings end with null ('0')
 Examples
 char string1[] = "hello";
Null character implicitly added
string1 has 6 elements
 char string1[] = { 'h', 'e', 'l', 'l', 'o', '0’ };
 Subscripting is the same
String1[ 0 ] is 'h'
string1[ 2 ] is 'l'
Examples Using Arrays
 Input from keyboard
char string2[ 10 ];
cin >> string2;
 Puts user input in string
 Stops at first whitespace character
 Adds null character
 If too much text entered, data written beyond array
 We want to avoid this
 Printing strings
 cout << string2 << endl;
 Does not work for other array types
 Characters printed until null found
Passing Arrays to Functions
 Specify name without brackets
 To pass array myArray to myFunction
int myArray[ 24 ];
myFunction( myArray, 24 );
 Array size usually passed, but not required
 Useful to iterate over all elements
 Arrays passed-by-reference
 Functions can modify original array data
 Value of name of array is address of first element
 Function knows where the array is stored
 Can change original memory locations
Passing Arrays to Functions
 Functions taking arrays
 Function prototype
 void modifyArray( int b[], int arraySize );
 void modifyArray( int [], int );
Names optional in prototype
 Both take an integer array and a single integer
 No need for array size between brackets
 Ignored by compiler
 If declare array parameter as const
 Cannot be modified (compiler error)
 void doNotModify( const int [] );
Sorting Arrays
 Example:
 Go left to right, and exchange elements as necessary
 One pass for each element
 Original: 3 4 2 7 6
 Pass 1: 3 2 4 6 7 (elements exchanged)
 Pass 2: 2 3 4 6 7
 Pass 3: 2 3 4 6 7 (no changes needed)
 Pass 4: 2 3 4 6 7
 Pass 5: 2 3 4 6 7
 Small elements "bubble" to the top (like 2 in this example)
Multiple-Subscripted Arrays
Multiple subscripts
a[ i ][ j ]
Tables with rows and columns
Specify row, then column
“Array of arrays”
 a[0] is an array of 4 elements
 a[0][0] is the first element of
that array
Row 0
Row 1
Row 2
Column 0 Column 1 Column 2 Column 3
a[ 0 ][ 0 ]
a[ 1 ][ 0 ]
a[ 2 ][ 0 ]
a[ 0 ][ 1 ]
a[ 1 ][ 1 ]
a[ 2 ][ 1 ]
a[ 0 ][ 2 ]
a[ 1 ][ 2 ]
a[ 2 ][ 2 ]
a[ 0 ][ 3 ]
a[ 1 ][ 3 ]
a[ 2 ][ 3 ]
Row subscript
Array name
Column subscript
To initialize
Default of 0
Initializers grouped by row in
braces
int b[ 2 ][ 2 ]={ { 1, 2 }, { 3, 4 } };
int b[ 2 ][ 2 ] = { { 1 }, { 3, 4 } };
Pointer
 Pointer variables
 Contain memory addresses as values
 Normally, variable contains specific value (direct reference)
 Pointers contain address of variable that has specific value (indirect reference)
 Indirection
 Referencing value through pointer
 Pointer declarations
 * indicates variable is pointer
int *myPtr;
declares pointer to int, pointer of type int *
 Multiple pointers require multiple asterisks
int *myPtr1, *myPtr2;
count
7
countPtr count
7
Pointer Variable Declarations and Initialization
Pointer Operators
 & (address operator)
 Returns memory address of its
operand
 Example
int y = 5;
int *yPtr;
yPtr = &y;
yPtr
y
5
yptr
500000 600000
y
600000 5
address of y
is value of
yptr
yPtr “points to” y
* - indirection/
dereferencing operator)
*yPtr returns y
dereferenced pointer is
lvalue
*yptr = 9 ??
Calling Functions by Reference
 3 ways to pass arguments to function
 Pass-by-value
 Pass-by-reference with reference arguments
 Pass-by-reference with pointer arguments
 Arguments passed to function using reference arguments
 Modify original values of arguments
 More than one value “returned”
int Cube(int *x) { …}
Function call: Cube(&a)
Using const with Pointers
const qualifier
Value of variable should not be modified
const used when function does not need to change a variable
Principle of least privilege
const pointers
Always point to same memory location
Default for array name
Must be initialized when declared
Four ways to pass pointer to function
Nonconstant pointer to nonconstant data
 Highest amount of access
Nonconstant pointer to constant data
Constant pointer to nonconstant data
Constant pointer to constant data
 Least amount of access
1 // Example 3
2 // Attempting to modify a constant pointer to
3 // non-constant data.
4
5 int main()
6 {
7 int x, y;
8
9 // ptr is a constant pointer to an integer that can
10 // be modified through ptr, but ptr always points to the
11 // same memory location.
12 int * const ptr = &x;
13
14 *ptr = 7; // allowed: *ptr is not const
15 ptr = &y; // error: ptr is const; cannot assign new address
16
17 return 0; // indicates successful termination
18
19 } // end main
d:cpphtp4_examplesch05Fig05_13.cpp(15) : error C2166:
l-value specifies const object
ptr is constant pointer to
integer.Can modify x (pointed to by
ptr) since x not constant.Cannot modify ptr to point
to new address since ptr is
constant.
Line 15 generates compiler
error by attempting to assign
new address to constant
pointer.
1 // Example 4
2 // Attempting to modify a constant pointer to constant data.
3 #include <iostream>
4
5 using std::cout;
6 using std::endl;
7
8 int main()
9 {
10 int x = 5, y;
11
12 // ptr is a constant pointer to a constant integer.
13 // ptr always points to the same location; the integer
14 // at that location cannot be modified.
15 const int *const ptr = &x;
16
17 cout << *ptr << endl;
18
19 *ptr = 7; // error: *ptr is const; cannot assign new value
20 ptr = &y; // error: ptr is const; cannot assign new address
21
22 return 0; // indicates successful termination
23
24 } // end main
ptr is constant pointer to
integer constant.
Cannot modify x (pointed to
by ptr) since *ptr declared
constant.
Cannot modify ptr to point
to new address since ptr is
constant.
Pointer Expressions and Pointer
Arithmetic
Pointer arithmetic
 Increment/decrement pointer (++ or --)
 Add/subtract an integer to/from a pointer( + or += , - or -=)
 Pointers may be subtracted from each other
 Pointer arithmetic meaningless unless performed on pointer to array
5 element int array on a machine using 4 byte ints
 vPtr points to first element v[ 0 ], which is at location 3000
vPtr = 3000
 vPtr += 2; sets vPtr to 3008
vPtr points to v[ 2 ]
pointer variable vPtr
v[0] v[1] v[2] v[4]v[3]
3000 3004 3008 3012 3016
location
Pointer Expressions and Pointer
Arithmetic
 Subtracting pointers
 Returns number of elements between two addresses
vPtr2 = v[ 2 ];
vPtr = v[ 0 ];
vPtr2 - vPtr == 2
 Pointer assignment
 Pointer can be assigned to another pointer if both of same type
 If not same type, cast operator must be used
 Exception: pointer to void (type void *)
 Generic pointer, represents any type
 No casting needed to convert pointer to void pointer
 void pointers cannot be dereferenced
Pointer Expressions and Pointer
Arithmetic
 Pointer comparison
 Use equality and relational operators
 Comparisons meaningless unless pointers point to members of same array
 Compare addresses stored in pointers
 Example: could show that one pointer points to higher numbered element of array
than other pointer
 Common use to determine whether pointer is 0 (does not point to anything)
Relationship Between Pointers
and Arrays
 Arrays and pointers closely related
 Array name like constant pointer
 Pointers can do array subscripting operations
 Accessing array elements with pointers
 Element b[ n ] can be accessed by *( bPtr + n )
 Called pointer/offset notation
 Addresses
 &b[ 3 ] same as bPtr + 3
 Array name can be treated as pointer
 b[ 3 ] same as *( b + 3 )
 Pointers can be subscripted (pointer/subscript notation)
 bPtr[ 3 ] same as b[ 3 ]
Arrays of Pointers
 Arrays can contain pointers
 Commonly used to store array of strings
char *suit[ 4 ] = {"Hearts", "Diamonds",
"Clubs", "Spades" };
 Each element of suit points to char * (a string)
 Array does not store strings, only pointers to strings
 suit array has fixed size, but strings can be of any size
suit[3]
suit[2]
suit[1]
suit[0] ’H’ ’e’ ’a’ ’r’ ’t’ ’s’ ’0’
’D’ ’i’ ’a’ ’m’ ’o’ ’n’ ’d’ ’s’ ’0’
’C’ ’l’ ’u’ ’b’ ’s’ ’0’
’S’ ’p’ ’a’ ’d’ ’e’ ’s’ ’0’
Function Pointers
 Calling functions using pointers
 Assume parameter:
 bool ( *compare ) ( int, int )
 Execute function with either
 ( *compare ) ( int1, int2 )
Dereference pointer to function to execute
OR
 compare( int1, int2 )
Could be confusing
 User may think compare name of actual function in program
1 // Example 5
2 // Multipurpose sorting program using function pointers.
3 #include <iostream>
4
5 using std::cout;
6 using std::cin;
7 using std::endl;
8
9 #include <iomanip>
10
11 using std::setw;
12
13 // prototypes
14 void bubble( int [], const int, bool (*)( int, int ) );
15 void swap( int * const, int * const );
16 bool ascending( int, int );
17 bool descending( int, int );
18
19 int main()
20 {
21 const int arraySize = 10;
22 int order;
23 int counter;
24 int a[ arraySize ] = { 2, 6, 4, 8, 10, 12, 89, 68, 45, 37 };
25
Parameter is pointer to
function that receives two
integer parameters and returns
bool result.
26 cout << "Enter 1 to sort in ascending order,n"
27 << "Enter 2 to sort in descending order: ";
28 cin >> order;
29 cout << "nData items in original ordern";
30
31 // output original array
32 for ( counter = 0; counter < arraySize; counter++ )
33 cout << setw( 4 ) << a[ counter ];
34
35 // sort array in ascending order; pass function ascending
36 // as an argument to specify ascending sorting order
37 if ( order == 1 ) {
38 bubble( a, arraySize, ascending );
39 cout << "nData items in ascending ordern";
40 }
41
42 // sort array in descending order; pass function descending
43 // as an agrument to specify descending sorting order
44 else {
45 bubble( a, arraySize, descending );
46 cout << "nData items in descending ordern";
47 }
48
49 // output sorted array
50 for ( counter = 0; counter < arraySize; counter++ )
51 cout << setw( 4 ) << a[ counter ];
52
53 cout << endl;
54
55 return 0; // indicates successful termination
56
57 } // end main
58
59 // multipurpose bubble sort; parameter compare is a pointer to
60 // the comparison function that determines sorting order
61 void bubble( int work[], const int size,
62 bool (*compare)( int, int ) )
63 {
64 // loop to control passes
65 for ( int pass = 1; pass < size; pass++ )
66
67 // loop to control number of comparisons per pass
68 for ( int count = 0; count < size - 1; count++ )
69
70 // if adjacent elements are out of order, swap them
71 if ( (*compare)( work[ count ], work[ count + 1 ] ) )
72 swap( &work[ count ], &work[ count + 1 ] );
compare is pointer to
function that receives two
integer parameters and returns
bool result.
Parentheses necessary to
indicate pointer to function
Call passed function
compare; dereference
pointer to execute function.
73
74 } // end function bubble
75
76 // swap values at memory locations to which
77 // element1Ptr and element2Ptr point
78 void swap( int * const element1Ptr, int * const element2Ptr )
79 {
80 int hold = *element1Ptr;
81 *element1Ptr = *element2Ptr;
82 *element2Ptr = hold;
83
84 } // end function swap
85
86 // determine whether elements are out of order
87 // for an ascending order sort
88 bool ascending( int a, int b )
89 {
90 return b < a; // swap if b is less than a
91
92 } // end function ascending
93
94 // determine whether elements are out of order
95 // for a descending order sort
96 bool descending( int a, int b )
97 {
98 return b > a; // swap if b is greater than a
99
100 } // end function descending
Enter 1 to sort in ascending order,
Enter 2 to sort in descending order: 1
Data items in original order
2 6 4 8 10 12 89 68 45 37
Data items in ascending order
2 4 6 8 10 12 37 45 68 89
Enter 1 to sort in ascending order,
Enter 2 to sort in descending order: 2
Data items in original order
2 6 4 8 10 12 89 68 45 37
Data items in descending order
89 68 45 37 12 10 8 6 4 2
Function Pointers
 Arrays of pointers to functions
 Menu-driven systems
 Pointers to each function stored in array of pointers to functions
 All functions must have same return type and same parameter types
 Menu choice  subscript into array of function pointers
1 // Example 6
2 // Demonstrating an array of pointers to functions.
3 #include <iostream>
4
5 using std::cout;
6 using std::cin;
7 using std::endl;
8
9 // function prototypes
10 void function1( int );
11 void function2( int );
12 void function3( int );
13
14 int main()
15 {
16 // initialize array of 3 pointers to functions that each
17 // take an int argument and return void
18 void (*f[ 3 ])( int ) = { function1, function2, function3 };
19
20 int choice;
21
22 cout << "Enter a number between 0 and 2, 3 to end: ";
23 cin >> choice;
24
Array initialized with names
of three functions; function
names are pointers.
25 // process user's choice
26 while ( choice >= 0 && choice < 3 ) {
27
28 // invoke function at location choice in array f
29 // and pass choice as an argument
30 (*f[ choice ])( choice );
31
32 cout << "Enter a number between 0 and 2, 3 to end: ";
33 cin >> choice;
34 }
35
36 cout << "Program execution completed." << endl;
37
38 return 0; // indicates successful termination
39
40 } // end main
41
42 void function1( int a )
43 {
44 cout << "You entered " << a
45 << " so function1 was callednn";
46
47 } // end function1
48
Call chosen function by
dereferencing corresponding
element in array.
25 // process user's choice
26 while ( choice >= 0 && choice < 3 ) {
27
28 // invoke function at location choice in array f
29 // and pass choice as an argument
30 (*f[ choice ])( choice );
31
32 cout << "Enter a number between 0 and 2, 3 to end: ";
33 cin >> choice;
34 }
35
36 cout << "Program execution completed." << endl;
37
38 return 0; // indicates successful termination
39
40 } // end main
41
42 void function1( int a )
43 {
44 cout << "You entered " << a
45 << " so function1 was callednn";
46
47 } // end function1
48
Call chosen function by
dereferencing corresponding
element in array.
Fundamentals of Characters and
Strings
 Character constant
 Integer value represented as character in single quotes
 'z' is integer value of z
 122 in ASCII
 String
 Series of characters treated as single unit
 Can include letters, digits, special characters +, -, * ...
 String literal (string constants)
 Enclosed in double quotes, for example:
"I like C++"
 Array of characters, ends with null character '0'
 String is constant pointer
 Pointer to string’s first character
Like arrays
Fundamentals of Characters and Strings
 String assignment
 Character array
 char color[] = "blue";
Creates 5 element char array color
 last element is '0'
 Variable of type char *
 char *colorPtr = "blue";
Creates pointer colorPtr to letter b in string “blue”
 “blue” somewhere in memory
 Alternative for character array
 char color[] = { ‘b’, ‘l’, ‘u’, ‘e’, ‘0’ };
Fundamentals of Characters and Strings
 Reading strings
 Assign input to character array word[ 20 ]
cin >> word
 Reads characters until whitespace or EOF
 String could exceed array size
cin >> setw( 20 ) >> word;
 Reads 19 characters (space reserved for '0')
Fundamentals of Characters and Strings
 cin.getline
 Read line of text
 cin.getline( array, size, delimiter );
 Copies input into specified array until either
 One less than size is reached
 delimiter character is input
 Example
char sentence[ 80 ];
cin.getline( sentence, 80, 'n' );
String Manipulation Functions of the String-
handling Library
 String handling library <cstring> provides functions to
 Manipulate string data
 Compare strings
 Search strings for characters and other strings
 Tokenize strings (separate strings into logical pieces)
String Manipulation Functions of the String-
handling Library
char *strcpy( char *s1,
const char *s2 );
Copies the string s2 into the character
array s1. The value of s1 is returned.
char *strncpy( char *s1,
const char *s2, size_t n );
Copies at most n characters of the string
s2 into the character array s1. The value
of s1 is returned.
char *strcat( char *s1,
const char *s2 );
Appends the string s2 to the string s1. The
first character of s2 overwrites the
terminating null character of s1. The value
of s1 is returned.
char *strncat( char *s1,
const char *s2, size_t n );
Appends at most n characters of string s2
to string s1. The first character of s2
overwrites the terminating null character of
s1. The value of s1 is returned.
int strcmp( const char *s1,
const char *s2 );
Compares the string s1 with the string s2.
The function returns a value of zero, less
than zero or greater than zero if s1 is
equal to, less than or greater than s2,
respectively.
String Manipulation Functions of the
String-handling Library
int strncmp( const char *s1,
const char *s2, size_t n );
Compares up to n characters of the
string s1 with the string s2. The
function returns zero, less than zero or
greater than zero if s1 is equal to, less
than or greater than s2, respectively.
char *strtok( char *s1, const
char *s2 );
A sequence of calls to strtok breaks
string s1 into “tokens”—logical pieces
such as words in a line of text—
delimited by characters contained in
string s2. The first call contains s1 as
the first argument, and subsequent calls
to continue tokenizing the same string
contain NULL as the first argument. A
pointer to the current token is returned
by each call. If there are no more
tokens when the function is called,
NULL is returned.
size_t strlen( const char *s ); Determines the length of string s. The
number of characters preceding the
terminating null character is returned.
Structure Definitions
 Structures
 Aggregate data types built using elements of other types
struct Time {
int hour;
int minute;
int second;
};
Structure member naming
 In same struct: must have unique names
 In different structs: can share name
struct definition must end with semicolon
Structure tag
Structure members
Structure
Structure Definitions
 Self-referential structure
 Structure member cannot be instance of enclosing struct
 Structure member can be pointer to instance of enclosing struct (self-referential
structure)
 Used for linked lists, queues, stacks and trees
 struct definition
 Creates new data type used to declare variables
 Structure variables declared like variables of other types
 Examples:
 Time timeObject;
 Time timeArray[ 10 ];
 Time *timePtr;
 Time &timeRef = timeObject;
Accessing Structure Members
 Member access operators
 Dot operator (.) for structure and class members
 Arrow operator (->) for structure and class members via pointer to object
 Print member hour of timeObject:
cout << timeObject.hour;
OR
timePtr = &timeObject;
cout << timePtr->hour;
 timePtr->hour same as ( *timePtr ).hour
 Parentheses required
* lower precedence than .
Implementing a User-Defined
Type Time with a struct
 Default: structures passed by value
 Pass structure by reference
 Avoid overhead of copying structure
 C-style structures
 No “interface”
 If implementation changes, all programs using that struct must change
accordingly
 Cannot print as unit
 Must print/format member by member
 Cannot compare in entirety
 Must compare member by member
1 // Example 7
2 // Create a structure, set its members, and print it.
3 #include <iostream>
4
5 using std::cout;
6 using std::endl;
7
8 #include <iomanip>
9
10 using std::setfill;
11 using std::setw;
12
13 // structure definition
14 struct Time {
15 int hour; // 0-23 (24-hour clock format)
16 int minute; // 0-59
17 int second; // 0-59
18
19 }; // end struct Time
20
21 void printUniversal( const Time & ); // prototype
22 void printStandard( const Time & ); // prototype
23
Define structure type Time
with three integer members.
Pass references to constant
Time objects to eliminate
copying overhead.
Class
 Classes(keyword class)
 Model objects
 Attributes (data members)
 Behaviors (member functions)
Methods
Invoked in response to messages
 Member access specifiers: public, Private, protected:
 Constructor function
 Special member function
 Initializes data members
 Same name as class
 Called when object instantiated
 Several constructors
 Function overloading
 No return type
Implementing a Time Abstract Data
Type with a class
 Objects of class
 After class definition
 Class name new type specifier
 Object, array, pointer and
reference declarations
Member functions defined
outside class
Time sunset; // object of type Time
Time arrayOfTimes[ 5 ]; // array of Time objects
Time *pointerToTime; // pointer to a Time object
Time &dinnerTime = sunset; // reference to a Time object
Class name becomes
new type specifier.
Binary scope resolution (::)
ReturnType ClassName::MemberFunctionName(
){…}
Member functions defined inside class
Do not need scope resolution
operator, class name
Compiler attempts inline
Outside class, inline explicitly with
keyword inline
1 // Example 8
2 // Time class.
3 #include <iostream>
4
5 using std::cout;
6 using std::endl;
7
8 #include <iomanip>
9
10 using std::setfill;
11 using std::setw;
12
13 // Time abstract data type (ADT) definition
14 class Time {
15
16 public:
17 Time(); // constructor
18 void setTime( int, int, int ); // set hour, minute, second
19 void printUniversal(); // print universal-time format
20 void printStandard(); // print standard-time format
21
Define class Time.
22 private:
23 int hour; // 0 - 23 (24-hour clock format)
24 int minute; // 0 - 59
25 int second; // 0 - 59
26
27 }; // end class Time
28
29 // Time constructor initializes each data member to zero and
30 // ensures all Time objects start in a consistent state
31 Time::Time()
32 {
33 hour = minute = second = 0;
34
35 } // end Time constructor
36
37 // set new Time value using universal time, perform validity
38 // checks on the data values and set invalid values to zero
39 void Time::setTime( int h, int m, int s )
40 {
41 hour = ( h >= 0 && h < 24 ) ? h : 0;
42 minute = ( m >= 0 && m < 60 ) ? m : 0;
43 second = ( s >= 0 && s < 60 ) ? s : 0;
44
45 } // end function setTime
46
Constructor initializes
private data members
to 0.
public member
function checks
parameter values for
validity before setting
private data
members.
47 // print Time in universal format
48 void Time::printUniversal()
49 {
50 cout << setfill( '0' ) << setw( 2 ) << hour << ":"
51 << setw( 2 ) << minute << ":"
52 << setw( 2 ) << second;
53
54 } // end function printUniversal
55
56 // print Time in standard format
57 void Time::printStandard()
58 {
59 cout << ( ( hour == 0 || hour == 12 ) ? 12 : hour % 12 )
60 << ":" << setfill( '0' ) << setw( 2 ) << minute
61 << ":" << setw( 2 ) << second
62 << ( hour < 12 ? " AM" : " PM" );
63
64 } // end function printStandard
65
66 int main()
67 {
68 Time t; // instantiate object t of class Time
69
Declare variable t to be
object of class Time.
No arguments (implicitly
“know” purpose is to print
data members); member
function calls more concise.
70 // output Time object t's initial values
71 cout << "The initial universal time is ";
72 t.printUniversal(); // 00:00:00
73
74 cout << "nThe initial standard time is ";
75 t.printStandard(); // 12:00:00 AM
76
77 t.setTime( 13, 27, 6 ); // change time
78
79 // output Time object t's new values
80 cout << "nnUniversal time after setTime is ";
81 t.printUniversal(); // 13:27:06
82
83 cout << "nStandard time after setTime is ";
84 t.printStandard(); // 1:27:06 PM
85
86 t.setTime( 99, 99, 99 ); // attempt invalid settings
87
88 // output t's values after specifying invalid values
89 cout << "nnAfter attempting invalid settings:"
90 << "nUniversal time: ";
91 t.printUniversal(); // 00:00:00
92
Invoke public member
functions to print time.
Set data members using
public member function.
Attempt to set data members
to invalid values using
public member function.
93 cout << "nStandard time: ";
94 t.printStandard(); // 12:00:00 AM
95 cout << endl;
96
97 return 0;
98
99 } // end main
The initial universal time is 00:00:00
The initial standard time is 12:00:00 AM
Universal time after setTime is 13:27:06
Standard time after setTime is 1:27:06 PM
After attempting invalid settings:
Universal time: 00:00:00
Standard time: 12:00:00 AM
Data members set to 0 after
attempting invalid settings.
Classes
 Destructors
 Same name as class
 Preceded with tilde (~)
 No arguments
 Cannot be overloaded
 Performs “termination housekeeping”
 Advantages of using classes
 Simplify programming
 Interfaces
 Hide implementation
 Software reuse
 Composition (aggregation)
Class objects included as members of other classes
 Inheritance
New classes derived from old
Class Scope and Accessing Class
Members
 Class scope
 Data members, member functions
 Within class scope
 Class members
Immediately accessible by all member functions
Referenced by name
 Outside class scope
 Referenced through handles
Object name, reference to object, pointer to object
 File scope
 Nonmember functions
Class Scope and Accessing Class
Members
Function scope
Variables declared in member function
Only known to function
Variables with same name as class-scope variables
 Class-scope variable “hidden”
Access with scope resolution operator (::)
ClassName::classVariableName
Variables only known to function they are defined in
Variables are destroyed after function completion
Operators to access class members
Identical to those for structs
Dot member selection operator (.)
 Object
 Reference to object
Arrow member selection operator (->)
 Pointers
1 // Example 9
2 // Demonstrating the class member access operators . and ->
3 //
4 // CAUTION: IN FUTURE EXAMPLES WE AVOID PUBLIC DATA!
5 #include <iostream>
6
7 using std::cout;
8 using std::endl;
9
10 // class Count definition
11 class Count {
12
13 public:
14 int x;
15
16 void print()
17 {
18 cout << x << endl;
19 }
20
21 }; // end class Count
22
Data member x public to
illustrate class member access
operators; typically data
members private.
Separating Interface from
Implementation
Separating interface from implementation
Advantage: Easier to modify programs
Disadvantage
 Header files
Portions of implementation: Inline member functions
Hints about other implementation: private members
 Can hide more with proxy class
Header files
Class definitions and function prototypes
Included in each file using class
 #include
File extension .h
Source-code files
Member function definitions
Same base name
 Convention
Compiled and linked
Controlling Access to Members
 Access modes
 private
 Default access mode
 Accessible to member functions and friends
 public
 Accessible to any function in program with handle to class object
 protected (later)
 Class member access
 Default private
 Explicitly set to private, public, protected
 struct member access
 Default public
 Explicitly set to private, public, protected
Access Functions and Utility
Functions
 Access to class’s private data
 Controlled with access functions (accessor methods)
 Get function - Read private data
 Set function - Modify private data
 Access functions
 public
 Read/display data
 Predicate functions
 Check conditions
 Utility functions (helper functions)
 private
 Support operation of public member functions
 Not intended for direct client use
1 // Example 10
2 // SalesPerson class definition.
3 // Member functions defined in salesp.cpp.
4 #ifndef SALESP_H
5 #define SALESP_H
6
7 class SalesPerson {
8
9 public:
10 SalesPerson(); // constructor
11 void getSalesFromUser(); // input sales from keyboard
12 void setSales( int, double ); // set sales for a month
13 void printAnnualSales(); // summarize and print sales
14
15 private:
16 double totalAnnualSales(); // utility function
17 double sales[ 12 ]; // 12 monthly sales figures
18
19 }; // end class SalesPerson
20
21 #endif
Set access function
performs validity
checks.
private utility
function.
25 // get 12 sales figures from the user at the keyboard
26 void SalesPerson::getSalesFromUser()
27 {
28 double salesFigure;
29
30 for ( int i = 1; i <= 12; i++ ) {
31 cout << "Enter sales amount for month " << i << ": ";
32 cin >> salesFigure;
33 setSales( i, salesFigure );
34
35 } // end for
36
37 } // end function getSalesFromUser
38
39 // set one of the 12 monthly sales figures; function subtracts
40 // one from month value for proper subscript in sales array
41 void SalesPerson::setSales( int month, double amount )
42 {
43 // test for valid month and amount values
44 if ( month >= 1 && month <= 12 && amount > 0 )
45 sales[ month - 1 ] = amount; // adjust for subscripts 0-11
46
47 else // invalid month or amount value
48 cout << "Invalid month or sales figure" << endl;
Set access function performs
validity checks.
Initializing Class Objects:
Constructors
Constructors
Initialize data members; no return type
 Or can set later
Same name as class
Can specify default arguments
Default constructors
 Defaults all arguments
OR
 Explicitly requires no arguments
 Can be invoked with no arguments
 Only one per class
Initializers
Passed as arguments to constructor
In parentheses to right of class name before semicolon
Class-type ObjectName( value1,value2,…);
1 // Example 11
2 // Declaration of class Time.
3 // Member functions defined in time2.cpp.
4
5 // prevent multiple inclusions of header file
6 #ifndef TIME2_H
7 #define TIME2_H
8
9 // Time abstract data type definition
10 class Time {
11
12 public:
13 Time( int = 0, int = 0, int = 0); // default constructor
14 void setTime( int, int, int ); // set hour, minute, second
15 void printUniversal(); // print universal-time format
16 void printStandard(); // print standard-time format
17
18 private:
19 int hour; // 0 - 23 (24-hour clock format)
20 int minute; // 0 - 59
21 int second; // 0 - 59
22
23 }; // end class Time
24
25 #endif
Default constructor specifying
all arguments.
1 // Example 12
2 // Member-function definitions for class Time.
3 #include <iostream>
4
5 using std::cout;
6
7 #include <iomanip>
8
9 using std::setfill;
10 using std::setw;
11
12 // include definition of class Time from time2.h
13 #include "time2.h"
14
15 // Time constructor initializes each data member to zero;
16 // ensures all Time objects start in a consistent state
17 Time::Time( int hr, int min, int sec )
18 {
19 setTime( hr, min, sec ); // validate and set time
20
21 } // end Time constructor
22
Constructor calls setTime
to validate passed (or default)
values.
23 // set new Time value using universal time, perform validity
24 // checks on the data values and set invalid values to zero
25 void Time::setTime( int h, int m, int s )
26 {
27 hour = ( h >= 0 && h < 24 ) ? h : 0;
28 minute = ( m >= 0 && m < 60 ) ? m : 0;
29 second = ( s >= 0 && s < 60 ) ? s : 0;
30
31 } // end function setTime
32
33 // print Time in universal format
34 void Time::printUniversal()
35 {
36 cout << setfill( '0' ) << setw( 2 ) << hour << ":"
37 << setw( 2 ) << minute << ":"
38 << setw( 2 ) << second;
39
40 } // end function printUniversal
41
1 // Example 13
2 // Demonstrating a default constructor for class Time.
3 #include <iostream>
4
5 using std::cout;
6 using std::endl;
7
8 // include definition of class Time from time2.h
9 #include "time2.h"
10
11 int main()
12 {
13 Time t1; // all arguments defaulted
14 Time t2( 2 ); // minute and second defaulted
15 Time t3( 21, 34 ); // second defaulted
16 Time t4( 12, 25, 42 ); // all values specified
17 Time t5( 27, 74, 99 ); // all bad values specified
18
19 cout << "Constructed with:nn"
20 << "all default arguments:n ";
21 t1.printUniversal(); // 00:00:00
22 cout << "n ";
23 t1.printStandard(); // 12:00:00 AM
24
Initialize Time
objects using
default arguments.
Initialize Time object with
invalid values; validity
checking will set values to 0.
25 cout << "nnhour specified; default minute and second:n ";
26 t2.printUniversal(); // 02:00:00
27 cout << "n ";
28 t2.printStandard(); // 2:00:00 AM
29
30 cout << "nnhour and minute specified; default second:n ";
31 t3.printUniversal(); // 21:34:00
32 cout << "n ";
33 t3.printStandard(); // 9:34:00 PM
34
35 cout << "nnhour, minute, and second specified:n ";
36 t4.printUniversal(); // 12:25:42
37 cout << "n ";
38 t4.printStandard(); // 12:25:42 PM
39
40 cout << "nnall invalid values specified:n ";
41 t5.printUniversal(); // 00:00:00
42 cout << "n ";
43 t5.printStandard(); // 12:00:00 AM
44 cout << endl;
45
46 return 0;
47
48 } // end main
t5 constructed with invalid
arguments; values set to 0.
Destructors
 Destructors
 Special member function
 Same name as class preceded with tilde (~)
 No arguments; No return value
 Cannot be overloaded
 Performs “termination housekeeping”
 Before system reclaims object’s memory
Reuse memory for new objects
 No explicit destructor
 Compiler creates “empty destructor”
 Constructors and destructors - Called implicitly by compiler
 Order of function calls
 Depends on when execution enters and exits scope of objects
 Generally, destructor calls reverse order of constructor calls
When Constructors and
Destructors Are Called
 Global scope objects
 Constructors - Before any other function (including main)
 Destructors
When main terminates (or exit function called)
Not called if program terminates with abort
 Automatic local objects
 Constructors - When objects defined & each time execution enters scope
 Destructors
When objects leave scope
 Execution exits block in which object defined
Not called if program ends with exit or abort
 static local objects
 Constructors
Exactly once
When execution reaches point where object defined
 Destructors
When main terminates or exit function called
Not called if program ends with abort
1 // Example 14
2 // Demonstrating the order in which constructors and
3 // destructors are called.
4 #include <iostream>
5
6 using std::cout;
7 using std::endl;
8
9 // include CreateAndDestroy class definition from create.h
10 #include "create.h"
11
12 void create( void ); // prototype
13
14 // global object
15 CreateAndDestroy first( 1, "(global before main)" );
16
17 int main()
18 {
19 cout << "nMAIN FUNCTION: EXECUTION BEGINS" << endl;
20
21 CreateAndDestroy second( 2, "(local automatic in main)" );
22
23 static CreateAndDestroy third(
24 3, "(local static in main)" );
25
Create variable with global
scope.
Create local automatic object.
Create static local object.
26 create(); // call function to create objects
27
28 cout << "nMAIN FUNCTION: EXECUTION RESUMES" << endl;
29
30 CreateAndDestroy fourth( 4, "(local automatic in main)" );
31
32 cout << "nMAIN FUNCTION: EXECUTION ENDS" << endl;
33
34 return 0;
35
36 } // end main
37
38 // function to create objects
39 void create( void )
40 {
41 cout << "nCREATE FUNCTION: EXECUTION BEGINS" << endl;
42
43 CreateAndDestroy fifth( 5, "(local automatic in create)" );
44
45 static CreateAndDestroy sixth(
46 6, "(local static in create)" );
47
48 CreateAndDestroy seventh(
49 7, "(local automatic in create)" );
50 cout << "nCREATE FUNCTION: EXECUTION ENDS" << endl;
52
53 } // end function create
Create local automatic
objects.
Create local automatic object.
Create local automatic object
in function.
Create static local object
in function.
Create local automatic object
in function.
Object 1 constructor runs (global before main)
MAIN FUNCTION: EXECUTION BEGINS
Object 2 constructor runs (local automatic in main)
Object 3 constructor runs (local static in main)
CREATE FUNCTION: EXECUTION BEGINS
Object 5 constructor runs (local automatic in create)
Object 6 constructor runs (local static in create)
Object 7 constructor runs (local automatic in create)
CREATE FUNCTION: EXECUTION ENDS
Object 7 destructor runs (local automatic in create)
Object 5 destructor runs (local automatic in create)
MAIN FUNCTION: EXECUTION RESUMES
Object 4 constructor runs (local automatic in main)
MAIN FUNCTION: EXECUTION ENDS
Object 4 destructor runs (local automatic in main)
Object 2 destructor runs (local automatic in main)
Object 6 destructor runs (local static in create)
Object 3 destructor runs (local static in main)
Object 1 destructor runs (global before main)
Destructors for local
automatic objects in main
called in reverse order of
constructors.
Local static object exists
until program termination.Global object constructed
before main execution and
destroyed last.
Local automatic objects
destroyed after function
execution ends in reverse
order of construction.
Local static object
constructed on first function
call and destroyed after main
execution ends.
Using Set and Get Functions
 Set functions
 Perform validity checks before modifying private data
 Notify if invalid values
 Indicate with return values
 Get functions
 “Query” functions
 Control format of data returned
Subtle Trap: Returning a Reference to a
private Data Member
 Reference to object
 &pRef = p;
 Alias for name of object
 Lvalue
 Can receive value in assignment statement
Changes original object
 Returning references
 public member functions can return non-const references to private data
members
 Client able to modify private data members
1 // Example 15
2 // Declaration of class Time.
3 // Member functions defined in time4.cpp
4
5 // prevent multiple inclusions of header file
6 #ifndef TIME4_H
7 #define TIME4_H
8
9 class Time {
10
11 public:
12 Time( int = 0, int = 0, int = 0 );
13 void setTime( int, int, int );
14 int getHour();
15
16 int &badSetHour( int ); // DANGEROUS reference return
17
18 private:
19 int hour;
20 int minute;
21 int second;
22
23 }; // end class Time
24
25 #endif
Function to demonstrate
effects of returning reference
to private data member.
25 // return hour value
26 int Time::getHour()
27 {
28 return hour;
29
30 } // end function getHour
31
32 // POOR PROGRAMMING PRACTICE:
33 // Returning a reference to a private data member.
34 int &Time::badSetHour( int hh )
35 {
36 hour = ( hh >= 0 && hh < 24 ) ? hh : 0;
37
38 return hour; // DANGEROUS reference return
39
40 } // end function badSetHour
Return reference to private
data member hour.
1 // Example 16
2 // Demonstrating a public member function that
3 // returns a reference to a private data member.
4 #include <iostream>
5
6 using std::cout;
7 using std::endl;
8
9 // include definition of class Time from time4.h
10 #include "time4.h"
11
12 int main()
13 {
14 Time t;
15
16 // store in hourRef the reference returned by badSetHour
17 int &hourRef = t.badSetHour( 20 );
18
19 cout << "Hour before modification: " << hourRef;
20
21 // use hourRef to set invalid value in Time object t
22 hourRef = 30;
23
24 cout << "nHour after modification: " << t.getHour();
25
badSetHour returns
reference to private data
member hour.
Reference allows setting of
private data member
hour.
26 // Dangerous: Function call that returns
27 // a reference can be used as an lvalue!
28 t.badSetHour( 12 ) = 74;
29
30 cout << "nn*********************************n"
31 << "POOR PROGRAMMING PRACTICE!!!!!!!!n"
32 << "badSetHour as an lvalue, Hour: "
33 << t.getHour()
34 << "n*********************************" << endl;
35
36 return 0;
37
38 } // end main
Hour before modification: 20
Hour after modification: 30
*********************************
POOR PROGRAMMING PRACTICE!!!!!!!!
badSetHour as an lvalue, Hour: 74
*********************************
Can use function call as
lvalue to set invalid value.
Returning reference allowed
invalid setting of private
data member hour.
Default Memberwise
Assignment
 Assigning objects
 Assignment operator (=)
 Can assign one object to another of same type
 Default: memberwise assignment
Each right member assigned individually to left member
 Passing, returning objects
 Objects passed as function arguments
 Objects returned from functions
 Default: pass-by-value
 Copy of object passed, returned
Copy constructor
 Copy original values into new object
1 // Example 17
2 // Demonstrating that class objects can be assigned
3 // to each other using default memberwise assignment.
4 #include <iostream>
5
6 using std::cout;
7 using std::endl;
8
9 // class Date definition
10 class Date {
11
12 public:
13 Date( int = 1, int = 1, int = 1990 ); // default constructor
14 void print();
15
16 private:
17 int month;
18 int day;
19 int year;
20
21 }; // end class Date
22
Software Reusability
 Software reusability
 Class libraries
 Well-defined
 Carefully tested
 Well-documented
 Portable
 Widely available
 Speeds development of powerful, high-quality software
 Rapid applications development (RAD)
 Resulting problems
 Cataloging schemes
 Licensing schemes
 Protection mechanisms
const (Constant) Objects and
const Member Functions
 Keyword const
 Specify object not modifiable
 Compiler error if attempt to modify const object
 Example
const Time noon( 12, 0, 0 );
 Declares const object noon of class Time
 Initializes to 12
 const member functions
 Member functions for const objects must also be const
 Cannot modify object
 Specify const in both prototype and definition
 Prototype
After parameter list
 Definition
Before beginning left brace
const (Constant) Objects and
const Member Functions
 Constructors and destructors
 Cannot be const
 Must be able to modify objects
 Constructor
Initializes objects
 Destructor
Performs termination housekeeping
 Member initializer syntax
 Initializing with member initializer syntax
 Can be used for
All data members
 Must be used for
const data members
Data members that are references
1 // Example 18
2 // Using a member initializer to initialize a
3 // constant of a built-in data type.
4 #include <iostream>
5
6 using std::cout;
7 using std::endl;
8
9 class Increment {
10
11 public:
12 Increment( int c = 0, int i = 1 ); // default constructor
13
14 void addIncrement()
15 {
16 count += increment;
17
18 } // end function addIncrement
19
20 void print() const; // prints count and increment
21
22 private:
23 int count;
24 const int increment; // const data member
25
26 }; // end class Increment
27
28 // constructor
29 Increment::Increment( int c, int i )
30 : count( c ), // initializer for non-const member
31 increment( i ) // required initializer for const member
32 {
33 // empty body
34
35 } // end Increment constructor
36
37 // print count and increment values
38 void Increment::print() const
39 {
40 cout << "count = " << count
41 << ", increment = " << increment << endl;
42
43 } // end function print
44
Declare increment as const
data member.
Member initializer list
separated from parameter list
by colon.
Member initializer syntax can
be used for non-const data
member count.
Member initializer syntax
must be used for const data
member increment.
Member initializer consists of
data member name
(increment) followed by
parentheses containing initial
value (c).
Composition: Objects as Members of
Classes
 Composition
 Class has objects of other classes as members
 Construction of objects
 Member objects constructed in order declared
 Not in order of constructor’s member initializer list
 Constructed before enclosing class objects (host objects)
1 // Example 19
2 // Date class definition.
3 // Member functions defined in date1.cpp
4 #ifndef DATE1_H
5 #define DATE1_H
6
7 class Date {
8
9 public:
10 Date( int = 1, int = 1, int = 1900 ); // default constructor
11 void print() const; // print date in month/day/year format
12 ~Date(); // provided to confirm destruction order
13
14 private:
15 int month; // 1-12 (January-December)
16 int day; // 1-31 based on month
17 int year; // any year
18
19 // utility function to test proper day for month and year
20 int checkDay( int ) const;
21
22 }; // end class Date
23
24 #endif
Note no constructor with
parameter of type Date.
Recall compiler provides
default copy constructor.
1 // EXAMPLE 20
2 // Employee class definition.
3 // Member functions defined in employee1.cpp.
4 #ifndef EMPLOYEE1_H
5 #define EMPLOYEE1_H
6
7 // include Date class definition from date1.h
8 #include "date1.h"
9
10 class Employee {
11
12 public:
13 Employee(
14 const char *, const char *, const Date &, const Date & );
15
16 void print() const;
17 ~Employee(); // provided to confirm destruction order
18
19 private:
20 char firstName[ 25 ];
21 char lastName[ 25 ];
22 const Date birthDate; // composition: member object
23 const Date hireDate; // composition: member object
24
25 }; // end class Employee
Using composition;
Employee object contains
Date objects as data
members.
13 // constructor uses member initializer list to pass initializer
14 // values to constructors of member objects birthDate and
15 // hireDate [Note: This invokes the so-called "default copy
16 // constructor" which the C++ compiler provides implicitly.]
17 Employee::Employee( const char *first, const char *last,
18 const Date &dateOfBirth, const Date &dateOfHire )
19 : birthDate( dateOfBirth ), // initialize birthDate
20 hireDate( dateOfHire ) // initialize hireDate
21 {
22 // copy first into firstName and be sure that it fits
23 int length = strlen( first );
24 length = ( length < 25 ? length : 24 );
25 strncpy( firstName, first, length );
26 firstName[ length ] = '0';
27
28 // copy last into lastName and be sure that it fits
29 length = strlen( last );
30 length = ( length < 25 ? length : 24 );
31 strncpy( lastName, last, length );
32 lastName[ length ] = '0';
33
34 // output Employee object to show when constructor is called
35 cout << "Employee object constructor: "
36 << firstName << ' ' << lastName << endl;
37
Member initializer syntax to
initialize Date data members
birthDate and
hireDate; compiler uses
default copy constructor.
Output to show timing of
constructors.
1 // Example 21
2 // Demonstrating composition--an object with member objects.
3 #include <iostream>
4
5 using std::cout;
6 using std::endl;
7
8 #include "employee1.h" // Employee class definition
9
10 int main()
11 {
12 Date birth( 7, 24, 1949 );
13 Date hire( 3, 12, 1988 );
14 Employee manager( "Bob", "Jones", birth, hire );
15
16 cout << 'n';
17 manager.print();
18
19 cout << "nTest Date constructor with invalid values:n";
20 Date lastDayOff( 14, 35, 1994 ); // invalid month and day
21 cout << endl;
22
23 return 0;
24
25 } // end main
Create Date objects to pass
to Employee constructor.
friend Functions and friend
Classes
 friend function
 Defined outside class’s scope
 Right to access non-public members
 Declaring friends
 Function
 Precede function prototype with keyword friend
 Want to make all member functions of class ClassTwo as friends of class
ClassOne
 Place declaration of form
friend class ClassTwo;
in ClassOne definition
friend Functions and
friend Classes
 Properties of friendship
 Friendship granted, not taken
 Class B friend of class A
Class A must explicitly declare class B friend
 Not symmetric
 Class B friend of class A
 Class A not necessarily friend of class B
 Not transitive
 Class A friend of class B
 Class B friend of class C
 Class A not necessarily friend of Class C
1 // Example 22
2 // Friends can access private members of a class.
3 #include <iostream>
4
5 using std::cout;
6 using std::endl;
7
8 // Count class definition
9 class Count {
10 friend void setX( Count &, int ); // friend declaration
11
12 public:
13
14 // constructor
15 Count()
16 : x( 0 ) // initialize x to 0
17 {
18 // empty body
19
20 } // end Count constructor
21
Precede function prototype
with keyword friend.
22 // output x
23 void print() const
24 {
25 cout << x << endl;
26
27 } // end function print
28
29 private:
30 int x; // data member
31
32 }; // end class Count
33
34 // function setX can modify private data of Count
35 // because setX is declared as a friend of Count
36 void setX( Count &c, int val )
37 {
38 c.x = val; // legal: setX is a friend of Count
39
40 } // end function setX
41
Pass Count object since C-
style, standalone function.
Since setX friend of
Count, can access and
modify private data
member x.
42 int main()
43 {
44 Count counter; // create Count object
45
46 cout << "counter.x after instantiation: ";
47 counter.print();
48
49 setX( counter, 8 ); // set x with a friend
50
51 cout << "counter.x after call to setX friend function: ";
52 counter.print();
53
54 return 0;
55
56 } // end main
counter.x after instantiation: 0
counter.x after call to setX friend function: 8
Use friend function to
access and modify private
data member x.
Using the this Pointer
 this pointer
 Allows object to access own address
 Not part of object itself
 Implicit argument to non-static member function call
 Implicitly reference member data and functions
 Type of this pointer depends on
 Type of object
 Whether member function is const
 In non-const member function of Employee
this has type Employee * const
 Constant pointer to non-constant Employee object
 In const member function of Employee
this has type const Employee * const
 Constant pointer to constant Employee object
1 // Example 23
2 // Using the this pointer to refer to object members.
3 #include <iostream>
4
5 using std::cout;
6 using std::endl;
7
8 class Test {
9
10 public:
11 Test( int = 0 ); // default constructor
12 void print() const;
13
14 private:
15 int x;
16
17 }; // end class Test
18
19 // constructor
20 Test::Test( int value )
21 : x( value ) // initialize x to value
22 {
23 // empty body
24
25 } // end Test constructor
26
27 // print x using implicit and explicit this pointers;
28 // parentheses around *this required
29 void Test::print() const
30 {
31 // implicitly use this pointer to access member x
32 cout << " x = " << x;
33
34 // explicitly use this pointer to access member x
35 cout << "n this->x = " << this->x;
36
37 // explicitly use dereferenced this pointer and
38 // the dot operator to access member x
39 cout << "n(*this).x = " << ( *this ).x << endl;
40
41 } // end function print
42
43 int main()
44 {
45 Test testObject( 12 );
46
47 testObject.print();
48
49 return 0;
50
Implicitly use this pointer;
only specify name of data
member (x).
Explicitly use this pointer
with arrow operator.
Explicitly use this pointer;
dereference this pointer
first, then use dot operator.
51 } // end main
x = 12
this->x = 12
(*this).x = 12
Using the this Pointer
 Cascaded member function calls
 Multiple functions invoked in same statement
 Function returns reference pointer to same object
{ return *this; }
 Other functions operate on that pointer
 Functions that do not return references must be called last
1 // Example 24
2 // Cascading member function calls.
3
4 // Time class definition.
5 // Member functions defined in time6.cpp.
6 #ifndef TIME6_H
7 #define TIME6_H
8
9 class Time {
10
11 public:
12 Time( int = 0, int = 0, int = 0 ); // default constructor
13
14 // set functions
15 Time &setTime( int, int, int ); // set hour, minute, second
16 Time &setHour( int ); // set hour
17 Time &setMinute( int ); // set minute
18 Time &setSecond( int ); // set second
19
20 // get functions (normally declared const)
21 int getHour() const; // return hour
22 int getMinute() const; // return minute
23 int getSecond() const; // return second
24
Set functions return reference
to Time object to enable
cascaded member function
calls.
25 // print functions (normally declared const)
26 void printUniversal() const; // print universal time
27 void printStandard() const; // print standard time
28
29 private:
30 int hour; // 0 - 23 (24-hour clock format)
31 int minute; // 0 - 59
32 int second; // 0 - 59
33
34 }; // end class Time
35
36 #endif
1 // Example 25
2 // Member-function definitions for Time class.
3 #include <iostream>
4
5 using std::cout;
6
7 #include <iomanip>
8
9 using std::setfill;
10 using std::setw;
11
12 #include "time6.h" // Time class definition
13
14 // constructor function to initialize private data;
15 // calls member function setTime to set variables;
16 // default values are 0 (see class definition)
17 Time::Time( int hr, int min, int sec )
18 {
19 setTime( hr, min, sec );
20
21 } // end Time constructor
22
23 // set values of hour, minute, and second
24 Time &Time::setTime( int h, int m, int s )
25 {
26 setHour( h );
27 setMinute( m );
28 setSecond( s );
29
30 return *this; // enables cascading
31
32 } // end function setTime
33
34 // set hour value
35 Time &Time::setHour( int h )
36 {
37 hour = ( h >= 0 && h < 24 ) ? h : 0;
38
39 return *this; // enables cascading
40
41 } // end function setHour
42
Return *this as reference to
enable cascaded member
function calls.
Return *this as reference to
enable cascaded member
function calls.
43 // set minute value
44 Time &Time::setMinute( int m )
45 {
46 minute = ( m >= 0 && m < 60 ) ? m : 0;
47
48 return *this; // enables cascading
49
50 } // end function setMinute
51
52 // set second value
53 Time &Time::setSecond( int s )
54 {
55 second = ( s >= 0 && s < 60 ) ? s : 0;
56
57 return *this; // enables cascading
58
59 } // end function setSecond
60
61 // get hour value
62 int Time::getHour() const
63 {
64 return hour;
65
66 } // end function getHour
67
Return *this as reference to
enable cascaded member
function calls.
Return *this as reference to
enable cascaded member
function calls.
68 // get minute value
69 int Time::getMinute() const
70 {
71 return minute;
72
73 } // end function getMinute
74
75 // get second value
76 int Time::getSecond() const
77 {
78 return second;
79
80 } // end function getSecond
81
82 // print Time in universal format
83 void Time::printUniversal() const
84 {
85 cout << setfill( '0' ) << setw( 2 ) << hour << ":"
86 << setw( 2 ) << minute << ":"
87 << setw( 2 ) << second;
88
89 } // end function printUniversal
90
91 // print Time in standard format
92 void Time::printStandard() const
93 {
94 cout << ( ( hour == 0 || hour == 12 ) ? 12 : hour % 12 )
95 << ":" << setfill( '0' ) << setw( 2 ) << minute
96 << ":" << setw( 2 ) << second
97 << ( hour < 12 ? " AM" : " PM" );
98
99 } // end function printStandard
1 // Example 26
2 // Cascading member function calls with the this pointer.
3 #include <iostream>
4
5 using std::cout;
6 using std::endl;
7
8 #include "time6.h" // Time class definition
9
10 int main()
11 {
12 Time t;
13
14 // cascaded function calls
15 t.setHour( 18 ).setMinute( 30 ).setSecond( 22 );
16
17 // output time in universal and standard formats
18 cout << "Universal time: ";
19 t.printUniversal();
20
21 cout << "nStandard time: ";
22 t.printStandard();
23
24 cout << "nnNew standard time: ";
25
Cascade member function
calls; recall dot operator
associates from left to right.
26 // cascaded function calls
27 t.setTime( 20, 20, 20 ).printStandard();
28
29 cout << endl;
30
31 return 0;
32
33 } // end main
Universal time: 18:30:22
Standard time: 6:30:22 PM
New standard time: 8:20:20 PM
Function call to
printStandard must
appear last;
printStandard does not
return reference to t.
Dynamic Memory Management with
Operators new and delete
Dynamic memory management
Control allocation and deallocation of memory
Operators new and delete
 Include standard header <new>
new
Time *timePtr;
timePtr = new Time;
Creates object of proper size for type Time
 Error if no space in memory for object
Calls default constructor for object
Returns pointer of specified type
Providing initializers
double *ptr = new double( 3.14159 );
Time *timePtr = new Time( 12, 0, 0 );
Allocating arrays
int *gradesArray = new int[ 10 ];
Dynamic Memory Management with
Operators new and delete
 delete
 Destroy dynamically allocated object and free space
 Consider
delete timePtr;
 Operator delete
 Calls destructor for object
 Deallocates memory associated with object
Memory can be reused to allocate other objects
 Deallocating arrays
delete [] gradesArray;
Deallocates array to which gradesArray points
 If pointer to array of objects
 First calls destructor for each object in array
 Then deallocates memory
static Class Members
 static class variable
 “Class-wide” data
 Property of class, not specific object of class
 Efficient when single copy of data is enough
 Only the static variable has to be updated
 May seem like global variables, but have class scope
 Only accessible to objects of same class
 Initialized exactly once at file scope
 Exist even if no objects of class exist
 Can be public, private or protected
static Class Members
Accessing static class variables
 Accessible through any object of class
 public static variables
 Can also be accessed using binary scope resolution operator(::)
Employee::count
 private static variables
 When no class member objects exist: Can only be accessed via
public static member function
Employee::getCount()
static member functions
 Cannot access non-static data or functions
 No this pointer for static functions
 static data members and static member functions exist
independent of objects
1 // Example 26
2 // Employee class definition.
3 #ifndef EMPLOYEE2_H
4 #define EMPLOYEE2_H
5
6 class Employee {
7
8 public:
9 Employee( const char *, const char * ); // constructor
10 ~Employee(); // destructor
11 const char *getFirstName() const; // return first name
12 const char *getLastName() const; // return last name
13
14 // static member function
15 static int getCount(); // return # objects instantiated
16
17 private:
18 char *firstName;
19 char *lastName;
20
21 // static data member
22 static int count; // number of objects instantiated
23
24 }; // end class Employee
25
static member function
can only access static data
members and member
functions.
static data member is
class-wide data.
1 // Example 27
2 // Member-function definitions for class Employee.
3 #include <iostream>
4
5 using std::cout;
6 using std::endl;
7
8 #include <new> // C++ standard new operator
9 #include <cstring> // strcpy and strlen prototypes
10
11 #include "employee2.h" // Employee class definition
12
13 // define and initialize static data member
14 int Employee::count = 0;
15
16 // define static member function that returns number of
17 // Employee objects instantiated
18 int Employee::getCount()
19 {
20 return count;
21
22 } // end static function getCount
Initialize static data
member exactly once at file
scope.
static member function
accesses static data
member count.
23
24 // constructor dynamically allocates space for
25 // first and last name and uses strcpy to copy
26 // first and last names into the object
27 Employee::Employee( const char *first, const char *last )
28 {
29 firstName = new char[ strlen( first ) + 1 ];
30 strcpy( firstName, first );
31
32 lastName = new char[ strlen( last ) + 1 ];
33 strcpy( lastName, last );
34
35 ++count; // increment static count of employees
36
37 cout << "Employee constructor for " << firstName
38 << ' ' << lastName << " called." << endl;
39
40 } // end Employee constructor
41
42 // destructor deallocates dynamically allocated memory
43 Employee::~Employee()
44 {
45 cout << "~Employee() called for " << firstName
46 << ' ' << lastName << endl;
47
new operator dynamically
allocates space.
Use static data member to
store total count of
employees.
48 delete [] firstName; // recapture memory
49 delete [] lastName; // recapture memory
50
51 --count; // decrement static count of employees
52
53 } // end destructor ~Employee
54
55 // return first name of employee
56 const char *Employee::getFirstName() const
57 {
58 // const before return type prevents client from modifying
59 // private data; client should copy returned string before
60 // destructor deletes storage to prevent undefined pointer
61 return firstName;
62
63 } // end function getFirstName
64
65 // return last name of employee
66 const char *Employee::getLastName() const
67 {
68 // const before return type prevents client from modifying
69 // private data; client should copy returned string before
70 // destructor deletes storage to prevent undefined pointer
71 return lastName;
72
73 } // end function getLastName
Operator delete deallocates
memory.
Use static data member to
store total count of
employees.
Data Abstraction and
Information Hiding
 Information hiding
 Classes hide implementation details from clients
 Example: stack data structure
 Data elements added (pushed) onto top
 Data elements removed (popped) from top
 Last-in, first-out (LIFO) data structure
 Client only wants LIFO data structure
Does not care how stack implemented
 Data abstraction
 Describe functionality of class independent of implementation
Data Abstraction and
Information Hiding
 Abstract data types (ADTs)
 Approximations/models of real-world concepts and behaviors
 int, float are models for a numbers
 Data representation
 Operations allowed on those data
 C++ extensible
 Standard data types cannot be changed, but new data types can be created
Proxy Classes
 Proxy class
 Hide implementation details of another class
 Knows only public interface of class being hidden
 Enables clients to use class’s services without giving access to class’s
implementation
 Forward class declaration
 Used when class definition only uses pointer to another class
 Prevents need for including header file
 Declares class before referencing
 Format:
class ClassToLoad;
1 // Example 28
2 // Header file for class Implementation
3
4 class Implementation {
5
6 public:
7
8 // constructor
9 Implementation( int v )
10 : value( v ) // initialize value with v
11 {
12 // empty body
13
14 } // end Implementation constructor
15
16 // set value to v
17 void setValue( int v )
18 {
19 value = v; // should validate v
20
21 } // end function setValue
22
public member function.
23
// return value
24 int getValue() const
25 {
26 return value;
27
28 } // end function getValue
29
30 private:
31 int value;
32
33 }; // end class Implementation
1 // Example 29
2 // Header file for interface.cpp
3
4 class Implementation; // forward class declaration
5
6 class Interface {
7
8 public:
9 Interface( int );
10 void setValue( int ); // same public interface as
11 int getValue() const; // class Implementation
12 ~Interface();
13
14 private:
15
16 // requires previous forward declaration (line 4)
17 Implementation *ptr;
18
19 }; // end class Interface
Provide same public
interface as class
Implementation; recall
setValue and getValue
only public member
functions.
Pointer to
Implementation object
requires forward class
declaration.
1 // Example 30
2 // Definition of class Interface
3 #include "interface.h" // Interface class definition
4 #include "implementation.h" // Implementation class definition
5
6 // constructor
7 Interface::Interface( int v )
8 : ptr ( new Implementation( v ) ) // initialize ptr
9 {
10 // empty body
11
12 } // end Interface constructor
13
14 // call Implementation's setValue function
15 void Interface::setValue( int v )
16 {
17 ptr->setValue( v );
18
19 } // end function setValue
20
Proxy class Interface
includes header file for class
Implementation.
Maintain pointer to
underlying
Implementation object.
Invoke corresponding
function on underlying
Implementation object.
21 // call Implementation's getValue function
22 int Interface::getValue() const
23 {
24 return ptr->getValue();
25
26 } // end function getValue
27
28 // destructor
29 Interface::~Interface()
30 {
31 delete ptr;
32
33 } // end destructor ~Interface
Invoke corresponding
function on underlying
Implementation object.
Deallocate underlying
Implementation object.
1 // Example 30
2 // Hiding a class’s private data with a proxy class.
3 #include <iostream>
4
5 using std::cout;
6 using std::endl;
7
8 #include "interface.h" // Interface class definition
9
10 int main()
11 {
12 Interface i( 5 );
13
14 cout << "Interface contains: " << i.getValue()
15 << " before setValue" << endl;
16
17 i.setValue( 10 );
18
19 cout << "Interface contains: " << i.getValue()
20 << " after setValue" << endl;
21
22 return 0;
23
24 } // end main
Interface contains: 5 before setValue
Interface contains: 10 after setValue
Only include proxy class
header file.
Create object of proxy class
Interface; note no
mention of
Implementation class.
Invoke member functions via
proxy class object.
Fundamentals of Operator
Overloading
 Use operators with objects (operator overloading)
 Clearer than function calls for certain classes
 Operator sensitive to context
 Types
 Built in (int, char) or user-defined
 Can use existing operators with user-defined types
 Cannot create new operators
 Overloading operators
 Create a function for the class
 Name function operator followed by symbol
 Operator+ for the addition operator +
Fundamentals of Operator
Overloading
 Using operators on a class object
 It must be overloaded for that class
 Exceptions:
 Assignment operator, =
May be used without explicit overloading
Memberwise assignment between objects
 Address operator, &
May be used on any class without overloading
Returns address of object
 Both can be overloaded
Restrictions on Operator
Overloading
 Cannot change
 How operators act on built-in data types
 I.e., cannot change integer addition
 Precedence of operator (order of evaluation)
 Use parentheses to force order-of-operations
 Associativity (left-to-right or right-to-left)
 Number of operands
 & is unitary, only acts on one operand
 Cannot create new operators
 Operators must be overloaded explicitly
 Overloading + does not overload +=
Restrictions on Operator
Overloading
Operators that cannot be overloaded
. .* :: ?: sizeof
Operators that can be overloaded
+ - * / % ^ & |
~ ! = < > += -= *=
/= %= ^= &= |= << >> >>=
<<= == != <= >= && || ++
-- ->* , -> [] () new delete
new[] delete[]
Operator Functions As Class Members
Vs. As Friend Functions
 Operator functions
 Member functions
 Use this keyword to implicitly get argument
 Gets left operand for binary operators (like +)
 Leftmost object must be of same class as operator
 Non member functions
 Need parameters for both operands
 Can have object of different class than operator
 Must be a friend to access private or protected data
 Example Overloaded << operator
 Left operand of type ostream &
 Such as cout object in cout << classObject
 Similarly, overloaded >> needs istream &
 Thus, both must be non-member functions
Operator Functions As Class Members
Vs. As Friend Functions
 Commutative operators
 May want + to be commutative
 So both “a + b” and “b + a” work
 Suppose we have two different classes
 Overloaded operator can only be member function when its class is on left
 HugeIntClass + Long int
 Can be member function
 When other way, need a non-member overload function
 Long int + HugeIntClass
Overloading Stream-Insertion and
Stream-Extraction Operators
 << and >>
 Already overloaded to process each built-in type
 Can also process a user-defined class
 Example program
 Class PhoneNumber
 Holds a telephone number
 Print out formatted number automatically
 (123) 456-7890
1 // Example 31
2 // Overloading the stream-insertion and
3 // stream-extraction operators.
4 #include <iostream>
5
6 using std::cout;
7 using std::cin;
8 using std::endl;
9 using std::ostream;
10 using std::istream;
11
12 #include <iomanip>
13
14 using std::setw;
15
16 // PhoneNumber class definition
17 class PhoneNumber {
18 friend ostream &operator<<( ostream&, const PhoneNumber & );
19 friend istream &operator>>( istream&, PhoneNumber & );
20
21 private:
22 char areaCode[ 4 ]; // 3-digit area code and null
23 char exchange[ 4 ]; // 3-digit exchange and null
24 char line[ 5 ]; // 4-digit line and null
25
26 }; // end class PhoneNumber
Notice function prototypes for
overloaded operators >> and <<
They must be non-member friend
functions, since the object of class
Phonenumber appears on the right of
the operator.
cin << object
cout >> object
27
28 // overloaded stream-insertion operator; cannot be
29 // a member function if we would like to invoke it with
30 // cout << somePhoneNumber;
31 ostream &operator<<( ostream &output, const PhoneNumber &num )
32 {
33 output << "(" << num.areaCode << ") "
34 << num.exchange << "-" << num.line;
35
36 return output; // enables cout << a << b << c;
37
38 } // end function operator<<
39
40 // overloaded stream-extraction operator; cannot be
41 // a member function if we would like to invoke it with
42 // cin >> somePhoneNumber;
43 istream &operator>>( istream &input, PhoneNumber &num )
44 {
45 input.ignore(); // skip (
46 input >> setw( 4 ) >> num.areaCode; // input area code
47 input.ignore( 2 ); // skip ) and space
48 input >> setw( 4 ) >> num.exchange; // input exchange
49 input.ignore(); // skip dash (-)
50 input >> setw( 5 ) >> num.line; // input line
51
52 return input; // enables cin >> a >> b >> c;
The expression:
cout << phone;
is interpreted as the function call:
operator<<(cout, phone);
output is an alias for cout.
This allows objects to be cascaded.
cout << phone1 << phone2;
first calls
operator<<(cout, phone1), and
returns cout.
Next, cout << phone2 executes.
Stream manipulator setw
restricts number of characters
read. setw(4) allows 3
characters to be read, leaving
room for the null character.
53
54 } // end function operator>>
55
56 int main()
57 {
58 PhoneNumber phone; // create object phone
59
60 cout << "Enter phone number in the form (123) 456-7890:n";
61
62 // cin >> phone invokes operator>> by implicitly issuing
63 // the non-member function call operator>>( cin, phone )
64 cin >> phone;
65
66 cout << "The phone number entered was: " ;
67
68 // cout << phone invokes operator<< by implicitly issuing
69 // the non-member function call operator<<( cout, phone )
70 cout << phone << endl;
71
72 return 0;
73
74 } // end main
Enter phone number in the form (123) 456-7890:
(800) 555-1212
The phone number entered was: (800) 555-1212
Overloading Unary Operators
 Overloading unary operators
 Non-static member function, no arguments
 Non-member function, one argument
 Argument must be class object or reference to class object
 Remember, static functions only access static data
Overloading Operators
Overloading unary operators (! to test for empty string)
 Non-static member function: !s becomes s.operator!()
bool operator!() const;
 Non-member function:!s becomes operator!(s)
friend bool operator!( const String & )
Overloading binary operators
 Non-member function (arg. must be class object or reference)
friend const String &operator+=(String &, const String &
);
 Non-static member function:
const String &operator+=( const String & );
 y += z equivalent to y.operator+=( z )
Case Study: Array class
 Arrays in C++
 No range checking
 Cannot be compared meaningfully with ==
 No array assignment (array names const pointers)
 Cannot input/output entire arrays at once
 Example:Implement an Array class with
 Range checking
 Array assignment
 Arrays that know their size
 Outputting/inputting entire arrays with << and >>
 Array comparisons with == and !=
Case Study: Array class
 Copy constructor
 Used whenever copy of object needed
 Passing by value (return value or parameter)
 Initializing an object with a copy of another
Array newArray( oldArray );
newArray copy of oldArray
 Prototype for class Array
 Array( const Array & );
 Must take reference
Otherwise, pass by value
Tries to make copy by calling copy constructor…
Infinite loop
1 // Example 32
2 // Array class for storing arrays of integers.
3 #ifndef ARRAY1_H
4 #define ARRAY1_H
5
6 #include <iostream>
7
8 using std::ostream;
9 using std::istream;
10
11 class Array {
12 friend ostream &operator<<( ostream &, const Array & );
13 friend istream &operator>>( istream &, Array & );
14
15 public:
16 Array( int = 10 ); // default constructor
17 Array( const Array & ); // copy constructor
18 ~Array(); // destructor
19 int getSize() const; // return size
20
21 // assignment operator
22 const Array &operator=( const Array & );
23
24 // equality operator
25 bool operator==( const Array & ) const;
26
Most operators overloaded as
member functions (except <<
and >>, which must be non-
member functions).
Prototype for copy constructor.
27 // inequality operator; returns opposite of == operator
28 bool operator!=( const Array &right ) const
29 {
30 return ! ( *this == right ); // invokes Array::operator==
31
32 } // end function operator!=
33
34 // subscript operator for non-const objects returns lvalue
35 int &operator[]( int );
36
37 // subscript operator for const objects returns rvalue
38 const int &operator[]( int ) const;
39
40 private:
41 int size; // array size
42 int *ptr; // pointer to first element of array
43
44 }; // end class Array
45
46 #endif
!= operator simply returns
opposite of == operator. Thus,
only need to define the ==
operator.
1 // Example 33
2 // Member function definitions for class Array
3 #include <iostream>
4
5 using std::cout;
6 using std::cin;
7 using std::endl;
8
9 #include <iomanip>
10
11 using std::setw;
12
13 #include <new> // C++ standard "new" operator
14
15 #include <cstdlib> // exit function prototype
16
17 #include "array1.h" // Array class definition
18
19 // default constructor for class Array (default size 10)
20 Array::Array( int arraySize )
21 {
22 // validate arraySize
23 size = ( arraySize > 0 ? arraySize : 10 );
24
25 ptr = new int[ size ]; // create space for array
26
27 for ( int i = 0; i < size; i++ )
28 ptr[ i ] = 0; // initialize array
29
30 } // end Array default constructor
31
32 // copy constructor for class Array;
33 // must receive a reference to prevent infinite recursion
34 Array::Array( const Array &arrayToCopy )
35 : size( arrayToCopy.size )
36 {
37 ptr = new int[ size ]; // create space for array
38
39 for ( int i = 0; i < size; i++ )
40 ptr[ i ] = arrayToCopy.ptr[ i ]; // copy into object
41
42 } // end Array copy constructor
43
44 // destructor for class Array
45 Array::~Array()
46 {
47 delete [] ptr; // reclaim array space
48
49 } // end destructor
50
We must declare a new integer array so
the objects do not point to the same
memory.
51 // return size of array
52 int Array::getSize() const
53 {
54 return size;
55
56 } // end function getSize
57
58 // overloaded assignment operator;
59 // const return avoids: ( a1 = a2 ) = a3
60 const Array &Array::operator=( const Array &right )
61 {
62 if ( &right != this ) { // check for self-assignment
63
64 // for arrays of different sizes, deallocate original
65 // left-side array, then allocate new left-side array
66 if ( size != right.size ) {
67 delete [] ptr; // reclaim space
68 size = right.size; // resize this object
69 ptr = new int[ size ]; // create space for array copy
70
71 } // end inner if
72
73 for ( int i = 0; i < size; i++ )
74 ptr[ i ] = right.ptr[ i ]; // copy array into object
75
76 } // end outer if
Want to avoid self-assignment.
77
78 return *this; // enables x = y = z, for example
79
80 } // end function operator=
81
82 // determine if two arrays are equal and
83 // return true, otherwise return false
84 bool Array::operator==( const Array &right ) const
85 {
86 if ( size != right.size )
87 return false; // arrays of different sizes
88
89 for ( int i = 0; i < size; i++ )
90
91 if ( ptr[ i ] != right.ptr[ i ] )
92 return false; // arrays are not equal
93
94 return true; // arrays are equal
95
96 } // end function operator==
97
98 // overloaded subscript operator for non-const Arrays
99 // reference return creates an lvalue
100 int &Array::operator[]( int subscript )
101 {
102 // check for subscript out of range error
103 if ( subscript < 0 || subscript >= size ) {
104 cout << "nError: Subscript " << subscript
105 << " out of range" << endl;
106
107 exit( 1 ); // terminate program; subscript out of range
108
109 } // end if
110
111 return ptr[ subscript ]; // reference return
112
113 } // end function operator[]
114
integers1[5] calls
integers1.operator[]( 5 )
exit() (header <cstdlib>) ends
the program.
115 // overloaded subscript operator for const Arrays
116 // const reference return creates an rvalue
117 const int &Array::operator[]( int subscript ) const
118 {
119 // check for subscript out of range error
120 if ( subscript < 0 || subscript >= size ) {
121 cout << "nError: Subscript " << subscript
122 << " out of range" << endl;
123
124 exit( 1 ); // terminate program; subscript out of range
125
126 } // end if
127
128 return ptr[ subscript ]; // const reference return
129
130 } // end function operator[]
131
132 // overloaded input operator for class Array;
133 // inputs values for entire array
134 istream &operator>>( istream &input, Array &a )
135 {
136 for ( int i = 0; i < a.size; i++ )
137 input >> a.ptr[ i ];
138
139 return input; // enables cin >> x >> y;
140
141 } // end function
142
143 // overloaded output operator for class Array
144 ostream &operator<<( ostream &output, const Array &a )
145 {
146 int i;
147
148 // output private ptr-based array
149 for ( i = 0; i < a.size; i++ ) {
150 output << setw( 12 ) << a.ptr[ i ];
151
152 if ( ( i + 1 ) % 4 == 0 ) // 4 numbers per row of output
153 output << endl;
154
155 } // end for
156
157 if ( i % 4 != 0 ) // end last line of output
158 output << endl;
159
160 return output; // enables cout << x << y;
161
162 } // end function operator<<
Converting between Types
 Cast operator (conversion operator)
 Convert from One class to another built-in type
 Must be non-static member function -
Cannot be friend
 Do not specify return type
Implicitly returns type to which you are converting
 Example: A::operator char *() const;
 Casts class A to a temporary char *
 (char *)s calls s.operator char*()
A::operator int() const;
A::operator OtherClass() const;
 Casting can prevent need for overloading
 Suppose class String can be cast to char *
 cout << s; // cout expects char *; s is a String
 Compiler implicitly calls the function to convert s to char *
 Do not have to overload << for String
Case Study: A String Class
 Build class String
 String creation, manipulation
 Class string in standard library (more Chapter 15)
 Conversion constructor
 Single-argument constructor
 Turns objects of other types into class objects
 String s1(“hi”);
 Creates a String from a char *
 Any single-argument constructor is a conversion constructor
Overloading ++ and --
 Increment/decrement operators can be overloaded
 Add 1 to a Date object, d1
 Prototype (member function)
 Date &operator++();
 ++d1 same as d1.operator++()
 Prototype (non-member)
 Friend Date &operator++( Date &);
 ++d1 same as operator++( d1 )
Overloading ++ and --
 To distinguish pre/post increment
 Post increment has a dummy parameter
 int of 0
 Prototype (member function)
 Date operator++( int );
 d1++ same as d1.operator++( 0 )
 Prototype (non-member)
 friend Date operator++( Data &, int );
 d1++ same as operator++( d1, 0 )
 Integer parameter does not have a name
 Not even in function definition
Overloading ++ and --
 Return values
 Preincrement
 Returns by reference (Date &)
 lvalue (can be assigned)
 Postincrement
 Returns by value
 Returns temporary object with old value
 rvalue (cannot be on left side of assignment)
 Example Date class
 Overloaded increment operator
 Change day, month and year
 Overloaded += operator
 Function to test for leap years
 Function to determine if day is last of month
1 // Example 34
2 // Date class definition.
3 #ifndef DATE1_H
4 #define DATE1_H
5 #include <iostream>
6
7 using std::ostream;
8
9 class Date {
10 friend ostream &operator<<( ostream &, const Date & );
11
12 public:
13 Date( int m = 1, int d = 1, int y = 1900 ); // constructor
14 void setDate( int, int, int ); // set the date
15
16 Date &operator++(); // preincrement operator
17 Date operator++( int ); // postincrement operator
18
19 const Date &operator+=( int ); // add days, modify object
20
21 bool leapYear( int ) const; // is this a leap year?
22 bool endOfMonth( int ) const; // is this end of month?
Note difference between pre
and post increment.
23
24 private:
25 int month;
26 int day;
27 int year;
28
29 static const int days[]; // array of days per month
30 void helpIncrement(); // utility function
31
32 }; // end class Date
33
34 #endif
35 Date &Date::operator++()
36 {
37 helpIncrement();
37 return *this; // reference return to create an lvalue
39 } // end function operator++
40
41 // overloaded postincrement operator; note that the dummy
42 // integer parameter does not have a parameter name
43 Date Date::operator++( int )
44 {
45 Date temp = *this; // hold current state of object
46 helpIncrement();
48 // return unincremented, saved, temporary object
49 return temp; // value return; not a reference return
51 } // end function operator++
Inheritance
 Inheritance
 Software reusability
 Create new class from existing class
 Absorb existing class’s data and behaviors
 Enhance with new capabilities
 Derived class inherits from base class
 Derived class
More specialized group of objects
Behaviors inherited from base class
 Can customize
Additional behaviors
Inheritance
 Class hierarchy
 Direct base class
 Inherited explicitly (one level up hierarchy)
 Indirect base class
 Inherited two or more levels up hierarchy
 Single inheritance
 Inherits from one base class
 Multiple inheritance
 Inherits from multiple base classes
Base classes possibly unrelated
 Chapter 22
Inheritance
 Three types of inheritance
 public
 Every object of derived class also object of base class
Base-class objects not objects of derived classes
Example: All cars vehicles, but not all vehicles cars
 Can access non-private members of base class
Derived class can effect change to private base-class members
 Through inherited non-private member functions
 private
 Alternative to composition
 Chapter 17
 protected
 Rarely used
Inheritance
 Abstraction
 Focus on commonalities among objects in system
 “is-a” vs. “has-a”
 “is-a”
 Inheritance
 Derived class object treated as base class object
 Example: Car is a vehicle
Vehicle properties/behaviors also car properties/behaviors
 “has-a”
 Composition
 Object contains one or more objects of other classes as members
 Example: Car has a steering wheel
Base Classes and Derived Classes
 Base classes and derived classes
 Object of one class “is an” object of another class
 Example: Rectangle is quadrilateral.
 Base class typically represents larger set of objects than derived classes
 Example:
Base class: Vehicle
 Cars, trucks, boats, bicycles, …
Derived class: Car
 Smaller, more-specific subset of vehicles
Base Classes and Derived Classes
 Inheritance examples
Base class Derived classes
Student GraduateStudent
UndergraduateStudent
Shape Circle
Triangle
Rectangle
Loan CarLoan
HomeImprovementLoan
MortgageLoan
Employee FacultyMember
StaffMember
Account CheckingAccount
SavingsAccount
Base Classes and Derived Classes
 Inheritance hierarchy
 Inheritance relationships: tree-like hierarchy structure
 Each class becomes
 Base class
Supply data/behaviors to other classes
OR
 Derived class
Inherit data/behaviors from other classes
Single
inheritance
CommunityMember
Employee Student
Administrator Teacher
AdministratorTeacher
StaffFaculty
Alumnus
Single
inheritance
Single
inheritance
Multiple
inheritance
Fig. 9.2 Inheritance hierarchy for university CommunityMembers.
Inheritance hierarchy
Shape
TwoDimensionalShape ThreeDimensionalShape
Circle Square Triangle Sphere Cube Tetrahedron
Fig. 9.3 Inheritance hierarchy for Shapes.
Inheritance hierarchy
Base Classes and Derived Classes
 public inheritance
 Specify with:
Class TwoDimensionalShape : public Shape
 Class TwoDimensionalShape inherits from class Shape
 Base class private members
 Not accessible directly
 Still inherited - manipulate through inherited member functions
 Base class public and protected members
 Inherited with original member access
 friend functions
 Not inherited
protected Members
 protected access
 Intermediate level of protection between public and private
 protected members accessible to
 Base class members
 Base class friends
 Derived class members
 Derived class friends
 Derived-class members
 Refer to public and protected members of base class
Simply use member names
Relationship between Base Classes and Derived
Classes
 Base class and derived class relationship
 Example: Point/circle inheritance hierarchy
 Point
x-y coordinate pair
 Circle
x-y coordinate pair
Radius
Relationship between Base Classes and Derived
Classes
 Using protected data members
 Advantages
 Derived classes can modify values directly
 Slight increase in performance
Avoid set/get function call overhead
 Disadvantages
 No validity checking
Derived class can assign illegal value
 Implementation dependent
Derived class member functions more likely dependent on base class
implementation
Base class implementation changes may result in derived class modifications
 Fragile (brittle) software
Case Study: Three-Level Inheritance Hierarchy
 Three level point/circle/cylinder hierarchy
 Point
 x-y coordinate pair
 Circle
 x-y coordinate pair
 Radius
 Cylinder
 x-y coordinate pair
 Radius
 Height
Constructors and Destructors in Derived Classes
 Instantiating derived-class object
 Chain of constructor calls
 Derived-class constructor invokes base class constructor
Implicitly or explicitly
 Base of inheritance hierarchy
Last constructor called in chain
First constructor body to finish executing
Example: Point3/Circle4/Cylinder hierarchy
 Point3 constructor called last
 Point3 constructor body finishes execution first
 Initializing data members
Each base-class constructor initializes data members inherited by derived class
Constructors and Destructors in Derived Classes
 Destroying derived-class object
 Chain of destructor calls
 Reverse order of constructor chain
 Destructor of derived-class called first
 Destructor of next base class up hierarchy next
Continue up hierarchy until final base reached
 After final base-class destructor, object removed from memory
 Base-class constructors, destructors, assignment operators
 Not inherited by derived classes
 Derived class constructors, assignment operators can call
 Constructors
 Assignment operators
public, protected and private Inheritance
Type of inheritanceBase class
member
access
specifier
public
inheritance
protected
inheritance
private
inheritance
Public
public in derived class.
Can be accessed directly by any
non-static member functions,
friend functions and non-
member functions.
protected in derived class.
Can be accessed directly by all
non-static member functions
and friend functions.
private in derived class.
Can be accessed directly by all
non-static member functions
and friend functions.
Protected
protected in derived class.
Can be accessed directly by all
non-static member functions
and friend functions.
protected in derived class.
Can be accessed directly by all
non-static member functions
and friend functions.
private in derived class.
Can be accessed directly by all
non-static member functions
and friend functions.
Private
Hidden in derived class.
Can be accessed by non-static
member functions and friend
functions through public or
protected member functions
of the base class.
Hidden in derived class.
Can be accessed by non-static
member functions and friend
functions through public or
protected member functions
of the base class.
Hidden in derived class.
Can be accessed by non-static
member functions and friend
functions through public or
protected member functions
of the base class.
1 // Example 35
2 // Point class definition represents an x-y coordinate pair.
3 #ifndef POINT_H
4 #define POINT_H
5
6 class Point {
7
8 public:
9 Point( int = 0, int = 0 ); // default constructor
10
11 void setX( int ); // set x in coordinate pair
12 int getX() const; // return x from coordinate pair
13
14 void setY( int ); // set y in coordinate pair
15 int getY() const; // return y from coordinate pair
16
17 void print() const; // output Point object
18
19 private:
20 int x; // x part of coordinate pair
21 int y; // y part of coordinate pair
22
23 }; // end class Point
24
25 #endif
Maintain x- and y-
coordinates as private data
members.
1 // Example 36
2 // Circle2 class contains x-y coordinate pair and radius.
3 #ifndef CIRCLE2_H
4 #define CIRCLE2_H
5
6 #include "point.h" // Point class definition
7
8 class Circle2 : public Point {
9
10 public:
11
12 // default constructor
13 Circle2( int = 0, int = 0, double = 0.0 );
14
15 void setRadius( double ); // set radius
16 double getRadius() const; // return radius
17
18 double getDiameter() const; // return diameter
19 double getCircumference() const; // return circumference
20 double getArea() const; // return area
21
22 void print() const; // output Circle2 object
23
24 private:
25 double radius; // Circle2's radius
Class Circle2 inherits from
class Point.
Maintain private data
member radius.
Colon indicates inheritance.Keyword public indicates
type of inheritance.
26
27 }; // end class Circle2
28
29 #endif
1 // Fig. 9.11: circle2.cpp
2 // Circle2 class member-function definitions.
3 #include <iostream>
4
5 using std::cout;
6
7 #include "circle2.h" // Circle2 class definition
8
9 // default constructor
10 Circle2::Circle2( int xValue, int yValue, double radiusValue )
11 {
12 x = xValue;
13 y = yValue;
14 setRadius( radiusValue );
15
16 } // end Circle2 constructor
17
Attempting to access base
class Point’s private
data members x and y results
in syntax errors.
18 // set radius
19 void Circle2::setRadius( double radiusValue )
20 {
21 radius = ( radiusValue < 0.0 ? 0.0 : radiusValue );
22
23 } // end function setRadius
24
25 // return radius
26 double Circle2::getRadius() const
27 {
28 return radius;
29
30 } // end function getRadius
31
32 // calculate and return diameter
33 double Circle2::getDiameter() const
34 {
35 return 2 * radius;
36
37 } // end function getDiameter
38
39 // calculate and return circumference
40 double Circle2::getCircumference() const
41 {
42 return 3.14159 * getDiameter();
43
44 } // end function getCircumference
45
46 // calculate and return area
47 double Circle2::getArea() const
48 {
49 return 3.14159 * radius * radius;
50
51 } // end function getArea
52
53 // output Circle2 object
54 void Circle2::print() const
55 {
56 cout << "Center = [" << x << ", " << y << ']'
57 << "; Radius = " << radius;
58
59 } // end function print
Attempting to access base
class Point’s private
data members x and y results
in syntax errors.
1 // Example 37
2 // Point class definition represents an x-y coordinate pair.
3 #ifndef POINT_H
4 #define POINT_H
5
6 class Point {
7
8 public:
9 Point( int = 0, int = 0 ); // default constructor
10
11 void setX( int ); // set x in coordinate pair
12 int getX() const; // return x from coordinate pair
13
14 void setY( int ); // set y in coordinate pair
15 int getY() const; // return y from coordinate pair
16
17 void print() const; // output Point object
18
19 private:
20 int x; // x part of coordinate pair
21 int y; // y part of coordinate pair
22
23 }; // end class Point
24
25 #endif
Maintain x- and y-
coordinates as private data
members.
1 // Example 38
2 // Point class member-function definitions.
3 #include <iostream>
4
5 using std::cout;
6
7 #include "point.h" // Point class definition
8
9 // default constructor
10 Point::Point( int xValue, int yValue )
11 {
12 x = xValue;
13 y = yValue;
14
15 } // end Point constructor
16
17 // set x in coordinate pair
18 void Point::setX( int xValue )
19 {
20 x = xValue; // no need for validation
21
22 } // end function setX
23
24 // return x from coordinate pair
25 int Point::getX() const
26 {
27 return x;
28
29 } // end function getX
30
31 // set y in coordinate pair
32 void Point::setY( int yValue )
33 {
34 y = yValue; // no need for validation
35
36 } // end function setY
37
38 // return y from coordinate pair
39 int Point::getY() const
40 {
41 return y;
42
43 } // end function getY
44
45 // output Point object
46 void Point::print() const
47 {
48 cout << '[' << x << ", " << y << ']';
49
50 } // end function print
1 // Example 39
2 // Testing class Point.
3 #include <iostream>
4
5 using std::cout;
6 using std::endl;
7
8 #include "point.h" // Point class definition
9
10 int main()
11 {
12 Point point( 72, 115 ); // instantiate Point object
13
14 // display point coordinates
15 cout << "X coordinate is " << point.getX()
16 << "nY coordinate is " << point.getY();
17
18 point.setX( 10 ); // set x-coordinate
19 point.setY( 10 ); // set y-coordinate
20
21 // display new point value
22 cout << "nnThe new location of point is ";
23 point.print();
24 cout << endl;
25
Create a Point object.
Invoke set functions to
modify private data.
Invoke public function
print to display new
coordinates.
26 return 0; // indicates successful termination
27
28 } // end main
X coordinate is 72
Y coordinate is 115
The new location of point is [10, 10]
1 // Example 40
2 // Circle class contains x-y coordinate pair and radius.
3 #ifndef CIRCLE_H
4 #define CIRCLE_H
5
6 class Circle {
7
8 public:
9
10 // default constructor
11 Circle( int = 0, int = 0, double = 0.0 );
12
13 void setX( int ); // set x in coordinate pair
14 int getX() const; // return x from coordinate pair
15
16 void setY( int ); // set y in coordinate pair
17 int getY() const; // return y from coordinate pair
18
19 void setRadius( double ); // set radius
20 double getRadius() const; // return radius
21
22 double getDiameter() const; // return diameter
23 double getCircumference() const; // return circumference
24 double getArea() const; // return area
25
Note code similar to Point
code.
26 void print() const; // output Circle object
27
28 private:
29 int x; // x-coordinate of Circle's center
30 int y; // y-coordinate of Circle's center
31 double radius; // Circle's radius
32
33 }; // end class Circle
34
35 #endif
Maintain x-y coordinates and
radius as private data
members.
Note code similar to Point
code.
1 // Example 41
2 // Circle class member-function definitions.
3 #include <iostream>
4
5 using std::cout;
6
7 #include "circle.h" // Circle class definition
8
9 // default constructor
10 Circle::Circle( int xValue, int yValue, double radiusValue )
11 {
12 x = xValue;
13 y = yValue;
14 setRadius( radiusValue );
15
16 } // end Circle constructor
17
18 // set x in coordinate pair
19 void Circle::setX( int xValue )
20 {
21 x = xValue; // no need for validation
22
23 } // end function setX
24
25 // return x from coordinate pair
26 int Circle::getX() const
27 {
28 return x;
29
30 } // end function getX
31
32 // set y in coordinate pair
33 void Circle::setY( int yValue )
34 {
35 y = yValue; // no need for validation
36
37 } // end function setY
38
39 // return y from coordinate pair
40 int Circle::getY() const
41 {
42 return y;
43
44 } // end function getY
45
46 // set radius
47 void Circle::setRadius( double radiusValue )
48 {
49 radius = ( radiusValue < 0.0 ? 0.0 : radiusValue );
50
51 } // end function setRadius
52
53 // return radius
54 double Circle::getRadius() const
55 {
56 return radius;
57
58 } // end function getRadius
59
60 // calculate and return diameter
61 double Circle::getDiameter() const
62 {
63 return 2 * radius;
64
65 } // end function getDiameter
66
Ensure non-negative value for
radius.
67 // calculate and return circumference
68 double Circle::getCircumference() const
69 {
70 return 3.14159 * getDiameter();
71
72 } // end function getCircumference
73
74 // calculate and return area
75 double Circle::getArea() const
76 {
77 return 3.14159 * radius * radius;
78
79 } // end function getArea
80
81 // output Circle object
82 void Circle::print() const
83 {
84 cout << "Center = [" << x << ", " << y << ']'
85 << "; Radius = " << radius;
86
87 } // end function print
1 // Example 42
2 // Testing class Circle.
3 #include <iostream>
4
5 using std::cout;
6 using std::endl;
7 using std::fixed;
8
9 #include <iomanip>
10
11 using std::setprecision;
12
13 #include "circle.h" // Circle class definition
14
15 int main()
16 {
17 Circle circle( 37, 43, 2.5 ); // instantiate Circle object
18
19 // display point coordinates
20 cout << "X coordinate is " << circle.getX()
21 << "nY coordinate is " << circle.getY()
22 << "nRadius is " << circle.getRadius();
23
Create Circle object.
24 circle.setX( 2 ); // set new x-coordinate
25 circle.setY( 2 ); // set new y-coordinate
26 circle.setRadius( 4.25 ); // set new radius
27
28 // display new point value
29 cout << "nnThe new location and radius of circle aren";
30 circle.print();
31
32 // display floating-point values with 2 digits of precision
33 cout << fixed << setprecision( 2 );
34
35 // display Circle's diameter
36 cout << "nDiameter is " << circle.getDiameter();
37
38 // display Circle's circumference
39 cout << "nCircumference is " << circle.getCircumference();
40
41 // display Circle's area
42 cout << "nArea is " << circle.getArea();
43
44 cout << endl;
45
46 return 0; // indicates successful termination
47
48 } // end main
Use set functions to modify
private data.
Invoke public function
print to display new
coordinates.
X coordinate is 37
Y coordinate is 43
Radius is 2.5
The new location and radius of circle are
Center = [2, 2]; Radius = 4.25
Diameter is 8.50
Circumference is 26.70
Area is 56.74
1 // Example 43
2 // Circle2 class contains x-y coordinate pair and radius.
3 #ifndef CIRCLE2_H
4 #define CIRCLE2_H
5
6 #include "point.h" // Point class definition
7
8 class Circle2 : public Point {
9
10 public:
11
12 // default constructor
13 Circle2( int = 0, int = 0, double = 0.0 );
14
15 void setRadius( double ); // set radius
16 double getRadius() const; // return radius
17
18 double getDiameter() const; // return diameter
19 double getCircumference() const; // return circumference
20 double getArea() const; // return area
21
22 void print() const; // output Circle2 object
23
24 private:
25 double radius; // Circle2's radius
Class Circle2 inherits from
class Point.
Maintain private data
member radius.
Colon indicates inheritance.Keyword public indicates
type of inheritance.
26
27 }; // end class Circle2
28
29 #endif
1 // Fig. 9.11: circle2.cpp
2 // Circle2 class member-function definitions.
3 #include <iostream>
4
5 using std::cout;
6
7 #include "circle2.h" // Circle2 class definition
8
9 // default constructor
10 Circle2::Circle2( int xValue, int yValue, double radiusValue )
11 {
12 x = xValue;
13 y = yValue;
14 setRadius( radiusValue );
15
16 } // end Circle2 constructor
17
Attempting to access base
class Point’s private
data members x and y results
in syntax errors.
18 // set radius
19 void Circle2::setRadius( double radiusValue )
20 {
21 radius = ( radiusValue < 0.0 ? 0.0 : radiusValue );
22
23 } // end function setRadius
24
25 // return radius
26 double Circle2::getRadius() const
27 {
28 return radius;
29
30 } // end function getRadius
31
32 // calculate and return diameter
33 double Circle2::getDiameter() const
34 {
35 return 2 * radius;
36
37 } // end function getDiameter
38
39 // calculate and return circumference
40 double Circle2::getCircumference() const
41 {
42 return 3.14159 * getDiameter();
43
44 } // end function getCircumference
45
46 // calculate and return area
47 double Circle2::getArea() const
48 {
49 return 3.14159 * radius * radius;
50
51 } // end function getArea
52
53 // output Circle2 object
54 void Circle2::print() const
55 {
56 cout << "Center = [" << x << ", " << y << ']'
57 << "; Radius = " << radius;
58
59 } // end function print
Attempting to access base
class Point’s private
data members x and y results
in syntax errors.
C:cpphtp4examplesch09CircleTestcircle2.cpp(12) : error C2248: 'x' : cannot access private
member declared in class 'Point'
C:cpphtp4examplesch09circletestpoint.h(20) :
see declaration of 'x'
C:cpphtp4examplesch09CircleTestcircle2.cpp(13) : error C2248: 'y' : cannot access private
member declared in class 'Point'
C:cpphtp4examplesch09circletestpoint.h(21) :
see declaration of 'y'
C:cpphtp4examplesch09CircleTestcircle2.cpp(56) : error C2248: 'x' : cannot access private
member declared in class 'Point'
C:cpphtp4examplesch09circletestpoint.h(20) :
see declaration of 'x'
C:cpphtp4examplesch09CircleTestcircle2.cpp(56) : error C2248: 'y' : cannot access private
member declared in class 'Point'
C:cpphtp4examplesch09circletestpoint.h(21) :
see declaration of 'y'
Attempting to access base
class Point’s private
data members x and y results
in syntax errors.
1 // Example 44
2 // Point2 class definition represents an x-y coordinate pair.
3 #ifndef POINT2_H
4 #define POINT2_H
5
6 class Point2 {
7
8 public:
9 Point2( int = 0, int = 0 ); // default constructor
10
11 void setX( int ); // set x in coordinate pair
12 int getX() const; // return x from coordinate pair
13
14 void setY( int ); // set y in coordinate pair
15 int getY() const; // return y from coordinate pair
16
17 void print() const; // output Point2 object
18
19 protected:
20 int x; // x part of coordinate pair
21 int y; // y part of coordinate pair
22
23 }; // end class Point2
24
25 #endif
Maintain x- and y-
coordinates as protected
data, accessible to derived
classes.
1 // Example 45
2 // Point2 class member-function definitions.
3 #include <iostream>
4
5 using std::cout;
6
7 #include "point2.h" // Point2 class definition
8
9 // default constructor
10 Point2::Point2( int xValue, int yValue )
11 {
12 x = xValue;
13 y = yValue;
14
15 } // end Point2 constructor
16
17 // set x in coordinate pair
18 void Point2::setX( int xValue )
19 {
20 x = xValue; // no need for validation
21
22 } // end function setX
23
24 // return x from coordinate pair
25 int Point2::getX() const
26 {
27 return x;
28
29 } // end function getX
30
31 // set y in coordinate pair
32 void Point2::setY( int yValue )
33 {
34 y = yValue; // no need for validation
35
36 } // end function setY
37
38 // return y from coordinate pair
39 int Point2::getY() const
40 {
41 return y;
42
43 } // end function getY
44
45 // output Point2 object
46 void Point2::print() const
47 {
48 cout << '[' << x << ", " << y << ']';
49
50 } // end function print
1 // Example 46
2 // Circle3 class contains x-y coordinate pair and radius.
3 #ifndef CIRCLE3_H
4 #define CIRCLE3_H
5
6 #include "point2.h" // Point2 class definition
7
8 class Circle3 : public Point2 {
9
10 public:
11
12 // default constructor
13 Circle3( int = 0, int = 0, double = 0.0 );
14
15 void setRadius( double ); // set radius
16 double getRadius() const; // return radius
17
18 double getDiameter() const; // return diameter
19 double getCircumference() const; // return circumference
20 double getArea() const; // return area
21
22 void print() const; // output Circle3 object
23
24 private:
25 double radius; // Circle3's radius
Class Circle3 inherits from
class Point2.
Maintain private data
member radius.
26
27 }; // end class Circle3
28
29 #endif
1 // Example 47
2 // Circle3 class member-function definitions.
3 #include <iostream>
4
5 using std::cout;
6
7 #include "circle3.h" // Circle3 class definition
8
9 // default constructor
10 Circle3::Circle3( int xValue, int yValue, double radiusValue )
11 {
12 x = xValue;
13 y = yValue;
14 setRadius( radiusValue );
15
16 } // end Circle3 constructor
17
18 // set radius
19 void Circle3::setRadius( double radiusValue )
20 {
21 radius = ( radiusValue < 0.0 ? 0.0 : radiusValue );
22
23 } // end function setRadius
24
Modify inherited data
members x and y, declared
protected in base class
Point2.
Constructor first implicitly
calls base class’s default
constructor.
25 // return radius
26 double Circle3::getRadius() const
27 {
28 return radius;
29
30 } // end function getRadius
31
32 // calculate and return diameter
33 double Circle3::getDiameter() const
34 {
35 return 2 * radius;
36
37 } // end function getDiameter
38
39 // calculate and return circumference
40 double Circle3::getCircumference() const
41 {
42 return 3.14159 * getDiameter();
43
44 } // end function getCircumference
45
46 // calculate and return area
47 double Circle3::getArea() const
48 {
49 return 3.14159 * radius * radius;
50
51 } // end function getArea
52
53 // output Circle3 object
54 void Circle3::print() const
55 {
56 cout << "Center = [" << x << ", " << y << ']'
57 << "; Radius = " << radius;
58
59 } // end function print
Access inherited data
members x and y, declared
protected in base class
Point2.
1 // Example 48
2 // Testing class Circle3.
3 #include <iostream>
4
5 using std::cout;
6 using std::endl;
7 using std::fixed;
8
9 #include <iomanip>
10
11 using std::setprecision;
12
13 #include "circle3.h" // Circle3 class definition
14
15 int main()
16 {
17 Circle3 circle( 37, 43, 2.5 ); // instantiate Circle3 object
18
19 // display point coordinates
20 cout << "X coordinate is " << circle.getX()
21 << "nY coordinate is " << circle.getY()
22 << "nRadius is " << circle.getRadius();
23
Use inherited get functions to
access inherited protected
data x and y.
Create Circle3 object.
Use Circle3 get function to
access private data
radius.
24 circle.setX( 2 ); // set new x-coordinate
25 circle.setY( 2 ); // set new y-coordinate
26 circle.setRadius( 4.25 ); // set new radius
27
28 // display new point value
29 cout << "nnThe new location and radius of circle aren";
30 circle.print();
31
32 // display floating-point values with 2 digits of precision
33 cout << fixed << setprecision( 2 );
34
35 // display Circle3's diameter
36 cout << "nDiameter is " << circle.getDiameter();
37
38 // display Circle3's circumference
39 cout << "nCircumference is " << circle.getCircumference();
40
41 // display Circle3's area
42 cout << "nArea is " << circle.getArea();
43
44 cout << endl;
45
46 return 0; // indicates successful termination
47
48 } // end main
Use inherited set functions to
modify inherited
protected data x and y.
Use Circle3 set function to
modify private data
radius.
X coordinate is 37
Y coordinate is 43
Radius is 2.5
The new location and radius of circle are
Center = [2, 2]; Radius = 4.25
Diameter is 8.50
Circumference is 26.70
Area is 56.74
Relationship between Base Classes and
Derived Classes
 Using protected data members
 Advantages
 Derived classes can modify values directly
 Slight increase in performance
Avoid set/get function call overhead
 Disadvantages
 No validity checking
Derived class can assign illegal value
 Implementation dependent
Derived class member functions more likely dependent on base class
implementation
Base class implementation changes may result in derived class modifications
 Fragile (brittle) software
1 // Example 49
2 // Point3 class definition represents an x-y coordinate pair.
3 #ifndef POINT3_H
4 #define POINT3_H
5
6 class Point3 {
7
8 public:
9 Point3( int = 0, int = 0 ); // default constructor
10
11 void setX( int ); // set x in coordinate pair
12 int getX() const; // return x from coordinate pair
13
14 void setY( int ); // set y in coordinate pair
15 int getY() const; // return y from coordinate pair
16
17 void print() const; // output Point3 object
18
19 private:
20 int x; // x part of coordinate pair
21 int y; // y part of coordinate pair
22
23 }; // end class Point3
24
25 #endif
Better software-engineering
practice: private over
protected when possible.
1 // Example 50
2 // Point3 class member-function definitions.
3 #include <iostream>
4
5 using std::cout;
6
7 #include "point3.h" // Point3 class definition
8
9 // default constructor
10 Point3::Point3( int xValue, int yValue )
11 : x( xValue ), y( yValue )
12 {
13 // empty body
14
15 } // end Point3 constructor
16
17 // set x in coordinate pair
18 void Point3::setX( int xValue )
19 {
20 x = xValue; // no need for validation
21
22 } // end function setX
23
Member initializers specify
values of x and y.
24 // return x from coordinate pair
25 int Point3::getX() const
26 {
27 return x;
28
29 } // end function getX
30
31 // set y in coordinate pair
32 void Point3::setY( int yValue )
33 {
34 y = yValue; // no need for validation
35
36 } // end function setY
37
38 // return y from coordinate pair
39 int Point3::getY() const
40 {
41 return y;
42
43 } // end function getY
44
45 // output Point3 object
46 void Point3::print() const
47 {
48 cout << '[' << getX() << ", " << getY() << ']';
49
50 } // end function print
Invoke non-private
member functions to access
private data.
1 // Example 51
2 // Circle4 class contains x-y coordinate pair and radius.
3 #ifndef CIRCLE4_H
4 #define CIRCLE4_H
5
6 #include "point3.h" // Point3 class definition
7
8 class Circle4 : public Point3 {
9
10 public:
11
12 // default constructor
13 Circle4( int = 0, int = 0, double = 0.0 );
14
15 void setRadius( double ); // set radius
16 double getRadius() const; // return radius
17
18 double getDiameter() const; // return diameter
19 double getCircumference() const; // return circumference
20 double getArea() const; // return area
21
22 void print() const; // output Circle4 object
23
24 private:
25 double radius; // Circle4's radius
Class Circle4 inherits from
class Point3.
Maintain private data
member radius.
26
27 }; // end class Circle4
28
29 #endif
1 // Example 52
2 // Circle4 class member-function definitions.
3 #include <iostream>
4
5 using std::cout;
6
7 #include "circle4.h" // Circle4 class definition
8
9 // default constructor
10 Circle4::Circle4( int xValue, int yValue, double radiusValue )
11 : Point3( xValue, yValue ) // call base-class constructor
12 {
13 setRadius( radiusValue );
14
15 } // end Circle4 constructor
16
17 // set radius
18 void Circle4::setRadius( double radiusValue )
19 {
20 radius = ( radiusValue < 0.0 ? 0.0 : radiusValue );
21
22 } // end function setRadius
23
Base-class initializer syntax
passes arguments to base
class Point3.
24 // return radius
25 double Circle4::getRadius() const
26 {
27 return radius;
28
29 } // end function getRadius
30
31 // calculate and return diameter
32 double Circle4::getDiameter() const
33 {
34 return 2 * getRadius();
35
36 } // end function getDiameter
37
38 // calculate and return circumference
39 double Circle4::getCircumference() const
40 {
41 return 3.14159 * getDiameter();
42
43 } // end function getCircumference
44
Invoke function getRadius
rather than directly accessing
data member radius.
45 // calculate and return area
46 double Circle4::getArea() const
47 {
48 return 3.14159 * getRadius() * getRadius();
49
50 } // end function getArea
51
52 // output Circle4 object
53 void Circle4::print() const
54 {
55 cout << "Center = ";
56 Point3::print(); // invoke Point3's print function
57 cout << "; Radius = " << getRadius();
58
59 } // end function print
Invoke function getRadius
rather than directly accessing
data member radius.
Redefine class Point3’s
member function print.
Invoke base-class Point3’s
print function using binary
scope-resolution operator
(::).
1 // Example 53
2 // Testing class Circle4.
3 #include <iostream>
4
5 using std::cout;
6 using std::endl;
7 using std::fixed;
8
9 #include <iomanip>
10
11 using std::setprecision;
12
13 #include "circle4.h" // Circle4 class definition
14
15 int main()
16 {
17 Circle4 circle( 37, 43, 2.5 ); // instantiate Circle4 object
18
19 // display point coordinates
20 cout << "X coordinate is " << circle.getX()
21 << "nY coordinate is " << circle.getY()
22 << "nRadius is " << circle.getRadius();
23
Create Circle4 object.
Use inherited get functions to
access inherited protected
data x and y.
Use Circle3 get function to
access private data
radius.
24 circle.setX( 2 ); // set new x-coordinate
25 circle.setY( 2 ); // set new y-coordinate
26 circle.setRadius( 4.25 ); // set new radius
27
28 // display new circle value
29 cout << "nnThe new location and radius of circle aren";
30 circle.print();
31
32 // display floating-point values with 2 digits of precision
33 cout << fixed << setprecision( 2 );
34
35 // display Circle4's diameter
36 cout << "nDiameter is " << circle.getDiameter();
37
38 // display Circle4's circumference
39 cout << "nCircumference is " << circle.getCircumference();
40
41 // display Circle4's area
42 cout << "nArea is " << circle.getArea();
43
44 cout << endl;
45
46 return 0; // indicates successful termination
47
48 } // end main
Use inherited set functions to
modify inherited
protected data x and y.Use Circle3 set function to
modify private data
radius.
X coordinate is 37
Y coordinate is 43
Radius is 2.5
The new location and radius of circle are
Center = [2, 2]; Radius = 4.25
Diameter is 8.50
Circumference is 26.70
Area is 56.74
Case Study: Three-Level Inheritance
Hierarchy
 Three level point/circle/cylinder hierarchy
 Point
 x-y coordinate pair
 Circle
 x-y coordinate pair
 Radius
 Cylinder
 x-y coordinate pair
 Radius
 Height
1 // Example 54
2 // Cylinder class inherits from class Circle4.
3 #ifndef CYLINDER_H
4 #define CYLINDER_H
5
6 #include "circle4.h" // Circle4 class definition
7
8 class Cylinder : public Circle4 {
9
10 public:
11
12 // default constructor
13 Cylinder( int = 0, int = 0, double = 0.0, double = 0.0 );
14
15 void setHeight( double ); // set Cylinder's height
16 double getHeight() const; // return Cylinder's height
17
18 double getArea() const; // return Cylinder's area
19 double getVolume() const; // return Cylinder's volume
20 void print() const; // output Cylinder
21
22 private:
23 double height; // Cylinder's height
24
25 }; // end class Cylinder
Class Cylinder inherits
from class Circle4.
Maintain private data
member height.
26
27 #endif
1 // Fig. 9.23: cylinder.cpp
2 // Cylinder class inherits from class Circle4.
3 #include <iostream>
4
5 using std::cout;
6
7 #include "cylinder.h" // Cylinder class definition
8
9 // default constructor
10 Cylinder::Cylinder( int xValue, int yValue, double radiusValue,
11 double heightValue )
12 : Circle4( xValue, yValue, radiusValue )
13 {
14 setHeight( heightValue );
15
16 } // end Cylinder constructor
17
Base-class initializer syntax
passes arguments to base
class Circle4.
18 // set Cylinder's height
19 void Cylinder::setHeight( double heightValue )
20 {
21 height = ( heightValue < 0.0 ? 0.0 : heightValue );
22
23 } // end function setHeight
24
25 // get Cylinder's height
26 double Cylinder::getHeight() const
27 {
28 return height;
29
30 } // end function getHeight
31
32 // redefine Circle4 function getArea to calculate Cylinder area
33 double Cylinder::getArea() const
34 {
35 return 2 * Circle4::getArea() +
36 getCircumference() * getHeight();
37
38 } // end function getArea
39
Redefine base class
Circle4’s member function
getArea to return
Cylinder surface area.
Invoke base-class
Circle4’s getArea
function using binary scope-
resolution operator (::).
40 // calculate Cylinder volume
41 double Cylinder::getVolume() const
42 {
43 return Circle4::getArea() * getHeight();
44
45 } // end function getVolume
46
47 // output Cylinder object
48 void Cylinder::print() const
49 {
50 Circle4::print();
51 cout << "; Height = " << getHeight();
52
53 } // end function print
Redefine class Circle4’s
member function print.Invoke base-class
Circle4’s print function
using binary scope-resolution
operator (::).
Invoke base-class
Circle4’s getArea
function using binary scope-
resolution operator (::).
1 // Example 55
2 // Testing class Cylinder.
3 #include <iostream>
4
5 using std::cout;
6 using std::endl;
7 using std::fixed;
8
9 #include <iomanip>
10
11 using std::setprecision;
12
13 #include "cylinder.h" // Cylinder class definition
14
15 int main()
16 {
17 // instantiate Cylinder object
18 Cylinder cylinder( 12, 23, 2.5, 5.7 );
19
20 // display point coordinates
21 cout << "X coordinate is " << cylinder.getX()
22 << "nY coordinate is " << cylinder.getY()
23 << "nRadius is " << cylinder.getRadius()
24 << "nHeight is " << cylinder.getHeight();
25
Invoke indirectly inherited
Point3 member functions.
Invoke directly inherited
Circle4 member function.
Invoke Cylinder member
function.
26 cylinder.setX( 2 ); // set new x-coordinate
27 cylinder.setY( 2 ); // set new y-coordinate
28 cylinder.setRadius( 4.25 ); // set new radius
29 cylinder.setHeight( 10 ); // set new height
30
31 // display new cylinder value
32 cout << "nnThe new location and radius of circle aren";
33 cylinder.print();
34
35 // display floating-point values with 2 digits of precision
36 cout << fixed << setprecision( 2 );
37
38 // display cylinder's diameter
39 cout << "nnDiameter is " << cylinder.getDiameter();
40
41 // display cylinder's circumference
42 cout << "nCircumference is "
43 << cylinder.getCircumference();
44
45 // display cylinder's area
46 cout << "nArea is " << cylinder.getArea();
47
48 // display cylinder's volume
49 cout << "nVolume is " << cylinder.getVolume();
50
Invoke indirectly inherited
Point3 member functions.
Invoke directly inherited
Circle4 member function.Invoke Cylinder member
function.
Invoke redefined print
function.
Invoke redefined getArea
function.
51 cout << endl;
52
53 return 0; // indicates successful termination
54
55 } // end main
X coordinate is 12
Y coordinate is 23
Radius is 2.5
Height is 5.7
The new location and radius of circle are
Center = [2, 2]; Radius = 4.25; Height = 10
Diameter is 8.50
Circumference is 26.70
Area is 380.53
Volume is 567.45
Software Engineering with Inheritance
 Customizing existing software
 Inherit from existing classes
 Include additional members
 Redefine base-class members
 No direct access to base class’s source code
Link to object code
 Independent software vendors (ISVs)
 Develop proprietary code for sale/license
Available in object-code format
 Users derive new classes
Without accessing ISV proprietary source code
Introduction
 Polymorphism
 “Program in the general”
 Derived-class object can be treated as base-class object
 “is-a” relationship
 Base class is not a derived class object
 Virtual functions and dynamic binding
 Makes programs extensible
 New classes added easily, can still be processed
 Examples
 Use abstract base class Shape
 Defines common interface (functionality)
 Point, Circle and Cylinder inherit from Shape
Polymorphism
Invoking Base-Class Functions from Derived-
Class Objects
 Pointers to base/derived objects
 Base pointer aimed at derived object
 “is a” relationship
Circle “is a” Point
 Will invoke base class functions
 Can cast base-object’s address to derived-class pointer
 Called down-casting
 Allows derived-class functionality
 Key point
 Base-pointer can aim at derived-object - but can only call base-class functions
 Data type of pointer/reference determines functions it can call
1 // Example 56
2 // Aiming base-class and derived-class pointers at base-class
3 // and derived-class objects, respectively.
4 #include <iostream>
5
6 using std::cout;
7 using std::endl;
8 using std::fixed;
9
10 #include <iomanip>
11
12 using std::setprecision;
13
14 #include "point.h" // Point class definition
15 #include "circle.h" // Circle class definition
16
17 int main()
18 {
19 Point point( 30, 50 );
20 Point *pointPtr = 0; // base-class pointer
21
22 Circle circle( 120, 89, 2.7 );
23 Circle *circlePtr = 0; // derived-class pointer
24
25 // set floating-point numeric formatting
26 cout << fixed << setprecision( 2 );
27
28 // output objects point and circle
29 cout << "Print point and circle objects:"
30 << "nPoint: ";
31 point.print(); // invokes Point's print
32 cout << "nCircle: ";
33 circle.print(); // invokes Circle's print
34
35 // aim base-class pointer at base-class object and print
36 pointPtr = &point;
37 cout << "nnCalling print with base-class pointer to "
38 << "nbase-class object invokes base-class print "
39 << "function:n";
40 pointPtr->print(); // invokes Point's print
41
42 // aim derived-class pointer at derived-class object
43 // and print
44 circlePtr = &circle;
45 cout << "nnCalling print with derived-class pointer to "
46 << "nderived-class object invokes derived-class "
47 << "print function:n";
48 circlePtr->print(); // invokes Circle's print
49
Use objects and pointers to
call the print function. The
pointers and objects are of the
same class, so the proper
print function is called.
50 // aim base-class pointer at derived-class object and print
51 pointPtr = &circle;
52 cout << "nnCalling print with base-class pointer to "
53 << "derived-class objectninvokes base-class print "
54 << "function on that derived-class object:n";
55 pointPtr->print(); // invokes Point's print
56 cout << endl;
57
58 return 0;
59
60 } // end main
Aiming a base-class pointer at
a derived object is allowed
(the Circle “is a” Point).
However, it calls Point’s
print function, determined by
the pointer type. virtual
functions allow us to change
this.
1 // Example 57
2 // Aiming a derived-class pointer at a base-class object.
3 #include "point.h" // Point class definition
4 #include "circle.h" // Circle class definition
5
6 int main()
7 {
8 Point point( 30, 50 );
9 Circle *circlePtr = 0;
10
11 // aim derived-class pointer at base-class object
12 circlePtr = &point; // Error: a Point is not a Circle
13
14 return 0;
15
16 } // end main
C:cpphtp4examplesch10fig10_06Fig10_06.cpp(12) : error C2440:
'=' : cannot convert from 'class Point *' to 'class Circle *'
Types pointed to are unrelated; conversion requires
reinterpret_cast, C-style cast or function-style cast
1 // Example 58
2 // Attempting to invoke derived-class-only member functions
3 // through a base-class pointer.
4 #include "point.h" // Point class definition
5 #include "circle.h" // Circle class definition
6
7 int main()
8 {
9 Point *pointPtr = 0;
10 Circle circle( 120, 89, 2.7 );
11
12 // aim base-class pointer at derived-class object
13 pointPtr = &circle;
14
15 // invoke base-class member functions on derived-class
16 // object through base-class pointer
17 int x = pointPtr->getX();
18 int y = pointPtr->getY();
19 pointPtr->setX( 10 );
20 pointPtr->setY( 10 );
21 pointPtr->print();
22
23 // attempt to invoke derived-class-only member functions
24 // on derived-class object through base-class pointer
25 double radius = pointPtr->getRadius();
26 pointPtr->setRadius( 33.33 );
27 double diameter = pointPtr->getDiameter();
28 double circumference = pointPtr->getCircumference();
29 double area = pointPtr->getArea();
30
31 return 0;
32
33 } // end main
These functions are only
defined in Circle.
However, pointPtr is of
class Point.
Virtual Functions
 virtual functions
 Object (not pointer) determines function called
 Why useful?
 Suppose Circle, Triangle, Rectangle derived from Shape
 Each has own draw function
 To draw any shape
 Have base class Shape pointer, call draw
 Program determines proper draw function at run time (dynamically)
 Treat all shapes generically
Virtual Functions
 Declare draw as virtual in base class
 Override draw in each derived class
 Like redefining, but new function must have same signature
 If function declared virtual, can only be overridden
 virtual void draw() const;
 Once declared virtual, virtual in all derived classes
Good practice to explicitly declare virtual
 Dynamic binding
 Choose proper function to call at run time
 Only occurs off pointer handles
 If function called from object, uses that object’s definition
Virtual Functions
 Polymorphism
 Same message, “print”, given to many objects
 All through a base pointer
 Message takes on “many forms”
 Summary
 Base-pointer to base-object, derived-pointer to derived
 Straightforward
 Base-pointer to derived object
 Can only call base-class functions
 Derived-pointer to base-object
 Compiler error
 Allowed if explicit cast made
Polymorphism Examples
 Suppose designing video game
 Base class SpaceObject
 Derived Martian, SpaceShip, LaserBeam
 Base function draw
 To refresh screen
 Screen manager has vector of base-class pointers to objects
 Send draw message to each object
 Same message has “many forms” of results
 Easy to add class Mercurian
 Inherits from SpaceObject
 Provides own definition for draw
 Screen manager does not need to change code
 Calls draw regardless of object’s type
 Mercurian objects “plug right in”
Type Fields and switch
Structures
 One way to determine object's class
 Give base class an attribute
 shapeType in class Shape
 Use switch to call proper print function
 Many problems
 May forget to test for case in switch
 If add/remove a class, must update switch structures
 Time consuming and error prone
 Better to use polymorphism
 Less branching logic, simpler programs, less debugging
Abstract Classes
 Abstract classes
 Sole purpose: to be a base class (called abstract base classes)
 Incomplete
 Derived classes fill in "missing pieces"
 Cannot make objects from abstract class
 However, can have pointers and references
 Concrete classes
 Can instantiate objects
 Implement all functions they define
 Provide specifics
Abstract Classes
 Abstract classes not required, but helpful
 To make a class abstract
 Need one or more "pure" virtual functions
 Declare function with initializer of 0
virtual void draw() const = 0;
 Regular virtual functions
 Have implementations, overriding is optional
 Pure virtual functions
 No implementation, must be overridden
 Abstract classes can have data and concrete functions
 Required to have one or more pure virtual functions
Case Study: Inheriting Interface
and Implementation
 Make abstract base class Shape
 Pure virtual functions (must be implemented)
 getName, print
 Default implementation does not make sense
 Virtual functions (may be redefined)
 getArea, getVolume
Initially return 0.0
 If not redefined, uses base class definition
 Derive classes Point, Circle, Cylinder
Case Study: Inheriting Interface
and Implementation
0.0 0.0 = 0 = 0
0.0 0.0 "Point" [x,y]
pr2 0.0 "Circle" center=[x,y];
radius=r
2pr2 +2prh pr2h "Cylinder"
center=[x,y];
radius=r;
height=h
getArea printgetNamegetVolume
Shape
Point
Circle
Cylinder
1 // Example 59
2 // Shape abstract-base-class definition.
3 #ifndef SHAPE_H
4 #define SHAPE_H
5
6 #include <string> // C++ standard string class
7
8 using std::string;
9
10 class Shape {
11
12 public:
13
14 // virtual function that returns shape area
15 virtual double getArea() const;
16
17 // virtual function that returns shape volume
18 virtual double getVolume() const;
19
20 // pure virtual functions; overridden in derived classes
21 virtual string getName() const = 0; // return shape name
22 virtual void print() const = 0; // output shape
23
24 }; // end class Shape
25
26 #endif
Virtual and pure virtual
functions.
1 // Example 60
2 // Shape class member-function definitions.
3 #include <iostream>
4
5 using std::cout;
6
7 #include "shape.h" // Shape class definition
8
9 // return area of shape; 0.0 by default
10 double getArea() const
11 {
12 return 0.0;
13
14 } // end function getArea
15
16 // return volume of shape; 0.0 by default
17 double getVolume() const
18 {
19 return 0.0;
20
21 } // end function getVolume
Polymorphism, Virtual Functions and
Dynamic Binding “Under the Hood”
 Polymorphism has overhead
 Not used in STL (Standard Template Library) to optimize performance
 virtual function table (vtable)
 Every class with a virtual function has a vtable
 For every virtual function, vtable has pointer to the proper function
 If derived class has same function as base class
 Function pointer aims at base-class function
Virtual Destructors
 Base class pointer to derived object
 If destroyed using delete, behavior unspecified
 Simple fix
 Declare base-class destructor virtual
 Makes derived-class destructors virtual
 Now, when delete used appropriate destructor called
 When derived-class object destroyed
 Derived-class destructor executes first
 Base-class destructor executes afterwards
 Constructors cannot be virtual
Case Study: Payroll System Using
Polymorphism
 Create a payroll program
 Use virtual functions and polymorphism
 Problem statement
 4 types of employees, paid weekly
 Salaried (fixed salary, no matter the hours)
 Hourly (overtime [>40 hours] pays time and a half)
 Commission (paid percentage of sales)
 Base-plus-commission (base salary + percentage of sales)
Boss wants to raise pay by 10%
Payroll System Using
Polymorphism
 Base class Employee
 Pure virtual function earnings (returns pay)
 Pure virtual because need to know employee type
 Cannot calculate for generic employee
 Other classes derive from Employee
Employee
SalariedEmployee HourlyEmployeeCommissionEmployee
BasePlusCommissionEmployee
Dynamic Cast
 Downcasting
 dynamic_cast operator
 Determine object's type at runtime
 Returns 0 if not of proper type (cannot be cast)
NewClass *ptr = dynamic_cast < NewClass *> objectPtr;
 Keyword typeid
 Header <typeinfo>
 Usage: typeid(object)
 Returns type_info object
 Has information about type of operand, including name
 typeid(object).name()
1 // Example 61
2 // Employee abstract base class.
3 #ifndef EMPLOYEE_H
4 #define EMPLOYEE_H
5
6 #include <string> // C++ standard string class
7
8 using std::string;
9
10 class Employee {
11
12 public:
13 Employee( const string &, const string &, const string & );
14
15 void setFirstName( const string & );
16 string getFirstName() const;
17
18 void setLastName( const string & );
19 string getLastName() const;
20
21 void setSocialSecurityNumber( const string & );
22 string getSocialSecurityNumber() const;
23
24 // pure virtual function makes Employee abstract base class
25 virtual double earnings() const = 0; // pure virtual
26 virtual void print() const; // virtual
27
28 private:
29 string firstName;
30 string lastName;
31 string socialSecurityNumber;
32
33 }; // end class Employee
34
35 #endif // EMPLOYEE_H
1 // Example 62
2 // Abstract-base-class Employee member-function definitions.
3 // Note: No definitions are given for pure virtual functions.
4 #include <iostream>
5
6 using std::cout;
7 using std::endl;
8
9 #include "employee.h" // Employee class definition
10
11 // constructor
12 Employee::Employee( const string &first, const string &last,
13 const string &SSN )
14 : firstName( first ),
15 lastName( last ),
16 socialSecurityNumber( SSN )
17 {
18 // empty body
19
20 } // end Employee constructor
21
22 // return first name
23 string Employee::getFirstName() const
24 {
25 return firstName;
26
27 } // end function getFirstName
28
29 // return last name
30 string Employee::getLastName() const
31 {
32 return lastName;
33
34 } // end function getLastName
35
36 // return social security number
37 string Employee::getSocialSecurityNumber() const
38 {
39 return socialSecurityNumber;
40
41 } // end function getSocialSecurityNumber
42
43 // set first name
44 void Employee::setFirstName( const string &first )
45 {
46 firstName = first;
47
48 } // end function setFirstName
49
50 // set last name
51 void Employee::setLastName( const string &last )
52 {
53 lastName = last;
54
55 } // end function setLastName
56
57 // set social security number
58 void Employee::setSocialSecurityNumber( const string &number )
59 {
60 socialSecurityNumber = number; // should validate
61
62 } // end function setSocialSecurityNumber
63
64 // print Employee's information
65 void Employee::print() const
66 {
67 cout << getFirstName() << ' ' << getLastName()
68 << "nsocial security number: "
69 << getSocialSecurityNumber() << endl;
70
71 } // end function print
Default implementation for
virtual function print.
1 // Example 63
2 // SalariedEmployee class derived from Employee.
3 #ifndef SALARIED_H
4 #define SALARIED_H
5
6 #include "employee.h" // Employee class definition
7
8 class SalariedEmployee : public Employee {
9
10 public:
11 SalariedEmployee( const string &, const string &,
12 const string &, double = 0.0 );
13
14 void setWeeklySalary( double );
15 double getWeeklySalary() const;
16
17 virtual double earnings() const;
18 virtual void print() const; // "salaried employee: "
19
20 private:
21 double weeklySalary;
22
23 }; // end class SalariedEmployee
24
25 #endif // SALARIED_H
New functions for the
SalariedEmployee class.
earnings must be
overridden. print is
overridden to specify that this
is a salaried employee.
1 // Example 64
2 // SalariedEmployee class member-function definitions.
3 #include <iostream>
4
5 using std::cout;
6
7 #include "salaried.h" // SalariedEmployee class definition
8
9 // SalariedEmployee constructor
10 SalariedEmployee::SalariedEmployee( const string &first,
11 const string &last, const string &socialSecurityNumber,
12 double salary )
13 : Employee( first, last, socialSecurityNumber )
14 {
15 setWeeklySalary( salary );
16
17 } // end SalariedEmployee constructor
18
19 // set salaried employee's salary
20 void SalariedEmployee::setWeeklySalary( double salary )
21 {
22 weeklySalary = salary < 0.0 ? 0.0 : salary;
23
24 } // end function setWeeklySalary
25
Use base class constructor for
basic fields.
26 // calculate salaried employee's pay
27 double SalariedEmployee::earnings() const
28 {
29 return getWeeklySalary();
30
31 } // end function earnings
32
33 // return salaried employee's salary
34 double SalariedEmployee::getWeeklySalary() const
35 {
36 return weeklySalary;
37
38 } // end function getWeeklySalary
39
40 // print salaried employee's name
41 void SalariedEmployee::print() const
42 {
43 cout << "nsalaried employee: ";
44 Employee::print(); // code reuse
45
46 } // end function print
Must implement pure virtual
functions.
1 // Example 65
2 // HourlyEmployee class definition.
3 #ifndef HOURLY_H
4 #define HOURLY_H
5
6 #include "employee.h" // Employee class definition
7
8 class HourlyEmployee : public Employee {
9
10 public:
11 HourlyEmployee( const string &, const string &,
12 const string &, double = 0.0, double = 0.0 );
13
14 void setWage( double );
15 double getWage() const;
16
17 void setHours( double );
18 double getHours() const;
19
20 virtual double earnings() const;
21 virtual void print() const;
22
23 private:
24 double wage; // wage per hour
25 double hours; // hours worked for week
26
27 }; // end class HourlyEmployee
28
29 #endif // HOURLY_H
1 // Example 66
2 // HourlyEmployee class member-function definitions.
3 #include <iostream>
4
5 using std::cout;
6
7 #include "hourly.h"
8
9 // constructor for class HourlyEmployee
10 HourlyEmployee::HourlyEmployee( const string &first,
11 const string &last, const string &socialSecurityNumber,
12 double hourlyWage, double hoursWorked )
13 : Employee( first, last, socialSecurityNumber )
14 {
15 setWage( hourlyWage );
16 setHours( hoursWorked );
17
18 } // end HourlyEmployee constructor
19
20 // set hourly employee's wage
21 void HourlyEmployee::setWage( double wageAmount )
22 {
23 wage = wageAmount < 0.0 ? 0.0 : wageAmount;
24
25 } // end function setWage
26
27 // set hourly employee's hours worked
28 void HourlyEmployee::setHours( double hoursWorked )
29 {
30 hours = ( hoursWorked >= 0.0 && hoursWorked <= 168.0 ) ?
31 hoursWorked : 0.0;
32
33 } // end function setHours
34
35 // return hours worked
36 double HourlyEmployee::getHours() const
37 {
38 return hours;
39
40 } // end function getHours
41
42 // return wage
43 double HourlyEmployee::getWage() const
44 {
45 return wage;
46
47 } // end function getWage
48
49 // get hourly employee's pay
50 double HourlyEmployee::earnings() const
51 {
52 if ( hours <= 40 ) // no overtime
53 return wage * hours;
54 else // overtime is paid at wage * 1.5
55 return 40 * wage + ( hours - 40 ) * wage * 1.5;
56
57 } // end function earnings
58
59 // print hourly employee's information
60 void HourlyEmployee::print() const
61 {
62 cout << "nhourly employee: ";
63 Employee::print(); // code reuse
64
65 } // end function print
1 // Example 67
2 // CommissionEmployee class derived from Employee.
3 #ifndef COMMISSION_H
4 #define COMMISSION_H
5
6 #include "employee.h" // Employee class definition
7
8 class CommissionEmployee : public Employee {
9
10 public:
11 CommissionEmployee( const string &, const string &,
12 const string &, double = 0.0, double = 0.0 );
13
14 void setCommissionRate( double );
15 double getCommissionRate() const;
16
17 void setGrossSales( double );
18 double getGrossSales() const;
19
20 virtual double earnings() const;
21 virtual void print() const;
22
23 private:
24 double grossSales; // gross weekly sales
25 double commissionRate; // commission percentage
26
27 }; // end class CommissionEmployee
28
29 #endif // COMMISSION_H
Must set rate and sales.
1 // Example 68
2 // CommissionEmployee class member-function definitions.
3 #include <iostream>
4
5 using std::cout;
6
7 #include "commission.h" // Commission class
8
9 // CommissionEmployee constructor
10 CommissionEmployee::CommissionEmployee( const string &first,
11 const string &last, const string &socialSecurityNumber,
12 double grossWeeklySales, double percent )
13 : Employee( first, last, socialSecurityNumber )
14 {
15 setGrossSales( grossWeeklySales );
16 setCommissionRate( percent );
17
18 } // end CommissionEmployee constructor
19
20 // return commission employee's rate
21 double CommissionEmployee::getCommissionRate() const
22 {
23 return commissionRate;
24
25 } // end function getCommissionRate
26
27 // return commission employee's gross sales amount
28 double CommissionEmployee::getGrossSales() const
29 {
30 return grossSales;
31
32 } // end function getGrossSales
33
34 // set commission employee's weekly base salary
35 void CommissionEmployee::setGrossSales( double sales )
36 {
37 grossSales = sales < 0.0 ? 0.0 : sales;
38
39 } // end function setGrossSales
40
41 // set commission employee's commission
42 void CommissionEmployee::setCommissionRate( double rate )
43 {
44 commissionRate = ( rate > 0.0 && rate < 1.0 ) ? rate : 0.0;
45
46 } // end function setCommissionRate
47
48 // calculate commission employee's earnings
49 double CommissionEmployee::earnings() const
50 {
51 return getCommissionRate() * getGrossSales();
52
53 } // end function earnings
54
55 // print commission employee's name
56 void CommissionEmployee::print() const
57 {
58 cout << "ncommission employee: ";
59 Employee::print(); // code reuse
60
61 } // end function print
1 // Example 69
2 // BasePlusCommissionEmployee class derived from Employee.
3 #ifndef BASEPLUS_H
4 #define BASEPLUS_H
5
6 #include "commission.h" // Employee class definition
7
8 class BasePlusCommissionEmployee : public CommissionEmployee {
9
10 public:
11 BasePlusCommissionEmployee( const string &, const string &,
12 const string &, double = 0.0, double = 0.0, double = 0.0 );
13
14 void setBaseSalary( double );
15 double getBaseSalary() const;
16
17 virtual double earnings() const;
18 virtual void print() const;
19
20 private:
21 double baseSalary; // base salary per week
22
23 }; // end class BasePlusCommissionEmployee
24
25 #endif // BASEPLUS_H
Inherits from
CommissionEmployee
(and from Employee
indirectly).
1 // Example 70
2 // BasePlusCommissionEmployee member-function definitions.
3 #include <iostream>
4
5 using std::cout;
6
7 #include "baseplus.h"
8
9 // constructor for class BasePlusCommissionEmployee
10 BasePlusCommissionEmployee::BasePlusCommissionEmployee(
11 const string &first, const string &last,
12 const string &socialSecurityNumber,
13 double grossSalesAmount, double rate,
14 double baseSalaryAmount )
15 : CommissionEmployee( first, last, socialSecurityNumber,
16 grossSalesAmount, rate )
17 {
18 setBaseSalary( baseSalaryAmount );
19
20 } // end BasePlusCommissionEmployee constructor
21
22 // set base-salaried commission employee's wage
23 void BasePlusCommissionEmployee::setBaseSalary( double salary )
24 {
25 baseSalary = salary < 0.0 ? 0.0 : salary;
26
27 } // end function setBaseSalary
28
29 // return base-salaried commission employee's base salary
30 double BasePlusCommissionEmployee::getBaseSalary() const
31 {
32 return baseSalary;
33
34 } // end function getBaseSalary
35
36 // return base-salaried commission employee's earnings
37 double BasePlusCommissionEmployee::earnings() const
38 {
39 return getBaseSalary() + CommissionEmployee::earnings();
40
41 } // end function earnings
42
43 // print base-salaried commission employee's name
44 void BasePlusCommissionEmployee::print() const
45 {
46 cout << "nbase-salaried commission employee: ";
47 Employee::print(); // code reuse
48
49 } // end function print
1 // Example 71
2 // Driver for Employee hierarchy.
3 #include <iostream>
4
5 using std::cout;
6 using std::endl;
7 using std::fixed;
8
9 #include <iomanip>
10
11 using std::setprecision;
12
13 #include <vector>
14
15 using std::vector;
16
17 #include <typeinfo>
18
19 #include "employee.h" // Employee base class
20 #include "salaried.h" // SalariedEmployee class
21 #include "commission.h" // CommissionEmployee class
22 #include "baseplus.h" // BasePlusCommissionEmployee class
23 #include "hourly.h" // HourlyEmployee class
24
25 int main()
26 {
27 // set floating-point output formatting
28 cout << fixed << setprecision( 2 );
29
30 // create vector employees
31 vector < Employee * > employees( 4 );
32
33 // initialize vector with Employees
34 employees[ 0 ] = new SalariedEmployee( "John", "Smith",
35 "111-11-1111", 800.00 );
36 employees[ 1 ] = new CommissionEmployee( "Sue", "Jones",
37 "222-22-2222", 10000, .06 );
38 employees[ 2 ] = new BasePlusCommissionEmployee( "Bob",
39 "Lewis", "333-33-3333", 300, 5000, .04 );
40 employees[ 3 ] = new HourlyEmployee( "Karen", "Price",
41 "444-44-4444", 16.75, 40 );
42
43 // generically process each element in vector employees
44 for ( int i = 0; i < employees.size(); i++ ) {
45
46 // output employee information
47 employees[ i ]->print();
48
49 // downcast pointer
50 BasePlusCommissionEmployee *commissionPtr =
51 dynamic_cast < BasePlusCommissionEmployee * >
52 ( employees[ i ] );
53
54 // determine whether element points to base-salaried
55 // commission employee
56 if ( commissionPtr != 0 ) {
57 cout << "old base salary: $"
58 << commissionPtr->getBaseSalary() << endl;
59 commissionPtr->setBaseSalary(
60 1.10 * commissionPtr->getBaseSalary() );
61 cout << "new base salary with 10% increase is: $"
62 << commissionPtr->getBaseSalary() << endl;
63
64 } // end if
65
66 cout << "earned $" << employees[ i ]->earnings() << endl;
67
68 } // end for
69
Use downcasting to cast the employee object into a
BasePlusCommissionEmployee. If it points to
the correct type of object, the pointer is non-zero. This
way, we can give a raise to only
BasePlusCommissionEmployees.
70 // release memory held by vector employees
71 for ( int j = 0; j < employees.size(); j++ ) {
72
73 // output class name
74 cout << "ndeleting object of "
75 << typeid( *employees[ j ] ).name();
76
77 delete employees[ j ];
78
79 } // end for
80
81 cout << endl;
82
83 return 0;
84
85 } // end main
typeid returns a
type_info object. This
object contains information
about the operand, including
its name.
salaried employee: John Smith
social security number: 111-11-1111
earned $800.00
commission employee: Sue Jones
social security number: 222-22-2222
earned $600.00
base-salaried commission employee: Bob Lewis
social security number: 333-33-3333
old base salary: $300.00
new base salary with 10% increase is: $330.00
earned $530.00
hourly employee: Karen Price
social security number: 444-44-4444
earned $670.00
deleting object of class SalariedEmployee
deleting object of class CommissionEmployee
deleting object of class BasePlusCommissionEmployee
deleting object of class HourlyEmployee
Multiple Inheritance
 Multiple inheritance
 Derived class has several base classes
 Powerful, but can cause ambiguity problems
 If both base classes have functions of the same name
 Solution: specify exact function using ::
myObject.BaseClass1::function()
 Format
 Use comma-separated list
class Derived : public Base1, public Base2{
contents
}
1 // Example 72
2 // Definition of class Base1
3 #ifndef BASE1_H
4 #define BASE1_H
5
6 // class Base1 definition
7 class Base1 {
8 public:
9 Base1( int parameterValue ) { value = parameterValue; }
10 int getData() const { return value; }
11
12 protected: // accessible to derived classes
13 int value; // inherited by derived class
14
15 }; // end class Base1
16
17 #endif // BASE1_H
There are two base classes in
this example, each has its own
getData function.
This base class contains an
int.
1 // Example 73
2 // Definition of class Base2
3 #ifndef BASE2_H
4 #define BASE2_H
5
6 // class Base2 definition
7 class Base2 {
8 public:
9 Base2( char characterData ) { letter = characterData; }
10 char getData() const { return letter; }
11
12 protected: // accessible to derived classes
13 char letter; // inherited by derived class
14
15 }; // end class Base2
16
17 #endif // BASE2_H
1 // Example 74
2 // Definition of class Derived which inherits
3 // multiple base classes (Base1 and Base2).
4 #ifndef DERIVED_H
5 #define DERIVED_H
6
7 #include <iostream>
8
9 using std::ostream;
10
11 #include "base1.h"
12 #include "base2.h"
13
14 // class Derived definition
15 class Derived : public Base1, public Base2 {
16 friend ostream &operator<<( ostream &, const Derived & );
17
18 public:
19 Derived( int, char, double );
20 double getReal() const;
21
22 private:
23 double real; // derived class's private data
24
25 }; // end class Derived
26
27 #endif // DERIVED_H
Use comma-separated list.
1 // Example 75
2 // Member function definitions for class Derived
3 #include "derived.h"
4
5 // constructor for Derived calls constructors for
6 // class Base1 and class Base2.
7 // use member initializers to call base-class constructors
8 Derived::Derived( int integer, char character, double double1 )
9 : Base1( integer ), Base2( character ), real( double1 ) { }
10
11 // return real
12 double Derived::getReal() const { return real; }
13
14 // display all data members of Derived
15 ostream &operator<<( ostream &output, const Derived &derived )
16 {
17 output << " Integer: " << derived.value
18 << "n Character: " << derived.letter
19 << "nReal number: " << derived.real;
20
21 return output; // enables cascaded calls
22
23 } // end operator<<
Note use of base-class
constructors in derived class
constructor.
1 // Example 76
2 // Driver for multiple inheritance example.
3 #include <iostream>
4
5 using std::cout;
6 using std::endl;
7
8 #include "base1.h"
9 #include "base2.h"
10 #include "derived.h"
11
12 int main()
13 {
14 Base1 base1( 10 ), *base1Ptr = 0; // create Base1 object
15 Base2 base2( 'Z' ), *base2Ptr = 0; // create Base2 object
16 Derived derived( 7, 'A', 3.5 ); // create Derived object
17
18 // print data members of base-class objects
19 cout << "Object base1 contains integer "
20 << base1.getData()
21 << "nObject base2 contains character "
22 << base2.getData()
23 << "nObject derived contains:n" << derived << "nn";
24
25 // print data members of derived-class object
26 // scope resolution operator resolves getData ambiguity
27 cout << "Data members of Derived can be"
28 << " accessed individually:"
29 << "n Integer: " << derived.Base1::getData()
30 << "n Character: " << derived.Base2::getData()
31 << "nReal number: " << derived.getReal() << "nn";
32
33 cout << "Derived can be treated as an "
34 << "object of either base class:n";
35
36 // treat Derived as a Base1 object
37 base1Ptr = &derived;
38 cout << "base1Ptr->getData() yields "
39 << base1Ptr->getData() << 'n';
40
41 // treat Derived as a Base2 object
42 base2Ptr = &derived;
43 cout << "base2Ptr->getData() yields "
44 << base2Ptr->getData() << endl;
45
46 return 0;
47
48 } // end main
Note calls to specific base
class functions.
Can treat derived-class
pointer as either base-class
pointer.
Object base1 contains integer 10
Object base2 contains character Z
Object derived contains:
Integer: 7
Character: A
Real number: 3.5
Data members of Derived can be accessed individually:
Integer: 7
Character: A
Real number: 3.5
Derived can be treated as an object of either base class:
base1Ptr->getData() yields 7
base2Ptr->getData() yields A
Multiple Inheritance and virtual
Base Classes
 Ambiguities from multiple inheritance
 iostream could have duplicate subobjects
 Data from ios inherited into ostream and istream
 Upcasting iostream pointer to ios object is a problem
 Two ios subobjects could exist, which is used?
 Ambiguous, results in syntax error
 iostream does not actually have this problem
ios
ostream
istream
iostream
Multiple Inheritance and virtual
Base Classes
 Solution: use virtual base class inheritance
 Only one subobject inherited into multiply derived class
Second Derived Class
Base Class
First Derived Class
Multiply-Derived Class
virtual
inheritance
virtual
inheritance
1 // Example 77
2 // Attempting to polymorphically call a function that is
3 // multiply inherited from two base classes.
4 #include <iostream>
5
6 using std::cout;
7 using std::endl;
8
9 // class Base definition
10 class Base {
11 public:
12 virtual void print() const = 0; // pure virtual
13
14 }; // end class Base
15
16 // class DerivedOne definition
17 class DerivedOne : public Base {
18 public:
19
20 // override print function
21 void print() const { cout << "DerivedOnen"; }
22
23 }; // end class DerivedOne
24
This example will
demonstrate the ambiguity of
multiple inheritance.
25 // class DerivedTwo definition
26 class DerivedTwo : public Base {
27 public:
28
29 // override print function
30 void print() const { cout << "DerivedTwon"; }
31
32 }; // end class DerivedTwo
33
34 // class Multiple definition
35 class Multiple : public DerivedOne, public DerivedTwo {
36 public:
37
38 // qualify which version of function print
39 void print() const { DerivedTwo::print(); }
40
41 }; // end class Multiple
42
43 int main()
44 {
45 Multiple both; // instantiate Multiple object
46 DerivedOne one; // instantiate DerivedOne object
47 DerivedTwo two; // instantiate DerivedTwo object
48
49 // create array of base-class pointers
50 Base *array[ 3 ];
51
52 array[ 0 ] = &both; // ERROR--ambiguous
53 array[ 1 ] = &one;
54 array[ 2 ] = &two;
55
56 // polymorphically invoke print
57 for ( int i = 0; i < 3; i++ )
58 array[ i ] -> print();
59
60 return 0;
61
62 } // end main
Which base subobject will be
used?
1 // Example 78
2 // Using virtual base classes.
3 #include <iostream>
4
5 using std::cout;
6 using std::endl;
7
8 // class Base definition
9 class Base {
10 public:
11
12 // implicit default constructor
13
14 virtual void print() const = 0; // pure virtual
15
16 }; // end Base class
17
18 // class DerivedOne definition
19 class DerivedOne : virtual public Base {
20 public:
21
22 // implicit default constructor calls
23 // Base default constructor
24
25 // override print function
26 void print() const { cout << "DerivedOnen"; }
27
28 }; // end DerivedOne class
Use virtual inheritance to
solve the ambiguity problem.
The compiler generates
default constructors, which
greatly simplifies the
hierarchy.
29
30 // class DerivedTwo definition
31 class DerivedTwo : virtual public Base {
32 public:
33
34 // implicit default constructor calls
35 // Base default constructor
36
37 // override print function
38 void print() const { cout << "DerivedTwon"; }
39
40 }; // end DerivedTwo class
41
42 // class Multiple definition
43 class Multiple : public DerivedOne, public DerivedTwo {
44 public:
45
46 // implicit default constructor calls
47 // DerivedOne and DerivedTwo default constructors
48
49 // qualify which version of function print
50 void print() const { DerivedTwo::print(); }
51
52 }; // end Multiple class
Use virtual inheritance, as
before.
53
54 int main()
55 {
56 Multiple both; // instantiate Multiple object
57 DerivedOne one; // instantiate DerivedOne object
58 DerivedTwo two; // instantiate DerivedTwo object
59
60 // declare array of base-class pointers and initialize
61 // each element to a derived-class type
62 Base *array[ 3 ];
63
64 array[ 0 ] = &both;
65 array[ 1 ] = &one;
66 array[ 2 ] = &two;
67
68 // polymorphically invoke function print
69 for ( int i = 0; i < 3; i++ )
70 array[ i ]->print();
71
72 return 0;
73
74 } // end main
DerivedTwo
DerivedOne
DerivedTwo
Program Design and Software Tools
Template, Standard Template Library
Template
Introduction
 Overloaded functions
 Similar operations but Different types of data
 Function templates
 Specify entire range of related (overloaded) functions
 Function-template specializations
 Identical operations
 Different types of data
 Single function template
 Compiler generates separate object-code functions
 Unlike Macros they allow Type checking
 Class templates
 Specify entire range of related classes
 Class-template specializations
Function Templates
 Function-template definitions
 Keyword template
 List formal type parameters in angle brackets (< and >)
 Each parameter preceded by keyword class or typename
class and typename interchangeable
template< class T >
template< typename ElementType >
template< class BorderType, class FillType >
 Specify types of
Arguments to function
Return type of function
Variables within function
1 // Example 79
2 // Using template functions.
3 #include <iostream>
4
5 using std::cout;
6 using std::endl;
7
8 // function template printArray definition
9 template< class T >
10 void printArray( const T *array, const int count )
11 {
12 for ( int i = 0; i < count; i++ )
13 cout << array[ i ] << " ";
14
15 cout << endl;
16
17 } // end function printArray
18
19 int main()
20 {
21 const int aCount = 5;
22 const int bCount = 7;
23 const int cCount = 6;
24
Function template definition;
declare single formal type
parameter T.
T is type parameter; use any
valid identifier.
If T is user-defined type,
stream-insertion operator
must be overloaded for class
T.
25 int a[ aCount ] = { 1, 2, 3, 4, 5 };
26 double b[ bCount ] = { 1.1, 2.2, 3.3, 4.4, 5.5, 6.6, 7.7 };
27 char c[ cCount ] = "HELLO"; // 6th position for null
28
29 cout << "Array a contains:" << endl;
30
31 // call integer function-template specialization
32 printArray( a, aCount );
33
34 cout << "Array b contains:" << endl;
35
36 // call double function-template specialization
37 printArray( b, bCount );
38
39 cout << "Array c contains:" << endl;
40
41 // call character function-template specialization
42 printArray( c, cCount );
43
44 return 0;
45
46 } // end main
Creates complete function-template specialization for printing
array of ints:
void printArray( const int *array, const int count )
{
for ( int i = 0; i < count; i++ )
cout << array[ i ] << " "
cout << endl;
} // end function printArray
Compiler infers T is
double; instantiates
function-template
specialization where T is
double.
Compiler infers T is char;
instantiates function-template
specialization where T is
char.
Overloading Function Templates
 Related function-template specializations
 Same name
 Compiler uses overloading resolution
 Function template overloading
 Other function templates with same name
 Different parameters
 Non-template functions with same name
 Different function arguments
 Compiler performs matching process
 Tries to find precise match of function name and argument types
 If fails, function template
Generate function-template specialization with precise match
Class Templates
 Stack
 LIFO (last-in-first-out) structure
 Class templates
 Generic programming
 Describe notion of stack generically
 Instantiate type-specific version
 Parameterized types
 Require one or more type parameters
Customize “generic class” template to form class-template specialization
1 // Example 80
2 // Stack class template.
3 #ifndef TSTACK1_H
4 #define TSTACK1_H
5
6 template< class T >
7 class Stack {
8
9 public:
10 Stack( int = 10 ); // default constructor (stack size 10)
11
12 // destructor
13 ~Stack()
14 {
15 delete [] stackPtr;
16
17 } // end ~Stack destructor
18
19 bool push( const T& ); // push an element onto the stack
20 bool pop( T& ); // pop an element off the stack
21
Specify class-template
definition; type parameter T
indicates type of Stack class
to be created.
Function parameters of type
T.
22 // determine whether Stack is empty
23 bool isEmpty() const
24 {
25 return top == -1;
26
27 } // end function isEmpty
28
29 // determine whether Stack is full
30 bool isFull() const
31 {
32 return top == size - 1;
33
34 } // end function isFull
35
36 private:
37 int size; // # of elements in the stack
38 int top; // location of the top element
39 T *stackPtr; // pointer to the stack
40
41 }; // end class Stack
42
Array of elements of type T.
43 // constructor
44 template< class T >
45 Stack< T >::Stack( int s )
46 {
47 size = s > 0 ? s : 10;
48 top = -1; // Stack initially empty
49 stackPtr = new T[ size ]; // allocate memory for elements
50
51 } // end Stack constructor
52
53 // push element onto stack;
54 // if successful, return true; otherwise, return false
55 template< class T >
56 bool Stack< T >::push( const T &pushValue )
57 {
58 if ( !isFull() ) {
59 stackPtr[ ++top ] = pushValue; // place item on Stack
60 return true; // push successful
61
62 } // end if
63
64 return false; // push unsuccessful
65
66 } // end function push
67
Member functions preceded
with header
template< class T >
Use binary scope resolution
operator (::) with class-
template name (Stack< T >)
to tie definition to class
template’s scope.
Constructor creates array of type T.
For example, compiler generates
stackPtr = new T[ size ];
for class-template specialization
Stack< double >.
68 // pop element off stack;
69 // if successful, return true; otherwise, return false
70 template< class T >
71 bool Stack< T >::pop( T &popValue )
72 {
73 if ( !isEmpty() ) {
74 popValue = stackPtr[ top-- ]; // remove item from Stack
75 return true; // pop successful
76
77 } // end if
78
79 return false; // pop unsuccessful
80
81 } // end function pop
82
83 #endif
Member function preceded
with header
template< class T >Use binary scope resolution
operator (::) with class-
template name (Stack< T >)
to tie definition to class
template’s scope.
1 // Example 81
2 // Stack-class-template test program.
3 #include <iostream>
4
5 using std::cout;
6 using std::cin;
7 using std::endl;
8
9 #include "tstack1.h" // Stack class template definition
10
11 int main()
12 {
13 Stack< double > doubleStack( 5 );
14 double doubleValue = 1.1;
15
16 cout << "Pushing elements onto doubleStackn";
17
18 while ( doubleStack.push( doubleValue ) ) {
19 cout << doubleValue << ' ';
20 doubleValue += 1.1;
21
22 } // end while
23
24 cout << "nStack is full. Cannot push " << doubleValue
25 << "nnPopping elements from doubleStackn";
Link to class template
definition.
Instantiate object of class
Stack< double >.
Invoke function push of
class-template specialization
Stack< double >.
26
27 while ( doubleStack.pop( doubleValue ) )
28 cout << doubleValue << ' ';
29
30 cout << "nStack is empty. Cannot popn";
31
32 Stack< int > intStack;
33 int intValue = 1;
34 cout << "nPushing elements onto intStackn";
35
36 while ( intStack.push( intValue ) ) {
37 cout << intValue << ' ';
38 ++intValue;
39
40 } // end while
41
42 cout << "nStack is full. Cannot push " << intValue
43 << "nnPopping elements from intStackn";
44
45 while ( intStack.pop( intValue ) )
46 cout << intValue << ' ';
47
48 cout << "nStack is empty. Cannot popn";
49
50 return 0;
Invoke function pop of class-
template specialization
Stack< double >.
Note similarity of code for
Stack< int > to code for
Stack< double >.
51
52 } // end main
Pushing elements onto doubleStack
1.1 2.2 3.3 4.4 5.5
Stack is full. Cannot push 6.6
Popping elements from doubleStack
5.5 4.4 3.3 2.2 1.1
Stack is empty. Cannot pop
Pushing elements onto intStack
1 2 3 4 5 6 7 8 9 10
Stack is full. Cannot push 11
Popping elements from intStack
10 9 8 7 6 5 4 3 2 1
Stack is empty. Cannot pop
1 // Example 82
2 // Stack class template test program. Function main uses a
3 // function template to manipulate objects of type Stack< T >.
4 #include <iostream>
5
6 using std::cout;
7 using std::cin;
8 using std::endl;
9
10 #include "tstack1.h" // Stack class template definition
11
12 // function template to manipulate Stack< T >
13 template< class T >
14 void testStack(
15 Stack< T > &theStack, // reference to Stack< T >
16 T value, // initial value to push
17 T increment, // increment for subsequent values
18 const char *stackName ) // name of the Stack < T > object
19 {
20 cout << "nPushing elements onto " << stackName << 'n';
21
22 while ( theStack.push( value ) ) {
23 cout << value << ' ';
24 value += increment;
25
26 } // end while
Function template to manipulat
Stack< T > eliminates simil
code from previous file for
Stack< double > and
Stack< int >.
27
28 cout << "nStack is full. Cannot push " << value
29 << "nnPopping elements from " << stackName << 'n';
30
31 while ( theStack.pop( value ) )
32 cout << value << ' ';
33
34 cout << "nStack is empty. Cannot popn";
35
36 } // end function testStack
37
38 int main()
39 {
40 Stack< double > doubleStack( 5 );
41 Stack< int > intStack;
42
43 testStack( doubleStack, 1.1, 1.1, "doubleStack" );
44 testStack( intStack, 1, 1, "intStack" );
45
46 return 0;
47
48 } // end main
Pushing elements onto doubleStack
1.1 2.2 3.3 4.4 5.5
Stack is full. Cannot push 6.6
Popping elements from doubleStack
5.5 4.4 3.3 2.2 1.1
Stack is empty. Cannot pop
Pushing elements onto intStack
1 2 3 4 5 6 7 8 9 10
Stack is full. Cannot push 11
Popping elements from intStack
10 9 8 7 6 5 4 3 2 1
Stack is empty. Cannot pop
Note output identical to that
of fig11_03.cpp.
Class templates
Nontype parameters
 Default arguments
 Treated as consts
template< class T, int elements >
Stack< double, 100 > mostRecentSalesFigures;
Declares object of type Stack< double, 100>
Type parameter
 Default type example: template< class T = string >
Overriding class templates
Class for specific type
 Does not match common class template
Example: template<>
Class Array< Martian > {
// body of class definition
};
Class Templates and Nontype Parameters
Templates and Inheritance
 Several ways of relating templates and inheritance
 Class template derived from class-template specialization
 Class template derived from non-template class
 Class-template specialization derived from class-template specialization
 Non-template class derived from class-template specialization
 Friendships between class template and
 Global function
 Member function of another class
 Entire class
Templates and Friends
 friend functions
 Inside definition of template< class T > class X
 friend void f1();
f1() friend of all class-template specializations
 friend void f2( X< T > & );
f2( X< float > & ) friend of X< float > only,
f2( X< double > & ) friend of X< double > only,
f2( X< int > & ) friend of X< int > only,
…
 friend void A::f4();
Member function f4 of class A friend of all class-template specializations
Templates and Friends
 friend functions
 Inside definition of template< class T > class X
 friend void C< T >::f5( X< T > & );
Member function C<float>::f5( X< float> & ) friend of class
X<float> only
 friend classes
 Inside definition of template< class T > class X
 friend class Y;
Every member function of Y friend of every class-template specialization
 friend class Z<T>;
class Z<float> friend of class-template specialization X<float>, etc.
Templates and static Members
 Non-template class
 static data members shared between all objects
 Class-template specialization
 Each has own copy of static data members
 static variables initialized at file scope
 Each has own copy of static member functions
Introduction to the Standard Template Library (STL)
 STL
 Powerful, template-based components
 Containers: template data structures
 Iterators: like pointers, access elements of containers
 Algorithms: data manipulation, searching, sorting, etc.
 Object- oriented programming: reuse, reuse, reuse
 Only an introduction to STL, a huge class library
Introduction to Containers
 Three types of containers
 Sequence containers: vector; deque; list
 Linear data structures (vectors, linked lists)
 First-class container
 Associative containers: set; multiset; map; multimap
 Non-linear, can find elements quickly
 Key/value pairs
 First-class container
 Container adapters:stack; queue; priority_queue
 Near containers
 Similar to containers, with reduced functionality
 Containers have some common functions
Common STL Member Functions
 Member functions for all containers
 Default constructor, copy constructor, destructor
 empty
 max_size, size
 = < <= > >= == !=
 swap
 Functions for first-class containers
 begin, end
 rbegin, rend
 erase, clear
Common STL typedefs
 typedefs for first-class containers
 value_type
 reference
 const_reference
 pointer
 iterator
 const_iterator
 reverse_iterator
 const_reverse_iterator
 difference_type
 size_type
Introduction to Iterators
 Iterators similar to pointers
 Point to first element in a container
 Iterator operators same for all containers
 * dereferences
 ++ points to next element
 begin() returns iterator to first element
 end() returns iterator to last element
 Use iterators with sequences (ranges)
 Containers
 Input sequences: istream_iterator
 Output sequences: ostream_iterator
Iterators
 Usage
 std::istream_iterator< int > inputInt( cin )
 Can read input from cin
 *inputInt: Dereference to read first int from cin
 ++inputInt: Go to next int in stream
 std::ostream_iterator< int > outputInt(cout)
 Can output ints to cout
 *outputInt = 7: Outputs 7 to cout
 ++outputInt: Advances iterator so we can output next int
 Example
int number1 = *inputInt;
++inputInt
int number1 = *inputInt;
cout << "The sum is: ";
*outputInt = number1 + number2;
Iterator Categories
 Input
 Read elements from container, can only move forward
 Output
 Write elements to container, only forward
 Forward
 Combines input and output, retains position
 Bidirectional
 Like forward, but can move backwards as well
 Multi-pass (can pass through sequence twice)
 Random access
 Like bidirectional, but can also jump to any element
Iterator Types Supported
 Sequence containers
 vector: random access
 deque: random access
 list: bidirectional
 Associative containers (all bidirectional)
 set
 multiset
 Map
 multimap
 Container adapters (no iterators supported)
 stack
 queue
 priority_queue
Iterator Operations
 All
 ++p, p++
 Input iterators
 *p (to use as rvalue)
 p = p1
 p == p1, p != p1
 Output iterators
 *p
 p = p1
Forward iterators
Have functionality of
input and output iterators
Bidirectional
--p, p--
Random access
p + i, p += i
p - i, p -= i
p[i]
p < p1, p <= p1
p > p1, p >= p1
Introduction to Algorithms
 STL has algorithms used generically across containers
 Operate on elements indirectly via iterators
 Often operate on sequences of elements
 Defined by pairs of iterators
 First and last element
 Algorithms often return iterators
 find()
 Returns iterator to element, or end() if not found
 Premade algorithms save programmers time and effort
vector Sequence Container
 vector
 Has random access iterators
 Data structure with contiguous memory locations
 Access elements with []
 Use when data must be sorted and easily accessible
 When memory exhausted
 Allocates larger, contiguous area of memory
 Copies itself there
 Deallocates old memory
 Declarations
 std::vector <type> v;
 type: int, float, etc.
vector Sequence Container
 Iterators
 std::vector<type>::const_iterator iterVar;
 const_iterator cannot modify elements (read)
 std::vector<type>::reverse_iterator iterVar;
 Visits elements in reverse order (end to beginning)
 Use rbegin to get starting point
 Use rend to get ending point
 vector functions
 v.push_back(value)
 Add element to end (found in all sequence containers).
 v.size()
 Current size of vector
 v.capacity()
 How much vector can hold before reallocating memory
 Reallocation doubles size
 vector<type> v(a, a + SIZE)
 Creates vector v with elements from array a up to (not including) a + SIZE
vector Sequence Container
 vector functions
 v.insert(iterator, value )
 Inserts value before location of iterator
 v.insert(iterator, array , array + SIZE)
 Inserts array elements (up to, but not including array + SIZE) into vector
 v.erase( iterator )
 Remove element from container
 v.erase( iter1, iter2 )
 Remove elements starting from iter1 and up to (not including) iter2
 v.clear()
 Erases entire container
 vector functions operations
 v.front(), v.back()
 Return first and last element
 v.[elementNumber] = value;
 Assign value to an element
 v.at[elementNumber] = value;
 As above, with range checking
 out_of_bounds exception
vector Sequence Container
 ostream_iterator
 std::ostream_iterator< type > Name( outputStream,
separator );
 type: outputs values of a certain type
 outputStream: iterator output location
 separator: character separating outputs
 Example
 std::ostream_iterator< int > output( cout, " " );
 std::copy( iterator1, iterator2, output );
 Copies elements from iterator1 up to (not including) iterator2 to output,
an ostream_iterator
list Sequence Container
 list container : Header <list>
 Efficient insertion/deletion anywhere in container
 Doubly-linked list (two pointers per node)
 Bidirectional iterators
 std::list< type > name;
 list functions for object t
 t.sort()
 Sorts in ascending order
 t.splice(iterator, otherObject );
 Inserts values from otherObject before iterator
 t.merge( otherObject )
 Removes otherObject and inserts it into t, sorted
 t.unique()
 Removes duplicate elements
 t.swap(otherObject);
 Exchange contents
 t.assign(iterator1, iterator2)
 Replaces contents with elements in range of iterators
 t.remove(value)
 Erases all instances of value
deque Sequence Container
 deque ("deek"): double-ended queue
 Header <deque>
 Indexed access using []
 Efficient insertion/deletion in front and back
 Non-contiguous memory: has "smarter" iterators
 Same basic operations as vector
 Also has
 push_front (insert at front of deque)
 pop_front (delete from front)
Associative Containers
 Associative containers
 Direct access to store/retrieve elements
 Uses keys (search keys)
 4 types: multiset, set, multimap and map
 Keys in sorted order
 multiset and multimap allow duplicate keys
 multimap and map have keys and associated values
 multiset and set only have values
multiset Associative Container
 multiset
 Header <set>
 Fast storage, retrieval of keys (no values)
 Allows duplicates
 Bidirectional iterators
 Ordering of elements
 Done by comparator function object
 Used when creating multiset
 For integer multiset
 less<int> comparator function object
 multiset< int, std::less<int> > myObject;
 Elements will be sorted in ascending order
Multiset Associative Container
 Multiset functions
 ms.insert(value)
 Inserts value into multiset
 ms.count(value)
 Returns number of occurrences of value
 ms.find(value)
 Returns iterator to first instance of value
 ms.lower_bound(value)
 Returns iterator to first location of value
 ms.upper_bound(value)
 Returns iterator to location after last occurrence of value
 Class pair
 Manipulate pairs of values
 Pair objects contain first and second
 const_iterators
 For a pair object q
q = ms.equal_range(value)
 Sets first and second to lower_bound and upper_bound for a given value
1 // Example 83
2 // Testing Standard Library class multiset
3 #include <iostream>
4
5 using std::cout;
6 using std::endl;
7
8 #include <set> // multiset class-template definition
9
10 // define short name for multiset type used in this program
11 typedef std::multiset< int, std::less< int > > ims;
12
13 #include <algorithm> // copy algorithm
14
15 int main()
16 {
17 const int SIZE = 10;
18 int a[ SIZE ] = { 7, 22, 9, 1, 18, 30, 100, 22, 85, 13 };
19
20 ims intMultiset; // ims is typedef for "integer multiset"
21 std::ostream_iterator< int > output( cout, " " );
22
23 cout << "There are currently " << intMultiset.count( 15 )
24 << " values of 15 in the multisetn";
25
typedefs help clarify
program. This declares an
integer multiset that stores
values in ascending order.
26 intMultiset.insert( 15 ); // insert 15 in intMultiset
27 intMultiset.insert( 15 ); // insert 15 in intMultiset
28
29 cout << "After inserts, there are "
30 << intMultiset.count( 15 )
31 << " values of 15 in the multisetnn";
32
33 // iterator that cannot be used to change element values
34 ims::const_iterator result;
35
36 // find 15 in intMultiset; find returns iterator
37 result = intMultiset.find( 15 );
38
39 if ( result != intMultiset.end() ) // if iterator not at end
40 cout << "Found value 15n"; // found search value 15
41
42 // find 20 in intMultiset; find returns iterator
43 result = intMultiset.find( 20 );
44
45 if ( result == intMultiset.end() ) // will be true hence
46 cout << "Did not find value 20n"; // did not find 20
47
48 // insert elements of array a into intMultiset
49 intMultiset.insert( a, a + SIZE );
50
51 cout << "nAfter insert, intMultiset contains:n";
52 std::copy( intMultiset.begin(), intMultiset.end(), output );
53
Use member function find.
54 // determine lower and upper bound of 22 in intMultiset
55 cout << "nnLower bound of 22: "
56 << *( intMultiset.lower_bound( 22 ) );
57 cout << "nUpper bound of 22: "
58 << *( intMultiset.upper_bound( 22 ) );
59
60 // p represents pair of const_iterators
61 std::pair< ims::const_iterator, ims::const_iterator > p;
62
63 // use equal_range to determine lower and upper bound
64 // of 22 in intMultiset
65 p = intMultiset.equal_range( 22 );
66
67 cout << "nnequal_range of 22:"
68 << "n Lower bound: " << *( p.first )
69 << "n Upper bound: " << *( p.second );
70
71 cout << endl;
72
73 return 0;
74
75 } // end main
Use a pair object to get the
lower and upper bound for
22.
There are currently 0 values of 15 in the multiset
After inserts, there are 2 values of 15 in the multiset
Found value 15
Did not find value 20
After insert, intMultiset contains:
1 7 9 13 15 15 18 22 22 30 85 100
Lower bound of 22: 22
Upper bound of 22: 30
equal_range of 22:
Lower bound: 22
Upper bound: 30
Set Associative Container
 Set: Header <set>
 Implementation identical to multiset
 Unique keys: Duplicates ignored and not inserted
 Supports bidirectional iterators (but not random access)
 std::set< type, std::less<type> > name;
 Multimap: Header <map>
 Fast storage and retrieval of keys and associated values
 Has key/value pairs
 Duplicate keys allowed (multiple values for a single key)
One-to-many relationship
I.e., one student can take many courses
 Insert pair objects (with a key and value)
 Bidirectional iterators
Multimap Associative Container
 Example
std::multimap< int, double, std::less< int > > mmapObject;
Key type int
Value type double
Sorted in ascending order
 Use typedef to simplify code
typedef std::multimap<int, double, std::less<int>> mmid;
mmid mmapObject;
mmapObject.insert( mmid::value_type( 1, 3.4 ) );
Inserts key 1 with value 3.4
 mmid::value_type creates a pair object
1 // Example 84
2 // Standard library class multimap test program.
3 #include <iostream>
4
5 using std::cout;
6 using std::endl;
7
8 #include <map> // map class-template definition
9
10 // define short name for multimap type used in this program
11 typedef std::multimap< int, double, std::less< int > > mmid;
12
13 int main()
14 {
15 mmid pairs;
16
17 cout << "There are currently " << pairs.count( 15 )
18 << " pairs with key 15 in the multimapn";
19
20 // insert two value_type objects in pairs
21 pairs.insert( mmid::value_type( 15, 2.7 ) );
22 pairs.insert( mmid::value_type( 15, 99.3 ) );
23
24 cout << "After inserts, there are "
25 << pairs.count( 15 )
26 << " pairs with key 15nn";
Definition for a multimap
that maps integer keys to
double values.
Create multimap and insert
key-value pairs.
27
28 // insert five value_type objects in pairs
29 pairs.insert( mmid::value_type( 30, 111.11 ) );
30 pairs.insert( mmid::value_type( 10, 22.22 ) );
31 pairs.insert( mmid::value_type( 25, 33.333 ) );
32 pairs.insert( mmid::value_type( 20, 9.345 ) );
33 pairs.insert( mmid::value_type( 5, 77.54 ) );
34
35 cout << "Multimap pairs contains:nKeytValuen";
36
37 // use const_iterator to walk through elements of pairs
38 for ( mmid::const_iterator iter = pairs.begin();
39 iter != pairs.end(); ++iter )
40 cout << iter->first << 't'
41 << iter->second << 'n';
42
43 cout << endl;
44
45 return 0;
46
47 } // end main
Use iterator to print entire
multimap.
There are currently 0 pairs with key 15 in the multimap
After inserts, there are 2 pairs with key 15
Multimap pairs contains:
Key Value
5 77.54
10 22.22
15 2.7
15 99.3
20 9.345
25 33.333
30 111.11
Map Associative Container
 map
 Header <map>
 Like multimap, but only unique key/value pairs
 One-to-one mapping (duplicates ignored)
 Use [] to access values
 Example: for map object m
m[30] = 4000.21;
 Sets the value of key 30 to 4000.21
 If subscript not in map, creates new key/value pair
 Type declaration
std::map< int, double, std::less< int > >;
1 // Example 85
2 // Standard library class map test program.
3 #include <iostream>
4
5 using std::cout;
6 using std::endl;
7
8 #include <map> // map class-template definition
9
10 // define short name for map type used in this program
11 typedef std::map< int, double, std::less< int > > mid;
12
13 int main()
14 {
15 mid pairs;
16
17 // insert eight value_type objects in pairs
18 pairs.insert( mid::value_type( 15, 2.7 ) );
19 pairs.insert( mid::value_type( 30, 111.11 ) );
20 pairs.insert( mid::value_type( 5, 1010.1 ) );
21 pairs.insert( mid::value_type( 10, 22.22 ) );
22 pairs.insert( mid::value_type( 25, 33.333 ) );
23 pairs.insert( mid::value_type( 5, 77.54 ) ); // dupe ignored
24 pairs.insert( mid::value_type( 20, 9.345 ) );
25 pairs.insert( mid::value_type( 15, 99.3 ) ); // dupe ignored
26
Again, use typedefs to
simplify declaration.
Duplicate keys ignored.
27 cout << "pairs contains:nKeytValuen";
28
29 // use const_iterator to walk through elements of pairs
30 for ( mid::const_iterator iter = pairs.begin();
31 iter != pairs.end(); ++iter )
32 cout << iter->first << 't'
33 << iter->second << 'n';
34
35 // use subscript operator to change value for key 25
36 pairs[ 25 ] = 9999.99;
37
38 // use subscript operator insert value for key 40
39 pairs[ 40 ] = 8765.43;
40
41 cout << "nAfter subscript operations, pairs contains:"
42 << "nKeytValuen";
43
44 for ( mid::const_iterator iter2 = pairs.begin();
45 iter2 != pairs.end(); ++iter2 )
46 cout << iter2->first << 't'
47 << iter2->second << 'n';
48
49 cout << endl;
50
51 return 0;
52
53 } // end main
Can use subscript operator to
add or change key-value
pairs.
pairs contains:
Key Value
5 1010.1
10 22.22
15 2.7
20 9.345
25 33.333
30 111.11
After subscript operations, pairs contains:
Key Value
5 1010.1
10 22.22
15 2.7
20 9.345
25 9999.99
30 111.11
40 8765.43
Container Adapters
 Container adapters
 stack, queue and priority_queue
 Not first class containers
 Do not support iterators
 Do not provide actual data structure
 Programmer can select implementation
 Member functions push and pop
 stack
 Header <stack>
 Insertions and deletions at one end
 Last-in, first-out (LIFO) data structure
 Can use vector, list, or deque (default)
 Declarations
stack<type, vector<type> > myStack;
stack<type, list<type> > myOtherStack;
stack<type> anotherStack; // default deque
 vector, list
Implementation of stack (default deque)
Does not change behavior, just performance (deque and vector fastest)
Algorithms
 Before STL
 Class libraries incompatible among vendors
 Algorithms built into container classes
 STL separates containers and algorithms
 Easier to add new algorithms
 More efficient, avoids virtual function calls
 <algorithm>
Basic Searching and Sorting
Algorithms
 find(iter1, iter2, value)
 Returns iterator to first instance of value (in range)
 find_if(iter1, iter2, function)
 Like find
 Returns iterator when function returns true
 sort(iter1, iter2)
 Sorts elements in ascending order
 binary_search(iter1, iter2, value)
 Searches ascending sorted list for value
 Uses binary search
Function Objects
 Function objects (<functional>)
 Contain functions invoked using operator()
STL function objects Type
divides< T > arithmetic
equal_to< T > relational
greater< T > relational
greater_equal< T > relational
less< T > relational
less_equal< T > relational
logical_and< T > logical
logical_not< T > logical
logical_or< T > logical
minus< T > arithmetic
modulus< T > arithmetic
negate< T > arithmetic
not_equal_to< T > relational
plus< T > arithmetic
multiplies< T > arithmetic
1 // Example 86
2 // Demonstrating function objects.
3 #include <iostream>
4
5 using std::cout;
6 using std::endl;
7
8 #include <vector> // vector class-template definition
9 #include <algorithm> // copy algorithm
10 #include <numeric> // accumulate algorithm
11 #include <functional> // binary_function definition
12
13 // binary function adds square of its second argument and
14 // running total in its first argument, then returns sum
15 int sumSquares( int total, int value )
16 {
17 return total + value * value;
18
19 } // end function sumSquares
20
Create a function to be used
with accumulate.
21 // binary function class template defines overloaded operator()
22 // that adds suare of its second argument and running total in
23 // its first argument, then returns sum
24 template< class T >
25 class SumSquaresClass : public std::binary_function< T, T, T > {
26
27 public:
28
29 // add square of value to total and return result
30 const T operator()( const T &total, const T &value )
31 {
32 return total + value * value;
33
34 } // end function operator()
35
36 }; // end class SumSquaresClass
37
Create a function object (it
can also encapsulate data).
Overload operator().
38 int main()
39 {
40 const int SIZE = 10;
41 int array[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
42
43 std::vector< int > integers( array, array + SIZE );
44
45 std::ostream_iterator< int > output( cout, " " );
46
47 int result = 0;
48
49 cout << "vector v contains:n";
50 std::copy( integers.begin(), integers.end(), output );
51
52 // calculate sum of squares of elements of vector integers
53 // using binary function sumSquares
54 result = std::accumulate( integers.begin(), integers.end(),
55 0, sumSquares );
56
57 cout << "nnSum of squares of elements in integers using "
58 << "binarynfunction sumSquares: " << result;
59
accumulate initially passes
0 as the first argument, with
the first element as the
second. It then uses the return
value as the first argument,
and iterates through the other
elements.
60 // calculate sum of squares of elements of vector integers
61 // using binary-function object
62 result = std::accumulate( integers.begin(), integers.end(),
63 0, SumSquaresClass< int >() );
64
65 cout << "nnSum of squares of elements in integers using "
66 << "binarynfunction object of type "
67 << "SumSquaresClass< int >: " << result << endl;
68
69 return 0;
70
71 } // end main
vector v contains:
1 2 3 4 5 6 7 8 9 10
Sum of squares of elements in integers using binary
function sumSquares: 385
Sum of squares of elements in integers using binary
function object of type SumSquaresClass< int >: 385
Use accumulate with a
function object.
Program Design and Software Tools
Stack/Queue - File Processing
Stack/Queue
Introduction
 Storage of data
 Arrays, variables are temporary
 Files are permanent
 Magnetic disk, optical disk, tapes
 In this chapter
 Create, update, process files
 Sequential and random access
 Formatted and raw processing
The Data Hierarchy
 From smallest to largest
 Bit (binary digit)
 1 or 0
 Character set
Digits, letters, symbols used to represent data
Every character represented by 1's and 0's
 Byte: 8 bits: Can store a character (char)
 From smallest to largest (continued)
 Field: group of characters with some meaning
 Your name
 Record: group of related fields
 struct or class in C++
 In payroll system, could be name, SS#, address, wage
 Each field associated with same employee
 Record key: field used to uniquely identify record
 File: group of related records
 Payroll for entire company
 Sequential file: records stored by key
 Database: group of related files
 Payroll, accounts-receivable, inventory…
Files and Streams
 C++ views file as sequence of bytes
 Ends with end-of-file marker
 When file opened
 Object created, stream associated with it
 cin, cout, etc. created when <iostream> included
 Communication between program and file/device
0 31 2 4 5 8 9
...
... n-1
end-of-file marker
6 7
Files and Streams
 To perform file processing
 Include <iostream> and <fstream>
 Class templates
 basic_ifstream (input)
 basic_ofstream (output)
 basic_fstream (I/O)
 typedefs for specializations that allow char I/O
 ifstream (char input)
 ofstream (char output)
 fstream (char I/O)
Files and Streams
 Opening files
 Create objects from template
 Derive from stream classes
 Can use stream methods : put, get, peek, etc.
basic_fstream
basic_ios
basic_ifstream basic_ofstreambasic_iostream
basic_istream basic_ostream
Creating a Sequential-Access File
 C++ imposes no structure on file
 Concept of "record" must be implemented by programmer
 To open file, create objects
 Creates "line of communication" from object to file
 Classes
 ifstream (input only)
 ofstream (output only)
 fstream (I/O)
 Constructors take file name and file-open mode
ofstream outClientFile( "filename", fileOpenMode );
 To attach a file later
Ofstream outClientFile;
outClientFile.open( "filename", fileOpenMode);
Creating a Sequential-Access File
 File-open modes
 ofstream opened for output by default
 ofstream outClientFile( "clients.dat", ios::out );
 ofstream outClientFile( "clients.dat");
Mode Description
ios::app Write all output to the end of the file.
ios::ate Open a file for output and move to the end of the
file (normally used to append data to a file).
Data can be written anywhere in the file.
ios::in Open a file for input.
ios::out Open a file for output.
ios::trunc Discard the file’s contents if it exists (this is
also the default action for ios::out)
ios::binary Open a file for binary (i.e., non-text) input or
output.
Creating a Sequential-Access File
 Operations
 Overloaded operator!
 !outClientFile
 Returns nonzero (true) if badbit or failbit set
Opened non-existent file for reading, wrong permissions
 Overloaded operator void*
 Converts stream object to pointer
 0 when failbit or badbit set, otherwise nonzero
failbit set when EOF found
 while ( cin >> myVariable )
Implicitly converts cin to pointer
Loops until EOF
 Writing to file (just like cout)
 outClientFile << myVariable
 Closing file
 outClientFile.close()
 Automatically closed when destructor called
1 // Example 87
2 // Create a sequential file.
3 #include <iostream>
4
5 using std::cout;
6 using std::cin;
7 using std::ios;
8 using std::cerr;
9 using std::endl;
10
11 #include <fstream>
12
13 using std::ofstream;
14
15 #include <cstdlib> // exit prototype
16
17 int main()
18 {
19 // ofstream constructor opens file
20 ofstream outClientFile( "clients.dat", ios::out );
21
22 // exit program if unable to create file
23 if ( !outClientFile ) { // overloaded ! operator
24 cerr << "File could not be opened" << endl;
25 exit( 1 );
26
27 } // end if
Notice the the header files
required for file I/O.
ofstream object created
and used to open file
"clients.dat". If the file
does not exist, it is created.
! operator used to test if the
file opened properly.
28
29 cout << "Enter the account, name, and balance." << endl
30 << "Enter end-of-file to end input.n? ";
31
32 int account;
33 char name[ 30 ];
34 double balance;
35
36 // read account, name and balance from cin, then place in file
37 while ( cin >> account >> name >> balance ) {
38 outClientFile << account << ' ' << name << ' ' << balance
39 << endl;
40 cout << "? ";
41
42 } // end while
43
44 return 0; // ofstream destructor closes file
45
46 } // end main
cin is implicitly converted to
a pointer. When EOF is
encountered, it returns 0 and
the loop stops.
Write data to file like a
regular stream.
File closed when destructor
called for object. Can be
explicitly closed with
close().
Enter the account, name, and balance.
Enter end-of-file to end input.
? 100 Jones 24.98
? 200 Doe 345.67
? 300 White 0.00
? 400 Stone -42.16
? 500 Rich 224.62
? ^Z
Reading Data from a Sequential-
Access File
 Reading files
 ifstream inClientFile( "filename", ios::in );
 Overloaded !
 !inClientFile tests if file was opened properly
 operator void* converts to pointer
 while (inClientFile >> myVariable)
 Stops when EOF found (gets value 0)
28 int main()
29 {
30 // ifstream constructor opens the file
31 ifstream inClientFile( "clients.dat", ios::in );
32
33 // exit program if ifstream could not open file
34 if ( !inClientFile ) {
35 cerr << "File could not be opened" << endl;
36 exit( 1 );
37
38 } // end if
39
40 int account;
41 char name[ 30 ];
42 double balance;
43
44 cout << left << setw( 10 ) << "Account" << setw( 13 )
45 << "Name" << "Balance" << endl << fixed << showpoint;
46
47 // display each record in file
48 while ( inClientFile >> account >> name >> balance )
49 outputLine( account, name, balance );
50
51 return 0; // ifstream destructor closes the file
52
53 } // end main
Open and test file for input.
Read from file until EOF
found.
54
55 // display single record from file
56 void outputLine( int account, const char * const name,
57 double balance )
58 {
59 cout << left << setw( 10 ) << account << setw( 13 ) << name
60 << setw( 7 ) << setprecision( 2 ) << right << balance
61 << endl;
62
63 } // end function outputLine
Account Name Balance
100 Jones 24.98
200 Doe 345.67
300 White 0.00
400 Stone -42.16
500 Rich 224.62
Reading Data from a Sequential-
Access File
 File position pointers
 Number of next byte to read/write
 Functions to reposition pointer
 seekg (seek get for istream class)
 seekp (seek put for ostream class)
 Classes have "get" and "put" pointers
 seekg and seekp take offset and direction
 Offset: number of bytes relative to direction
 Direction (ios::beg default)
ios::beg - relative to beginning of stream
ios::cur - relative to current position
ios::end - relative to end
Reading Data from a Sequential-
Access File
 Examples
 fileObject.seekg(0)
 Goes to front of file (location 0) because ios::beg is default
 fileObject.seekg(n)
 Goes to nth byte from beginning
 fileObject.seekg(n, ios::cur)
 Goes n bytes forward
 fileObject.seekg(y, ios::end)
 Goes y bytes back from end
 fileObject.seekg(0, ios::cur)
 Goes to last byte
 seekp similar
 To find pointer location
 tellg and tellp
 location = fileObject.tellg()
Updating Sequential-Access Files
 Updating sequential files
 Risk overwriting other data
 Example: change name "White" to "Worthington"
 Old data
300 White 0.00 400 Jones 32.87
 Insert new data
 Formatted text different from internal representation
 Problem can be avoided, but awkward
300 White 0.00 400 Jones 32.87
300 Worthington 0.00ones 32.87
300 Worthington 0.00
Data gets overwritten
Random-Access Files
 Instant access
 Want to locate record quickly
 Airline reservations, ATMs
 Sequential files must search through each one
 Random-access files are solution
 Instant access
 Insert record without destroying other data
 Update/delete items without changing other data
Random-Access Files
 C++ imposes no structure on files
 Programmer must create random-access files
 Simplest way: fixed-length records
 Calculate position in file from record size and key
0 200 300 400 500
byte offsets
}
}
}
}
}
}
}
100
100
bytes
100
bytes
100
bytes
100
bytes
100
bytes
100
bytes
Creating a Random-Access File
 "1234567" (char *) vs 1234567 (int)
 char * takes 8 bytes (1 for each character + null)
 int takes fixed number of bytes (perhaps 4)
 123 same size in bytes as 1234567
 << operator and write()
 outFile << number
 Outputs number (int) as a char *
 Variable number of bytes
 outFile.write( const char *, size );
 Outputs raw bytes
 Takes pointer to memory location, number of bytes to write
Copies data directly from memory into file
Does not convert to char *
Creating a Random-Access File
 Example
outFile.write( reinterpret_cast<const char *>(&number), sizeof(
number ) );
 &number is an int *
 Convert to const char * with reinterpret_cast
 sizeof(number)
 Size of number (an int) in bytes
 read function similar (more later)
 Must use write/read between compatible machines
 Only when using raw, unformatted data
 Use ios::binary for raw writes/reads
 Usually write entire struct or object to file
Writing Data Randomly to a Random-Access
File
 Use seekp to write to exact location in file
 Where does the first record begin?
 Byte 0
 The second record?
 Byte 0 + sizeof(object)
 Any record?
 (Recordnum - 1) * sizeof(object)
 read - similar to write
 Reads raw bytes from file into memory
 inFile.read( reinterpret_cast<char *>( &number ),
sizeof( int ) );
 &number: location to store data
 sizeof(int): how many bytes to read
 Do not use inFile >> number with raw bytes
 >> expects char *
Input/Output of Objects
 I/O of objects
 Chapter 8 (overloaded >>)
 Only object's data transmitted
 Member functions available internally
 When objects stored in file, lose type info (class, etc.)
 Program must know type of object when reading
 One solution
 When writing, output object type code before real object
 When reading, read type code
Call proper overloaded function (switch)
Program Design and Software Tools
Exception Handling
Exception Handling
Introduction
 Exceptions
 Indicates problem occurred in program
 Not common
 An "exception" to a program that usually works
 Exception Handling
 Resolve exceptions
 Program may be able to continue
 Controlled termination
 Write fault-tolerant programs
Exception-Handling Overview
 Consider pseudocode
Perform a task
If the preceding task did not execute correctly
Perform error processing
Perform next task
If the preceding task did not execute correctly
Perform error processing
 Mixing logic and error handling
 Can make program difficult to read/debug
 Exception handling removes error correction from "main line" of program
Exception-Handling Overview
 Exception handling
 For synchronous errors (divide by zero, null pointer)
 Cannot handle asynchronous errors (independent of program)
 Disk I/O, mouse, keyboard, network messages
 Easy to handle errors
 Terminology
 Function that has error throws an exception
 Exception handler (if it exists) can deal with problem
 Catches and handles exception
 If no exception handler, uncaught exception
 Could terminate program
Exception-Handling Overview
 C++ code
try {
code that may raise exception
}
catch (exceptionType){
code to handle exception
}
 try block encloses code that may raise exception
 One or more catch blocks follow
 Catch and handle exception, if appropriate
 Take parameter; if named, can access exception object
Exception-Handling Overview
 Throw point
 Location in try block where exception occurred
 If exception handled
 Program skips remainder of try block
 Resumes after catch blocks
 If not handled
 Function terminates
 Looks for enclosing catch block (stack unwinding)
 If no exception
 Program skips catch blocks
Other Error-Handling Techniques
 Ignore exception
 Typical for personal (not commercial) software
 Program may fail
 Abort program
 Usually appropriate
 Not appropriate for mission-critical software
 Set error indicators
 Unfortunately, may not test for these when necessary
 Test for error condition
 Call exit (<cstdlib>) and pass error code
Other Error-Handling Techniques
 setjump and longjump
 <csetjmp>
 Jump from deeply nested function to call error handler
 Can be dangerous
 Dedicated error handling
 new can have a special handler
Simple Exception-Handling
Example: Divide by Zero
 Keyword throw
 Throws an exception
 Use when error occurs
 Can throw almost anything (exception object, integer, etc.)
 throw myObject;
 throw 5;
 Exception objects
 Base class runtime_error ( <stdexcept> )
 Constructor can take a string (to describe exception)
 Member function what() returns that string
Simple Exception-Handling
Example: Divide by Zero
 Upcoming example
 Handle divide-by-zero errors
 Define new exception class
 DivideByZeroException
 Inherit from runtime_error
 In division function
 Test denominator
 If zero, throw exception (throw object)
 In try block
 Attempt to divide
 Have enclosing catch block
Catch DivideByZeroException objects
1 // Example 88
2 // A simple exception-handling example that checks for
3 // divide-by-zero exceptions.
4 #include <iostream>
5
6 using std::cout;
7 using std::cin;
8 using std::endl;
9
10 #include <exception>
11
12 using std::exception;
13
14 // DivideByZeroException objects should be thrown by functions
15 // upon detecting division-by-zero exceptions
16 class DivideByZeroException : public runtime_error {
17
18 public:
19
20 // constructor specifies default error message
21 DivideByZeroException::DivideByZeroException()
22 : exception( "attempted to divide by zero" ) {}
23
24 }; // end class DivideByZeroException
25
Define new exception class
(inherit from runtime_error
). Pass a descriptive message
to the constructor.
26 // perform division and throw DivideByZeroException object if
27 // divide-by-zero exception occurs
28 double quotient( int numerator, int denominator )
29 {
30 // throw DivideByZeroException if trying to divide by zero
31 if ( denominator == 0 )
32 throw DivideByZeroException(); // terminate function
33
34 // return division result
35 return static_cast< double >( numerator ) / denominator;
36
37 } // end function quotient
38
39 int main()
40 {
41 int number1; // user-specified numerator
42 int number2; // user-specified denominator
43 double result; // result of division
44
45 cout << "Enter two integers (end-of-file to end): ";
46
If the denominator is zero, throw
a DivideByZeroException
object.
47 // enable user to enter two integers to divide
48 while ( cin >> number1 >> number2 ) {
49
50 // try block contains code that might throw exception
51 // and code that should not execute if an exception occurs
52 try {
53 result = quotient( number1, number2 );
54 cout << "The quotient is: " << result << endl;
55
56 } // end try
57
58 // exception handler handles a divide-by-zero exception
59 catch ( DivideByZeroException &divideByZeroException ) {
60 cout << "Exception occurred: "
61 << divideByZeroException.what() << endl;
62
63 } // end catch
64
65 cout << "nEnter two integers (end-of-file to end): ";
66
67 } // end while
68
69 cout << endl;
70
71 return 0; // terminate normally
72
73 } // end main
Notice the structure of the try
and catch blocks. The catch
block can catch
DivideByZeroException
objects, and print an error
message. If no exception occurs,
the catch block is skipped.
Member function what returns
the string describing the
exception.
Enter two integers (end-of-file to end): 100 7
The quotient is: 14.2857
Enter two integers (end-of-file to end): 100 0
Exception occurred: attempted to divide by zero
Enter two integers (end-of-file to end): ^Z
Rethrowing an Exception
 Rethrowing exceptions
 Use when exception handler cannot process exception
 Can still rethrow if handler did some processing
 Can rethrow exception to another handler
 Goes to next enclosing try block
 Corresponding catch blocks try to handle
 To rethrow
 Use statement "throw;"
 No arguments
 Terminates function
1 // Example 89
2 // Demonstrating exception rethrowing.
3 #include <iostream>
4
5 using std::cout;
6 using std::endl;
7
8 #include <exception>
9
10 using std::exception;
11
12 // throw, catch and rethrow exception
13 void throwException()
14 {
15 // throw exception and catch it immediately
16 try {
17 cout << " Function throwException throws an exceptionn";
18 throw exception(); // generate exception
19
20 } // end try
21
22 // handle exception
23 catch ( exception &caughtException ) {
24 cout << " Exception handled in function throwException"
25 << "n Function throwException rethrows exception";
26
27 throw; // rethrow exception for further processing
28
29 } // end catch
Exception handler generates a
default exception (base class
exception). It immediately
catches and rethrows it (note
use of throw;).
30
31 cout << "This also should not printn";
32
33 } // end function throwException
34
35 int main()
36 {
37 // throw exception
38 try {
39 cout << "nmain invokes function throwExceptionn";
40 throwException();
41 cout << "This should not printn";
42
43 } // end try
44
45 // handle exception
46 catch ( exception &caughtException ) {
47 cout << "nnException handled in mainn";
48
49 } // end catch
50
51 cout << "Program control continues after catch in mainn";
52
53 return 0;
54
55 } // end main
This should never be reached,
since the throw immediately
exits the function.
throwException rethrows
an exception to main. It is
caught and handled.
main invokes function throwException
Function throwException throws an exception
Exception handled in function throwException
Function throwException rethrows exception
Exception handled in main
Program control continues after catch in main
Exception Specifications
 List of exceptions function can throw
 Also called throw list
int someFunction( double value )
throw ( ExceptionA, ExceptionB, ExceptionC )
{
// function body
}
 Can only throw ExceptionA, ExceptionB, and ExceptionC (and derived
classes)
 If throws other type, function unexpected called
 By default, terminates program (more 13.7)
 If no throw list, can throw any exception
 If empty throw list, cannot throw any exceptions
Processing Unexpected Exceptions
 Function unexpected
 Calls function registered with set_unexpected
 <exception>
 Calls terminate by default
 set_terminate
 Sets what function terminate calls
 By default, calls abort
If redefined, still calls abort after new function finishes
 Arguments for set functions
 Pass pointer to function
 Function must take no arguments
 Returns void
Stack Unwinding
 If exception thrown but not caught
 Goes to enclosing try block
 Terminates current function
 Unwinds function call stack
 Looks for try/catch that can handle exception
 If none found, unwinds again
 If exception never caught
 Calls terminate
1 // Example 90
2 // Demonstrating stack unwinding.
3 #include <iostream>
4
5 using std::cout;
6 using std::endl;
7
8 #include <stdexcept>
9
10 using std::runtime_error;
11
12 // function3 throws run-time error
13 void function3() throw ( runtime_error )
14 {
15 throw runtime_error( "runtime_error in function3" ); // fourth
16 }
17
18 // function2 invokes function3
19 void function2() throw ( runtime_error )
20 {
21 function3(); // third
22 }
23
Note the use of the throw list.
Throws a runtime error
exception, defined in
<stdexcept>.
24 // function1 invokes function2
25 void function1() throw ( runtime_error )
26 {
27 function2(); // second
28 }
29
30 // demonstrate stack unwinding
31 int main()
32 {
33 // invoke function1
34 try {
35 function1(); // first
36
37 } // end try
38
39 // handle run-time error
40 catch ( runtime_error &error ) // fifth
41 {
42 cout << "Exception occurred: " << error.what() << endl;
43
44 } // end catch
45
46 return 0;
47
48 } // end main
Exception occurred: runtime_error in function3
function1 calls
function2 which calls
function3. The exception
occurs, and unwinds until an
appropriate try/catch
block can be found.
Constructors, Destructors and Exception Handling
 Error in constructor
 new fails; cannot allocate memory
 Cannot return a value - how to inform user?
 Hope user examines object, notices errors
 Set some global variable
 Good alternative: throw an exception
 Destructors automatically called for member objects
 Called for automatic variables in try block
 Can catch exceptions in destructor
Exceptions and Inheritance
 Exception classes
 Can be derived from base classes
 I.e., runtime_error; exception
 If catch can handle base class, can handle derived classes
 Polymorphic programming
Processing new Failures
 When new fails to get memory
 Should throw bad_alloc exception
 Defined in <new>
 Some compilers have new return 0
 Result depends on compiler
1 // Example 91
2 // Demonstrating pre-standard new returning 0 when memory
3 // is not allocated.
4 #include <iostream>
5
6 using std::cout;
7
8 int main()
9 {
10 double *ptr[ 50 ];
11
12 // allocate memory for ptr
13 for ( int i = 0; i < 50; i++ ) {
14 ptr[ i ] = new double[ 5000000 ];
15
16 // new returns 0 on failure to allocate memory
17 if ( ptr[ i ] == 0 ) {
18 cout << "Memory allocation failed for ptr[ "
19 << i << " ]n";
20
21 break;
22
23 } // end if
24
Demonstrating new that
returns 0 on allocation
failure.
25 // successful memory allocation
26 else
27 cout << "Allocated 5000000 doubles in ptr[ "
28 << i << " ]n";
29
30 } // end for
31
32 return 0;
33
34 } // end main
Allocated 5000000 doubles in ptr[ 0 ]
Allocated 5000000 doubles in ptr[ 1 ]
Allocated 5000000 doubles in ptr[ 2 ]
Allocated 5000000 doubles in ptr[ 3 ]
Memory allocation failed for ptr[ 4 ]
1 // Example 92
2 // Demonstrating standard new throwing bad_alloc when memory
3 // cannot be allocated.
4 #include <iostream>
5
6 using std::cout;
7 using std::endl;
8
9 #include <new> // standard operator new
10
11 using std::bad_alloc;
12
13 int main()
14 {
15 double *ptr[ 50 ];
16
17 // attempt to allocate memory
18 try {
19
20 // allocate memory for ptr[ i ]; new throws bad_alloc
21 // on failure
22 for ( int i = 0; i < 50; i++ ) {
23 ptr[ i ] = new double[ 5000000 ];
24 cout << "Allocated 5000000 doubles in ptr[ "
25 << i << " ]n";
26 }
27
28 } // end try
Demonstrating new that
throws an exception.
29
30 // handle bad_alloc exception
31 catch ( bad_alloc &memoryAllocationException ) {
32 cout << "Exception occurred: "
33 << memoryAllocationException.what() << endl;
34
35 } // end catch
36
37 return 0;
38
39 } // end main
Allocated 5000000 doubles in ptr[ 0 ]
Allocated 5000000 doubles in ptr[ 1 ]
Allocated 5000000 doubles in ptr[ 2 ]
Allocated 5000000 doubles in ptr[ 3 ]
Exception occurred: Allocation Failure
Processing new Failures
 set_new_handler
 Header <new>
 Register function to call when new fails
 Takes function pointer to function that
 Takes no arguments
 Returns void
 Once registered, function called instead of throwing exception
1 // Example 93
2 // Demonstrating set_new_handler.
3 #include <iostream>
4
5 using std::cout;
6 using std::cerr;
7
8 #include <new> // standard operator new and set_new_handler
9
10 using std::set_new_handler;
11
12 #include <cstdlib> // abort function prototype
13
14 void customNewHandler()
15 {
16 cerr << "customNewHandler was called";
17 abort();
18 }
19
20 // using set_new_handler to handle failed memory allocation
21 int main()
22 {
23 double *ptr[ 50 ];
24
The custom handler must take
no arguments and return
void.
25 // specify that customNewHandler should be called on failed
26 // memory allocation
27 set_new_handler( customNewHandler );
28
29 // allocate memory for ptr[ i ]; customNewHandler will be
30 // called on failed memory allocation
31 for ( int i = 0; i < 50; i++ ) {
32 ptr[ i ] = new double[ 5000000 ];
33
34 cout << "Allocated 5000000 doubles in ptr[ "
35 << i << " ]n";
36
37 } // end for
38
39 return 0;
40
41 } // end main
Allocated 5000000 doubles in ptr[ 0 ]
Allocated 5000000 doubles in ptr[ 1 ]
Allocated 5000000 doubles in ptr[ 2 ]
Allocated 5000000 doubles in ptr[ 3 ]
customNewHandler was called
Note call to
set_new_handler.
Class auto_ptr and Dynamic Memory Allocation
 Declare pointer, allocate memory with new
 What if exception occurs before you can delete it?
 Memory leak
 Template class auto_ptr
 Header <memory>
 Like regular pointers (has * and ->)
 When pointer goes out of scope, calls delete
 Prevents memory leaks
 Usage
auto_ptr< MyClass > newPointer( new MyClass() );
 newPointer points to dynamically allocated object
1 // Example 94
2 // Demonstrating auto_ptr.
3 #include <iostream>
4
5 using std::cout;
6 using std::endl;
7
8 #include <memory>
9
10 using std::auto_ptr; // auto_ptr class definition
11
12 class Integer {
13
14 public:
15
16 // Integer constructor
17 Integer( int i = 0 )
18 : value( i )
19 {
20 cout << "Constructor for Integer " << value << endl;
21
22 } // end Integer constructor
23
24 // Integer destructor
25 ~Integer()
26 {
27 cout << "Destructor for Integer " << value << endl;
28
29 } // end Integer destructor
30
31 // function to set Integer
32 void setInteger( int i )
33 {
34 value = i;
35
36 } // end function setInteger
37
38 // function to return Integer
39 int getInteger() const
40 {
41 return value;
42
43 } // end function getInteger
44
45 private:
46 int value;
47
48 }; // end class Integer
49
50 // use auto_ptr to manipulate Integer object
51 int main()
52 {
53 cout << "Creating an auto_ptr object that points to an "
54 << "Integern";
55
56 // "aim" auto_ptr at Integer object
57 auto_ptr< Integer > ptrToInteger( new Integer( 7 ) );
58
59 cout << "nUsing the auto_ptr to manipulate the Integern";
60
61 // use auto_ptr to set Integer value
62 ptrToInteger->setInteger( 99 );
63
64 // use auto_ptr to get Integer value
65 cout << "Integer after setInteger: "
66 << ( *ptrToInteger ).getInteger()
67 << "nnTerminating program" << endl;
68
69 return 0;
70
71 } // end main
Create an auto_ptr. It can
be manipulated like a regular
pointer.
delete not explicitly called,
but the auto_ptr will be
destroyed once it leaves
scope. Thus, the destructor for
class Integer will be
called.
Creating an auto_ptr object that points to an Integer
Constructor for Integer 7
Using the auto_ptr to manipulate the Integer
Integer after setInteger: 99
Terminating program
Destructor for Integer 99
Standard Library Exception Hierarchy
 Exception hierarchy
 Base class exception (<exception>)
 Virtual function what, overridden to provide error messages
 Sample derived classes
 runtime_error, logic_error
 bad_alloc, bad_cast, bad_typeid
Thrown by new, dynamic_cast and typeid
 To catch all exceptions
 catch(...)
 catch( exception AnyException)
 Will not catch user-defined exceptions
Program Design and Software Tools
Preprocessing
Preprocessing
Preprocessing
 Preprocessing
 Occurs before program compiled
 Inclusion of external files
 Definition of symbolic constants
 Macros
 Conditional compilation
 Conditional execution pf preprocessing directive
 All directives begin with #
 Can only have whitespace before directives
 Directives not C++ statements
 Do not end with ;
The #include Preprocessor
Directive
 #include directive
 Puts copy of file in place of directive
 Two forms
 #include <filename>
For standard library header files
Searches pre-designated directories
 #include "filename"
Searches in current directory
Normally used for programmer-defined files
 Usage
 Loading header files
 #include <iostream>
 Programs with multiple source files
 Header file
 Has common declarations and definitions
 Classes, structures, enumerations, function prototypes
 Extract commonality of multiple program files
The #define Preprocessor
Directive: Symbolic Constants
 #define
 Symbolic constants
 Constants represented as symbols
 When program compiled, all occurrences replaced
 Format
 #define identifier replacement-text
 #define PI 3.14159
 Everything to right of identifier replaces text
 #define PI=3.14159
 Replaces PI with "=3.14159"
 Probably an error
 Cannot redefine symbolic constants
 Advantage: Takes no memory
 Disadvantages
 Name not seen by debugger (only replacement text)
 Do not have specific data type
 const variables preferred
The #define Preprocessor
Directive: Macros
 Macro
 Operation specified in #define
 Macro without arguments
 Treated like a symbolic constant
 Macro with arguments
 Arguments substituted for replacement text
 Macro expanded
 Performs a text substitution
 No data type checking
The #define Preprocessor
Directive: Macros
 Example
#define CIRCLE_AREA( x ) ( PI * ( x ) * ( x ) )
area = CIRCLE_AREA( 4 );
becomes
area = ( 3.14159 * ( 4 ) * ( 4 ) );
 Use parentheses
 Without them,
#define CIRCLE_AREA( x ) PI * x * x
area = CIRCLE_AREA( c + 2 );
becomes
area = 3.14159 * c + 2 * c + 2;
which evaluates incorrectly
The #define Preprocessor
Directive: Macros
 Multiple arguments
#define RECTANGLE_AREA( x, y ) ( ( x ) * ( y ) )
rectArea = RECTANGLE_AREA( a + 4, b + 7 );
becomes
rectArea = ( ( a + 4 ) * ( b + 7 ) );
 #undef
 Undefines symbolic constant or macro
 Can later be redefined
Conditional Compilation
 Control preprocessor directives and compilation
 Cannot evaluate cast expressions, sizeof, enumeration constants
 Structure similar to if
#if !defined( NULL )
#define NULL 0
#endif
 Determines if symbolic constant NULL defined
 If NULL defined,
 defined( NULL ) evaluates to 1
 #define statement skipped
 Otherwise
 #define statement used
 Every #if ends with #endif
Conditional Compilation
 Can use else
 #else
 #elif is "else if"
 Abbreviations
 #ifdef short for
 #if defined(name)
 #ifndef short for
 #if !defined(name)
 "Comment out" code
 Cannot use /* ... */ with C-style comments
 Cannot nest /* */
 Instead, use
#if 0
code commented out
#endif
 To enable code, change 0 to 1
Conditional Compilation
 Debugging
#define DEBUG 1
#ifdef DEBUG
cerr << "Variable x = " << x << endl;
#endif
 Defining DEBUG enables code
 After code corrected
 Remove #define statement
 Debugging statements are now ignored
The #error and #pragma
Preprocessor Directives
 #error tokens
 Prints implementation-dependent message
 Tokens are groups of characters separated by spaces
 #error 1 - Out of range error has 6 tokens
 Compilation may stop (depends on compiler)
 #pragma tokens
 Actions depend on compiler
 May use compiler-specific options
 Unrecognized #pragmas are ignored
The # and ## Operators
 # operator
 Replacement text token converted to string with quotes
#define HELLO( x ) cout << "Hello, " #x << endl;
 HELLO( JOHN ) becomes
 cout << "Hello, " "John" << endl;
 Same as cout << "Hello, John" << endl;
 ## operator
 Concatenates two tokens
#define TOKENCONCAT( x, y ) x ## y
 TOKENCONCAT( O, K ) becomes
 OK
Line Numbers
 #line
 Renumbers subsequent code lines, starting with integer
 #line 100
 File name can be included
 #line 100 "file1.cpp"
 Next source code line is numbered 100
 For error purposes, file name is "file1.cpp"
 Can make syntax errors more meaningful
 Line numbers do not appear in source file
Predefined Symbolic
Constants
 Five predefined symbolic constants
 Cannot be used in #define or #undef
Symbolic
constant Description
__LINE__ The line number of the current source code line (an integer constant).
__FILE__ The presumed name of the source file (a string).
__DATE__ The date the source file is compiled (a string of the form "Mmm dd
yyyy" such as "Jan 19 2001").
__TIME__ The time the source file is compiled (a string literal of the form
"hh:mm:ss").
Assertions
 assert is a macro
 Header <cassert>
 Tests value of an expression
 If 0 (false) prints error message, calls abort
Terminates program, prints line number and file
Good for checking for illegal values
 If 1 (true), program continues as normal
 assert( x <= 10 );
 To remove assert statements
 No need to delete them manually
 #define NDEBUG
 All subsequent assert statements ignored
Program Design and Software Tools
Unified Modeling Language
Unified Modeling Language
What is UML?
The Unified Modelling Language is a standard notation to model
[object oriented] systems.
Syntax and semantics
Model systems
Visual documentations
Collections of best practices
Used to produce a set of artifacts that can be delivered
Wide support
Independent of programming languages
Support high level concepts
UML Diagram Types
Use Case diagrams
Static structure diagrams
Class diagrams
Object diagrams
Interaction diagrams
Sequence diagrams
Collaboration diagrams
Statechart diagrams
Activity diagrams
Component diagrams
Deployment diagram
Copyright © 1997 by Rational Software Corporation
Actors
 An actor is someone or some thing that must interact with the system under
development
Student
Registrar
Professor
Billing System
Use Cases
 A use case is a pattern of behavior the system exhibits
 Each use case is a sequence of related transactions performed by an actor and the
system in a dialogue
 Actors are examined to determine their needs
 Registrar -- maintain the curriculum
 Professor -- request roster
 Student -- maintain schedule
Maintain ScheduleMaintain Curriculum Request Course Roster
Use Case Diagram
 Use case diagrams are created to visualize the relationships between actors and use
cases
Student
Registrar
Professor
Maintain Schedule
Maintain Curriculum
Request Course Roster
Billing System
Use Case Realizations
 The use case diagram presents an outside view of the system
 Interaction diagrams describe how use cases are realized as interactions among
societies of objects
 Two types of interaction diagrams
 Sequence diagrams
 Collaboration diagrams
Class Diagram
Class diagrams are the most commonly used diagrams in
UML.
Class diagrams are for visualizing, specifying and
documenting the system from a static perspective.
Class diagrams indicate which classes know about other
classes and, if they do, what type of relationship exists.
Class diagrams will have different levels of detail
(abstraction) depending on where we are in the software
development process.
Class Diagrams
Class diagrams describe types of objects in a system and their
relationships.
There are three types of relationships between classes:
• Dependency (“uses”)
• Aggregation (“has”)
• Inheritance (“is”)
Class diagrams also show the attributes and operations of a
class.
Class Diagrams
Class diagrams consist of several classes connected with
relationships
Representation of a class:
Class Diagram
Convention
Name of class is a word with initial upper case letter
Capitalize first letter of every word in name
Name of attributes is lower case letter
Capitalize first letter of every word other than first
Operations have same naming schemes as attributes
Brackets include parameter operation works on
Associations
 “relationship between different objects of one or more classes”
Connectors
Multiplicities
UML Class Diagram
Class
Association
Label Multiplicity
Class
 Derived from the CRC Cards
 Sections: name, attributes, operations
Construct Description Syntax
class a description of a set of objects that
share the same attributes, operations,
methods, relationships and semantics.
Name
Attributes
Methods
Association
 It is more important to identify classes than to identify associations
 Too many associations can be confusing
 Classes may have association with themselves
person
manages
1*
Construct Description Syntax
association a relationship between two or more
classifiers that involves connections
among their instances.
Generalization
Generalization: identifying
commonality among classes
Construct Description Syntax
generalization a taxonomic relationship between a
more general and a more specific
element.
Aggregation
A composite aggregation (filled diamond) means that the
multiplicity at the composite end may be at most one.
Shared aggregation (hollow diamond) means that the multiplicity
at the composite end may be more than one.
Construct Description Syntax
aggregation A special form of association that
specifies a whole-part relationship
between the aggregate (whole) and
the component part.
Aggregation Guidelines
There is an obvious physical or
logical assembly
The part and composite have
the same lifetime
Operations applied to the composite propagate to the parts
e.g. destruction, movement, etc.
Objects and Inheritance
subtype
supertype
dependency
Classifier
A classifier is a mechanism that describes structural and
behavioral features.
Types of classifiers are …
classes, interfaces, datatypes, signals, components, nodes, use cases
and subsystems.
Classes are the most important kind of classifier.
Classes have a number of features beyond attributes and behaviors
that allow you to model some of the more subtle/advanced features
of a system.
Advanced Class Features
Abstract and Concrete Classes and Operations
Template Icon
 A parameterized element.
 Represented in UML as a
dashed box in the upper right-
hand corner of the class icon,
which lists the template
parameters.
State Transition Diagram
Initialization
Open
entry: Register student
exit: Increment count
Closed
Canceled
do: Initialize course
do: Finalize course
do: Notify registered students
Add Student /
Set count = 0
Add student[ count < 10 ]
[ count = 10 ]
Cancel
Cancel
Cancel
Sequence Diagram
 A sequence diagram displays object interactions arranged in a time sequence
: Student registration
form
registration
manager
math 101
1: fill in info
2: submit
3: add course(joe, math 01)
4: are you open?
5: are you open?
6: add (joe)
7: add (joe)
math 101
section 1
: Registrar
course form :
CourseForm
theManager :
CurriculumManager
aCourse :
Course
1: set course info
2: process
3: add course
4: new course
Collaboration Diagram
 A collaboration diagram displays object interactions organized around objects and their
links to one another
The Physical World
 Component diagrams illustrate the organizations and dependencies among software
components
 A component may be
 A source code component
 A run time components or
 An executable component
Component Diagram
Course
Course
Offering
Student
Professor
Course.dll
People.dll
Course
User
Register.exe
Billing.exe
Billing
System
Deploying the System
 The deployment diagram shows the configuration of run-time processing elements and
the software processes living on them
 The deployment diagram visualizes the distribution of components across the
enterprise.
Deployment Diagram
Registration Database
Library
Dorm
Main
Building
Review topics
1. Lvalue/rvalue
2. Reference variable + Calling functions by reference
3. Passing arrays to functions
4. Function pointers
5. Arrays of pointers to functions (e.g. menus)
6. Using member selection operators ('.' '->')
7. Returning a reference to a private data member
8. *this pointer
1. implicit & explicit use of *this pointer
2. *this pointer & cascaded function calls
9. When are destructors used, why not yet in the classes we're creating?
10. When is it appropriate to use 'new' and 'delete' from the <new> library?
11. Classes?
12. Polymorphism?
13. Multiple Inheritance?
Confusing Equality (==) and
Assignment (=) Operators
 Lvalues
 Expressions that can appear on left side of equation
 Can be changed
x = 4;
 Rvalues
 Only appear on right side of equation
 Constants, such as numbers (i.e. cannot write 4 = x;)
 Lvalues can be used as rvalues, but not vice versa
References and Reference
Parameters
 Call by value
 Copy of data passed to function
 Changes to copy do not change original
 Prevent unwanted side effects
 Call by reference
 Function can directly access data
 Changes affect original
 Reference parameter
 Alias for argument in function call
 Passes parameter by reference
 Use & after data type in prototype
 void myFunction( int &data )
 Read “data is a reference to an int”
 Function call format the same
 However, original can now be changed
References and Reference
Parameters
 Pointers
 Another way to pass-by-refernce
 References as aliases to other variables
 Refer to same variable
 Can be used within a function
int count = 1; // declare integer variable count
int &cRef = count; // create cRef as an alias for count
++cRef; // increment count (using its alias)
 References must be initialized when declared
 Otherwise, compiler error
 Dangling reference
 Reference to undefined variable
Passing Arrays to Functions
 Specify name without brackets
 To pass array myArray to myFunction
int myArray[ 24 ];
myFunction( myArray, 24 );
 Array size usually passed, but not required
 Useful to iterate over all elements
 Arrays passed-by-reference
 Functions can modify original array data
 Value of name of array is address of first element
 Function knows where the array is stored
 Can change original memory locations
Passing Arrays to Functions
 Functions taking arrays
 Function prototype
 void modifyArray( int b[], int arraySize );
 void modifyArray( int [], int );
Names optional in prototype
 Both take an integer array and a single integer
 No need for array size between brackets
 Ignored by compiler
 If declare array parameter as const
 Cannot be modified (compiler error)
 void doNotModify( const int [] );
Using const with Pointers
const qualifier
Value of variable should not be modified
const used when function does not need to change a variable
Principle of least privilege
const pointers
Always point to same memory location
Default for array name
Must be initialized when declared
Four ways to pass pointer to function
Nonconstant pointer to nonconstant data
 Highest amount of access
Nonconstant pointer to constant data
Constant pointer to nonconstant data
Constant pointer to constant data
 Least amount of access
1 // Example 95
2 // Attempting to modify a constant pointer to
3 // non-constant data.
4
5 int main()
6 {
7 int x, y;
8
9 // ptr is a constant pointer to an integer that can
10 // be modified through ptr, but ptr always points to the
11 // same memory location.
12 int * const ptr = &x;
13
14 *ptr = 7; // allowed: *ptr is not const
15 ptr = &y; // error: ptr is const; cannot assign new address
16
17 return 0; // indicates successful termination
18
19 } // end main
ptr is constant pointer to
integer.Can modify x (pointed to by
ptr) since x not constant.Cannot modify ptr to point
to new address since ptr is
constant.
Line 15 generates compiler
error by attempting to assign
new address to constant
pointer.
d:cpphtp4_examplesch05Fig05_13.cpp(15) : error C2166:
l-value specifies const object
1 // Example 96
2 // Attempting to modify a constant pointer to constant data.
3 #include <iostream>
4
5 using std::cout;
6 using std::endl;
7
8 int main()
9 {
10 int x = 5, y;
11
12 // ptr is a constant pointer to a constant integer.
13 // ptr always points to the same location; the integer
14 // at that location cannot be modified.
15 const int *const ptr = &x;
16
17 cout << *ptr << endl;
18
19 *ptr = 7; // error: *ptr is const; cannot assign new value
20 ptr = &y; // error: ptr is const; cannot assign new address
21
22 return 0; // indicates successful termination
23
24 } // end main
ptr is constant pointer to
integer constant.
Cannot modify x (pointed to
by ptr) since *ptr declared
constant.
Cannot modify ptr to point
to new address since ptr is
constant.
Relationship Between Pointers
and Arrays
 Arrays and pointers closely related
 Array name like constant pointer
 Pointers can do array subscripting operations
 Accessing array elements with pointers
 Element b[ n ] can be accessed by *( bPtr + n )
 Called pointer/offset notation
 Addresses
 &b[ 3 ] same as bPtr + 3
 Array name can be treated as pointer
 b[ 3 ] same as *( b + 3 )
 Pointers can be subscripted (pointer/subscript notation)
 bPtr[ 3 ] same as b[ 3 ]
Function Pointers
 Calling functions using pointers
 Assume parameter:
 bool ( *compare ) ( int, int )
 Execute function with either
 ( *compare ) ( int1, int2 )
Dereference pointer to function to execute
OR
 compare( int1, int2 )
Could be confusing
 User may think compare name of actual function in program
1 //Example 97
2 // Multipurpose sorting program using function pointers.
3 #include <iostream>
4
5 using std::cout;
6 using std::cin;
7 using std::endl;
8
9 #include <iomanip>
10
11 using std::setw;
12
13 // prototypes
14 void bubble( int [], const int, bool (*)( int, int ) );
15 void swap( int * const, int * const );
16 bool ascending( int, int );
17 bool descending( int, int );
18
19 int main()
20 {
21 const int arraySize = 10;
22 int order;
23 int counter;
24 int a[ arraySize ] = { 2, 6, 4, 8, 10, 12, 89, 68, 45, 37 };
25
Parameter is pointer to
function that receives two
integer parameters and returns
bool result.
26 cout << "Enter 1 to sort in ascending order,n"
27 << "Enter 2 to sort in descending order: ";
28 cin >> order;
29 cout << "nData items in original ordern";
30
31 // output original array
32 for ( counter = 0; counter < arraySize; counter++ )
33 cout << setw( 4 ) << a[ counter ];
34
35 // sort array in ascending order; pass function ascending
36 // as an argument to specify ascending sorting order
37 if ( order == 1 ) {
38 bubble( a, arraySize, ascending );
39 cout << "nData items in ascending ordern";
40 }
41
42 // sort array in descending order; pass function descending
43 // as an agrument to specify descending sorting order
44 else {
45 bubble( a, arraySize, descending );
46 cout << "nData items in descending ordern";
47 }
48
49 // output sorted array
50 for ( counter = 0; counter < arraySize; counter++ )
51 cout << setw( 4 ) << a[ counter ];
52
53 cout << endl;
54
55 return 0; // indicates successful termination
56
57 } // end main
58
59 // multipurpose bubble sort; parameter compare is a pointer to
60 // the comparison function that determines sorting order
61 void bubble( int work[], const int size,
62 bool (*compare)( int, int ) )
63 {
64 // loop to control passes
65 for ( int pass = 1; pass < size; pass++ )
66
67 // loop to control number of comparisons per pass
68 for ( int count = 0; count < size - 1; count++ )
69
70 // if adjacent elements are out of order, swap them
71 if ( (*compare)( work[ count ], work[ count + 1 ] ) )
72 swap( &work[ count ], &work[ count + 1 ] );
compare is pointer to
function that receives two
integer parameters and returns
bool result.
Parentheses necessary to
indicate pointer to function
Call passed function
compare; dereference
pointer to execute function.
73
74 } // end function bubble
75
76 // swap values at memory locations to which
77 // element1Ptr and element2Ptr point
78 void swap( int * const element1Ptr, int * const element2Ptr )
79 {
80 int hold = *element1Ptr;
81 *element1Ptr = *element2Ptr;
82 *element2Ptr = hold;
83
84 } // end function swap
85
86 // determine whether elements are out of order
87 // for an ascending order sort
88 bool ascending( int a, int b )
89 {
90 return b < a; // swap if b is less than a
91
92 } // end function ascending
93
94 // determine whether elements are out of order
95 // for a descending order sort
96 bool descending( int a, int b )
97 {
98 return b > a; // swap if b is greater than a
99
100 } // end function descending
Enter 1 to sort in ascending order,
Enter 2 to sort in descending order: 1
Data items in original order
2 6 4 8 10 12 89 68 45 37
Data items in ascending order
2 4 6 8 10 12 37 45 68 89
Enter 1 to sort in ascending order,
Enter 2 to sort in descending order: 2
Data items in original order
2 6 4 8 10 12 89 68 45 37
Data items in descending order
89 68 45 37 12 10 8 6 4 2
Function Pointers
 Arrays of pointers to functions
 Menu-driven systems
 Pointers to each function stored in array of pointers to functions
 All functions must have same return type and same parameter types
 Menu choice  subscript into array of function pointers
1 // Example 98
2 // Demonstrating an array of pointers to functions.
3 #include <iostream>
4
5 using std::cout;
6 using std::cin;
7 using std::endl;
8
9 // function prototypes
10 void function1( int );
11 void function2( int );
12 void function3( int );
13
14 int main()
15 {
16 // initialize array of 3 pointers to functions that each
17 // take an int argument and return void
18 void (*f[ 3 ])( int ) = { function1, function2, function3 };
19
20 int choice;
21
22 cout << "Enter a number between 0 and 2, 3 to end: ";
23 cin >> choice;
24
Array initialized with names
of three functions; function
names are pointers.
25 // process user's choice
26 while ( choice >= 0 && choice < 3 ) {
27
28 // invoke function at location choice in array f
29 // and pass choice as an argument
30 (*f[ choice ])( choice );
31
32 cout << "Enter a number between 0 and 2, 3 to end: ";
33 cin >> choice;
34 }
35
36 cout << "Program execution completed." << endl;
37
38 return 0; // indicates successful termination
39
40 } // end main
41
42 void function1( int a )
43 {
44 cout << "You entered " << a
45 << " so function1 was callednn";
46
47 } // end function1
48
Call chosen function by
dereferencing corresponding
element in array.
49 void function2( int b )
50 {
51 cout << "You entered " << b
52 << " so function2 was callednn";
53
54 } // end function2
55
56 void function3( int c )
57 {
58 cout << "You entered " << c
59 << " so function3 was callednn";
60
61 } // end function3
Enter a number between 0 and 2, 3 to end: 0
You entered 0 so function1 was called
Enter a number between 0 and 2, 3 to end: 1
You entered 1 so function2 was called
Enter a number between 0 and 2, 3 to end: 2
You entered 2 so function3 was called
Enter a number between 0 and 2, 3 to end: 3
Program execution completed.
Accessing Structure Members
 Member access operators
 Dot operator (.) for structure and class members
 Arrow operator (->) for structure and class members via pointer to object
 Print member hour of timeObject:
cout << timeObject.hour;
OR
timePtr = &timeObject;
cout << timePtr->hour;
 timePtr->hour same as ( *timePtr ).hour
 Parentheses required
* lower precedence than .
Subtle Trap: Returning a Reference to a
private Data Member
 Reference to object
 &pRef = p;
 Alias for name of object
 Lvalue
 Can receive value in assignment statement
Changes original object
 Returning references
 public member functions can return non-const references to private data
members
 Client able to modify private data members
1 // Example 99
2 // Declaration of class Time.
3 // Member functions defined in time4.cpp
4
5 // prevent multiple inclusions of header file
6 #ifndef TIME4_H
7 #define TIME4_H
8
9 class Time {
10
11 public:
12 Time( int = 0, int = 0, int = 0 );
13 void setTime( int, int, int );
14 int getHour();
15
16 int &badSetHour( int ); // DANGEROUS reference return
17
18 private:
19 int hour;
20 int minute;
21 int second;
22
23 }; // end class Time
24
25 #endif
Function to demonstrate
effects of returning reference
to private data member.
25 // return hour value
26 int Time::getHour()
27 {
28 return hour;
29
30 } // end function getHour
31
32 // POOR PROGRAMMING PRACTICE:
33 // Returning a reference to a private data member.
34 int &Time::badSetHour( int hh )
35 {
36 hour = ( hh >= 0 && hh < 24 ) ? hh : 0;
37
38 return hour; // DANGEROUS reference return
39
40 } // end function badSetHour
Return reference to private
data member hour.
1 // Example 100
2 // Demonstrating a public member function that
3 // returns a reference to a private data member.
4 #include <iostream>
5
6 using std::cout;
7 using std::endl;
8
9 // include definition of class Time from time4.h
10 #include "time4.h"
11
12 int main()
13 {
14 Time t;
15
16 // store in hourRef the reference returned by badSetHour
17 int &hourRef = t.badSetHour( 20 );
18
19 cout << "Hour before modification: " << hourRef;
20
21 // use hourRef to set invalid value in Time object t
22 hourRef = 30;
23
24 cout << "nHour after modification: " << t.getHour();
25
badSetHour returns
reference to private data
member hour.
Reference allows setting of
private data member
hour.
26 // Dangerous: Function call that returns
27 // a reference can be used as an lvalue!
28 t.badSetHour( 12 ) = 74;
29
30 cout << "nn*********************************n"
31 << "POOR PROGRAMMING PRACTICE!!!!!!!!n"
32 << "badSetHour as an lvalue, Hour: "
33 << t.getHour()
34 << "n*********************************" << endl;
35
36 return 0;
37
38 } // end main
Hour before modification: 20
Hour after modification: 30
*********************************
POOR PROGRAMMING PRACTICE!!!!!!!!
badSetHour as an lvalue, Hour: 74
*********************************
Can use function call as
lvalue to set invalid value.
Returning reference allowed
invalid setting of private
data member hour.
Default Memberwise Assignment
 Assigning objects
 Assignment operator (=)
 Can assign one object to another of same type
 Default: memberwise assignment
Each right member assigned individually to left member
 Passing, returning objects
 Objects passed as function arguments
 Objects returned from functions
 Default: pass-by-value
 Copy of object passed, returned
Copy constructor
 Copy original values into new object
Dynamic Memory Management
with Operators
new and delete
 Dynamic memory management
 Control allocation and deallocation of memory
 Operators new and delete
 Include standard header <new>
 new
Time *timePtr;
timePtr = new Time;
 Creates object of proper size for type Time
 Error if no space in memory for object
 Calls default constructor for object
 Returns pointer of specified type
 Providing initializers
double *ptr = new double( 3.14159 );
Time *timePtr = new Time( 12, 0, 0 );
 Allocating arrays
int *gradesArray = new int[ 10 ];
Dynamic Memory Management with
Operators new and delete
 delete
 Destroy dynamically allocated object and free space
 Consider
delete timePtr;
 Operator delete
 Calls destructor for object
 Deallocates memory associated with object
Memory can be reused to allocate other objects
 Deallocating arrays
delete [] gradesArray;
Deallocates array to which gradesArray points
 If pointer to array of objects
 First calls destructor for each object in array
 Then deallocates memory
employee2.h (2 of 2)
employee2.cpp
(1 of 3)
1 // Example 102
2 // Member-function definitions for class Employee.
3 #include <iostream>
4
5 using std::cout;
6 using std::endl;
7
8 #include <new> // C++ standard new operator
9 #include <cstring> // strcpy and strlen prototypes
10
11 #include "employee2.h" // Employee class definition
12
13 // define and initialize static data member
14 int Employee::count = 0;
15
16 // define static member function that returns number of
17 // Employee objects instantiated
18 int Employee::getCount()
19 {
20 return count;
21
22 } // end static function getCount
Initialize static data
member exactly once at file
scope.
static member function
accesses static data
member count.
static Class Members
 static class variable
 “Class-wide” data
 Property of class, not specific object of class
 Efficient when single copy of data is enough
 Only the static variable has to be updated
 May seem like global variables, but have class scope
 Only accessible to objects of same class
 Initialized exactly once at file scope
 Exist even if no objects of class exist
 Can be public, private or protected
static Class Members
 Accessing static class variables
 Accessible through any object of class
 public static variables
 Can also be accessed using binary scope resolution operator(::)
Employee::count
 private static variables
 When no class member objects exist: Can only be accessed via public
static member function
Employee::getCount()
 static member functions
 Cannot access non-static data or functions
 No this pointer for static functions
 static data members and static member functions exist independent
of objects
1 // Example 101
2 // Employee class definition.
3 #ifndef EMPLOYEE2_H
4 #define EMPLOYEE2_H
5
6 class Employee {
7
8 public:
9 Employee( const char *, const char * ); // constructor
10 ~Employee(); // destructor
11 const char *getFirstName() const; // return first name
12 const char *getLastName() const; // return last name
13
14 // static member function
15 static int getCount(); // return # objects instantiated
16
17 private:
18 char *firstName;
19 char *lastName;
20
21 // static data member
22 static int count; // number of objects instantiated
23
24 }; // end class Employee
25
static member function
can only access static data
members and member
functions.
static data member is
class-wide data.
23
24 // constructor dynamically allocates space for
25 // first and last name and uses strcpy to copy
26 // first and last names into the object
27 Employee::Employee( const char *first, const char *last )
28 {
29 firstName = new char[ strlen( first ) + 1 ];
30 strcpy( firstName, first );
31
32 lastName = new char[ strlen( last ) + 1 ];
33 strcpy( lastName, last );
34
35 ++count; // increment static count of employees
36
37 cout << "Employee constructor for " << firstName
38 << ' ' << lastName << " called." << endl;
39
40 } // end Employee constructor
41
42 // destructor deallocates dynamically allocated memory
43 Employee::~Employee()
44 {
45 cout << "~Employee() called for " << firstName
46 << ' ' << lastName << endl;
47
new operator dynamically
allocates space.
Use static data member to
store total count of
employees.
48 delete [] firstName; // recapture memory
49 delete [] lastName; // recapture memory
50
51 --count; // decrement static count of employees
52
53 } // end destructor ~Employee
54
55 // return first name of employee
56 const char *Employee::getFirstName() const
57 {
58 // const before return type prevents client from modifying
59 // private data; client should copy returned string before
60 // destructor deletes storage to prevent undefined pointer
61 return firstName;
62
63 } // end function getFirstName
64
65 // return last name of employee
66 const char *Employee::getLastName() const
67 {
68 // const before return type prevents client from modifying
69 // private data; client should copy returned string before
70 // destructor deletes storage to prevent undefined pointer
71 return lastName;
72
73 } // end function getLastName
Operator delete deallocates
memory.
Use static data member to
store total count of
employees.
Operator Functions As Class Members
Vs. As Friend Functions
 Operator functions
 Member functions
 Use this keyword to implicitly get argument
 Gets left operand for binary operators (like +)
 Leftmost object must be of same class as operator
 Non member functions
 Need parameters for both operands
 Can have object of different class than operator
 Must be a friend to access private or protected data
 Example Overloaded << operator
 Left operand of type ostream &
 Such as cout object in cout << classObject
 Similarly, overloaded >> needs istream &
 Thus, both must be non-member functions
Operator Functions As Class Members
Vs. As Friend Functions
 Commutative operators
 May want + to be commutative
 So both “a + b” and “b + a” work
 Suppose we have two different classes
 Overloaded operator can only be member function when its class is on left
 HugeIntClass + Long int
 Can be member function
 When other way, need a non-member overload function
 Long int + HugeIntClass
Overloading Stream-Insertion and
Stream-Extraction Operators
 << and >>
 Already overloaded to process each built-in type
 Can also process a user-defined class
 Example program
 Class PhoneNumber
 Holds a telephone number
 Print out formatted number automatically
 (123) 456-7890
1 // Example 103
2 // Overloading the stream-insertion and
3 // stream-extraction operators.
4 #include <iostream>
5
6 using std::cout;
7 using std::cin;
8 using std::endl;
9 using std::ostream;
10 using std::istream;
11
12 #include <iomanip>
13
14 using std::setw;
15
16 // PhoneNumber class definition
17 class PhoneNumber {
18 friend ostream &operator<<( ostream&, const PhoneNumber & );
19 friend istream &operator>>( istream&, PhoneNumber & );
20
21 private:
22 char areaCode[ 4 ]; // 3-digit area code and null
23 char exchange[ 4 ]; // 3-digit exchange and null
24 char line[ 5 ]; // 4-digit line and null
25
26 }; // end class PhoneNumber
Notice function prototypes for
overloaded operators >> and <<
They must be non-member friend
functions, since the object of class
Phonenumber appears on the right of
the operator.
cin << object
cout >> object
27
28 // overloaded stream-insertion operator; cannot be
29 // a member function if we would like to invoke it with
30 // cout << somePhoneNumber;
31 ostream &operator<<( ostream &output, const PhoneNumber &num )
32 {
33 output << "(" << num.areaCode << ") "
34 << num.exchange << "-" << num.line;
35
36 return output; // enables cout << a << b << c;
37
38 } // end function operator<<
39
40 // overloaded stream-extraction operator; cannot be
41 // a member function if we would like to invoke it with
42 // cin >> somePhoneNumber;
43 istream &operator>>( istream &input, PhoneNumber &num )
44 {
45 input.ignore(); // skip (
46 input >> setw( 4 ) >> num.areaCode; // input area code
47 input.ignore( 2 ); // skip ) and space
48 input >> setw( 4 ) >> num.exchange; // input exchange
49 input.ignore(); // skip dash (-)
50 input >> setw( 5 ) >> num.line; // input line
51
52 return input; // enables cin >> a >> b >> c;
The expression:
cout << phone;
is interpreted as the function call:
operator<<(cout, phone);
output is an alias for cout.
This allows objects to be cascaded.
cout << phone1 << phone2;
first calls
operator<<(cout, phone1), and
returns cout.
Next, cout << phone2 executes.
Stream manipulator setw
restricts number of characters
read. setw(4) allows 3
characters to be read, leaving
room for the null character.
53
54 } // end function operator>>
55
56 int main()
57 {
58 PhoneNumber phone; // create object phone
59
60 cout << "Enter phone number in the form (123) 456-7890:n";
61
62 // cin >> phone invokes operator>> by implicitly issuing
63 // the non-member function call operator>>( cin, phone )
64 cin >> phone;
65
66 cout << "The phone number entered was: " ;
67
68 // cout << phone invokes operator<< by implicitly issuing
69 // the non-member function call operator<<( cout, phone )
70 cout << phone << endl;
71
72 return 0;
73
74 } // end main
Enter phone number in the form (123) 456-7890:
(800) 555-1212
The phone number entered was: (800) 555-1212

More Related Content

PPT
Basics of c++ Programming Language
PPTX
C++ Overview PPT
PPTX
PPTX
Loops c++
PPSX
Complete C programming Language Course
PDF
Parallelism
PDF
Cadence manual
Basics of c++ Programming Language
C++ Overview PPT
Loops c++
Complete C programming Language Course
Parallelism
Cadence manual

What's hot (20)

PPTX
If else statement in c++
PPTX
Type casting in c programming
PPT
Strings
PPTX
CONDITIONAL STATEMENT IN C LANGUAGE
PPTX
Introduction to c++
PPT
Expression evaluation
PPT
Basics of c++
PPTX
Variables in python
PPSX
C++ Programming Language
PPT
Basic concept of OOP's
PPSX
Data types, Variables, Expressions & Arithmetic Operators in java
PPTX
Programming Fundamentals lecture 1
PPT
Introduction to C++
PPTX
Introduction to programming
PPS
Wrapper class
PPTX
Constants, Variables, and Data Types
PPT
OOP in C++
PPTX
Polymorphism in C++
PPTX
Scope rules : local and global variables
PPTX
Our presentation on algorithm design
If else statement in c++
Type casting in c programming
Strings
CONDITIONAL STATEMENT IN C LANGUAGE
Introduction to c++
Expression evaluation
Basics of c++
Variables in python
C++ Programming Language
Basic concept of OOP's
Data types, Variables, Expressions & Arithmetic Operators in java
Programming Fundamentals lecture 1
Introduction to C++
Introduction to programming
Wrapper class
Constants, Variables, and Data Types
OOP in C++
Polymorphism in C++
Scope rules : local and global variables
Our presentation on algorithm design
Ad

Viewers also liked (6)

PPTX
C++ language
PPT
Introduction to Procedural Programming in C++
PPTX
presentation on C++ basics by prince kumar kushwaha
PDF
20130110 prs presentation ncim c++ 11
PDF
Intro to C++ - language
PPT
Intro. to prog. c++
C++ language
Introduction to Procedural Programming in C++
presentation on C++ basics by prince kumar kushwaha
20130110 prs presentation ncim c++ 11
Intro to C++ - language
Intro. to prog. c++
Ad

Similar to Complete C++ programming Language Course (20)

PPT
Oop lec 1
PPT
C Introduction
PPTX
C++ lecture 01
PPTX
C++ programming language basic to advance level
PPT
C_chap02.ppt Introduction to C Programming Language
PPT
C Intro.ppt
PPSX
Esoft Metro Campus - Programming with C++
PPT
Lecture 1
PPT
Lecture 1
PPT
intro to c
PPTX
C Language (All Concept)
PPTX
c & c++ logic building concepts practice.pptx
PPTX
KMK1093 CHAPTER 2.kkkpptx KMK1093 CHAPTER 2.kkkpptx
PPTX
Programming in C
DOC
C notes for exam preparation
PPT
intro to programming languge c++ for computer department
PPTX
Introduction%20C.pptx
PPTX
made it easy: python quick reference for beginners
PPTX
#Code2 create c++ for beginners
PDF
4. programing 101
Oop lec 1
C Introduction
C++ lecture 01
C++ programming language basic to advance level
C_chap02.ppt Introduction to C Programming Language
C Intro.ppt
Esoft Metro Campus - Programming with C++
Lecture 1
Lecture 1
intro to c
C Language (All Concept)
c & c++ logic building concepts practice.pptx
KMK1093 CHAPTER 2.kkkpptx KMK1093 CHAPTER 2.kkkpptx
Programming in C
C notes for exam preparation
intro to programming languge c++ for computer department
Introduction%20C.pptx
made it easy: python quick reference for beginners
#Code2 create c++ for beginners
4. programing 101

More from Vivek Singh Chandel (20)

PDF
Deceptive Marketing.pdf
PDF
brain controled wheel chair.pdf
PDF
Mechanism of fullerene synthesis in the ARC REACTOR (Vivek Chan 2013)
PDF
Manav dharma shashtra tatha shashan paddati munshiram jigyasu
PDF
Self driving and connected cars fooling sensors and tracking drivers
PDF
EEG Acquisition Device to Control Wheelchair Using Thoughts
PDF
Full Shri Ramcharitmanas in Hindi Complete With Meaning (Ramayana)
PPSX
Net framework session01
PPSX
Net framework session03
PPSX
Net framework session02
PPSX
04 intel v_tune_session_05
PPSX
03 intel v_tune_session_04
PPSX
02 intel v_tune_session_02
PPSX
01 intel v_tune_session_01
PPSX
09 intel v_tune_session_13
PPSX
07 intel v_tune_session_10
PPSX
02 asp.net session02
PPSX
01 asp.net session01
PPSX
16 asp.net session23
PPSX
15 asp.net session22
Deceptive Marketing.pdf
brain controled wheel chair.pdf
Mechanism of fullerene synthesis in the ARC REACTOR (Vivek Chan 2013)
Manav dharma shashtra tatha shashan paddati munshiram jigyasu
Self driving and connected cars fooling sensors and tracking drivers
EEG Acquisition Device to Control Wheelchair Using Thoughts
Full Shri Ramcharitmanas in Hindi Complete With Meaning (Ramayana)
Net framework session01
Net framework session03
Net framework session02
04 intel v_tune_session_05
03 intel v_tune_session_04
02 intel v_tune_session_02
01 intel v_tune_session_01
09 intel v_tune_session_13
07 intel v_tune_session_10
02 asp.net session02
01 asp.net session01
16 asp.net session23
15 asp.net session22

Recently uploaded (20)

PDF
2.FourierTransform-ShortQuestionswithAnswers.pdf
PDF
VCE English Exam - Section C Student Revision Booklet
PPTX
PPH.pptx obstetrics and gynecology in nursing
PDF
Mark Klimek Lecture Notes_240423 revision books _173037.pdf
PPTX
Renaissance Architecture: A Journey from Faith to Humanism
PDF
Chapter 2 Heredity, Prenatal Development, and Birth.pdf
PPTX
master seminar digital applications in india
PPTX
Institutional Correction lecture only . . .
PDF
The Lost Whites of Pakistan by Jahanzaib Mughal.pdf
PPTX
Introduction to Child Health Nursing – Unit I | Child Health Nursing I | B.Sc...
PPTX
Final Presentation General Medicine 03-08-2024.pptx
PDF
FourierSeries-QuestionsWithAnswers(Part-A).pdf
PDF
Complications of Minimal Access Surgery at WLH
PPTX
The Healthy Child – Unit II | Child Health Nursing I | B.Sc Nursing 5th Semester
PPTX
PPT- ENG7_QUARTER1_LESSON1_WEEK1. IMAGERY -DESCRIPTIONS pptx.pptx
PDF
Supply Chain Operations Speaking Notes -ICLT Program
PDF
Insiders guide to clinical Medicine.pdf
PDF
Physiotherapy_for_Respiratory_and_Cardiac_Problems WEBBER.pdf
PDF
Abdominal Access Techniques with Prof. Dr. R K Mishra
PDF
STATICS OF THE RIGID BODIES Hibbelers.pdf
2.FourierTransform-ShortQuestionswithAnswers.pdf
VCE English Exam - Section C Student Revision Booklet
PPH.pptx obstetrics and gynecology in nursing
Mark Klimek Lecture Notes_240423 revision books _173037.pdf
Renaissance Architecture: A Journey from Faith to Humanism
Chapter 2 Heredity, Prenatal Development, and Birth.pdf
master seminar digital applications in india
Institutional Correction lecture only . . .
The Lost Whites of Pakistan by Jahanzaib Mughal.pdf
Introduction to Child Health Nursing – Unit I | Child Health Nursing I | B.Sc...
Final Presentation General Medicine 03-08-2024.pptx
FourierSeries-QuestionsWithAnswers(Part-A).pdf
Complications of Minimal Access Surgery at WLH
The Healthy Child – Unit II | Child Health Nursing I | B.Sc Nursing 5th Semester
PPT- ENG7_QUARTER1_LESSON1_WEEK1. IMAGERY -DESCRIPTIONS pptx.pptx
Supply Chain Operations Speaking Notes -ICLT Program
Insiders guide to clinical Medicine.pdf
Physiotherapy_for_Respiratory_and_Cardiac_Problems WEBBER.pdf
Abdominal Access Techniques with Prof. Dr. R K Mishra
STATICS OF THE RIGID BODIES Hibbelers.pdf

Complete C++ programming Language Course

  • 2. Topics for C++ Language 1.Introduction to C++ language 2.Structured/OO Programming 3.Memory Concepts 4.Arithmetic 5.Control Structure 6.Functions 7.Arrays 8.Pointers 9.Structures 10.Inheritance 11.Polymorphism 12.Multiple Inheritance 13.Templetes 14.Stacks/Queue 15.Exception Handling 16.Preprocessing 17.Unified Modeling Language
  • 3. Introduction to C++ language Course Description  An introduction to the development of programs using C++.  Emphasis is given to the development of program modules that can function independently.  Object-oriented design  The theory of data structures and programming language design is continued. Course Information
  • 4. Computer Languages  Machine language  Generally consist of strings of numbers - Ultimately 0s and 1s - Machine-dependent  Example: +1300042774 +1400593419  Assembly language  English-like abbreviations for elementary operations  Incomprehensible to computers - Convert to machine language  Example: LOAD BASEPAY ADD OVERPAY STORE GROSSPAY  High-level languages  Similar to everyday English, use common mathematical notations  Compiler/Interpreter  Example: grossPay = basePay + overTimePay
  • 5. History of C and C++  History of C  Evolved from two other programming languages  BCPL and B: “Typeless” languages  Dennis Ritchie (Bell Lab): Added typing, other features  1989: ANSI standard/ ANSI/ISO 9899: 1990  History of C++  Early 1980s: Bjarne Stroustrup (Bell Lab)  Provides capabilities for object-oriented programming  Objects: reusable software components  Object-oriented programs  Building block approach” to creating programs  C++ programs are built from pieces called classes and functions  C++ standard library: Rich collections of existing classes and functions
  • 6. Structured/OO Programming  Structured programming (1960s)  Disciplined approach to writing programs  Clear, easy to test and debug, and easy to modify  E.g.Pascal:1971: Niklaus Wirth  OOP  “Software reuse”  “Modularity”  “Extensible”  More understandable, better organized and easier to maintain than procedural programming
  • 7. Basics of a Typical C++ Environment  C++ systems  Program-development environment  Language  C++ Standard Library  C++ program names extensions  .cpp  .cxx  .cc  .C
  • 8. Basics of a Typical C++ Environment Phases of C++ Programs: 1. Edit 2. Preprocess 3. Compile 4. Link 5. Load 6. Execute Loader Primary Memory Program is created in the editor and stored on disk. Preprocessor program processes the code. Loader puts program in memory. CPU takes each instruction and executes it, possibly storing new data values as the program executes. Compiler Compiler creates object code and stores it on disk. Linker links the object code with the libraries, creates an executable file and stores it on disk Editor Preprocessor Linker CPU Primary Memory . . . . . . . . . . . . Disk Disk Disk Disk Disk
  • 9. Basics of a Typical C++ Environment  Common Input/output functions  cin  Standard input stream  Normally keyboard  cout  Standard output stream  Normally computer screen  cerr  Standard error stream  Display error messages  Comments: C’s comment /* .. */ OR Begin with // or  Preprocessor directives: Begin with #  Processed before compiling
  • 10. A Simple Program: Printing a Line of Text  Standard output stream object  std::cout  “Connected” to screen  <<  Stream insertion operator  Value to right (right operand) inserted into output stream  Namespace  std:: specifies that entity belongs to “namespace” std  std:: removed through use of using statements  Escape characters:  Indicates “special” character output
  • 11. 1 // Example 1 2 // A first program in C++. 3 #include <iostream> 4 5 // function main begins program execution 6 int main() 7 { 8 std::cout << "Welcome to C++!n"; 9 10 return 0; // indicate that program ended successfully 11 12 } // end function main Welcome to C++!
  • 12. A Simple Program: Printing a Line of Text Escape Sequence Description n Newline. Position the screen cursor to the beginning of the next line. t Horizontal tab. Move the screen cursor to the next tab stop. r Carriage return. Position the screen cursor to the beginning of the current line; do not advance to the next line. a Alert. Sound the system bell. Backslash. Used to print a backslash character. " Double quote. Used to print a double quote character.
  • 13. Memory Concepts  Variable names  Correspond to actual locations in computer's memory  Every variable has name, type, size and value  When new value placed into variable, overwrites previous value  std::cin >> integer1;  Assume user entered 45  std::cin >> integer2;  Assume user entered 72  sum = integer1 + integer2; integer1 45 integer1 45 integer2 72 integer1 45 integer2 72 sum 117
  • 14. Arithmetic  Arithmetic calculations  * : Multiplication  / : Division  Integer division truncates remainder 7 / 5 evaluates to 1  % : Modulus operator returns remainder 7 % 5 evaluates to 2 Operator(s) Operation(s) Order of evaluation (precedence) () Parentheses Evaluated first. If the parentheses are nested, the expression in the innermost pair is evaluated first. If there are several pairs of parentheses “on the same level” (i.e., not nested), they are evaluated left to right. *, /, or % Multiplication Division Modulus Evaluated second. If there are several, they re evaluated left to right. + or - Addition Subtraction Evaluated last. If there are several, they are evaluated left to right.
  • 15. Decision Making: Equality and Relational Operators  if structure  Make decision based on truth or falsity of condition  If condition met, body executed  Else, body not executed  Equality and relational operators  Equality operators  Same level of precedence  Relational operators  Same level of precedence  Associate left to right
  • 16. Decision Making: Equality and Relational Operators Standard algebraic equality operator or relational operator C++ equality or relational operator Example of C++ condition Meaning of C++ condition Relational operators > > x > y x is greater than y < < x < y x is less than y  >= x >= y x is greater than or equal to y  <= x <= y x is less than or equal to y Equality operators = == x == y x is equal to y  != x != y x is not equal to y
  • 17. Algorithms /pseudocode  Computing problems  Solved by executing a series of actions in a specific order  Algorithm: a procedure determining  Actions to be executed  Order to be executed  Example: recipe  Program control  Specifies the order in which statements are executed  Pseudocode  Artificial, informal language used to develop algorithms  Similar to everyday English
  • 18. Control Structures  Sequential execution  Statements executed in order  Transfer of control  Next statement executed not next one in sequence  Structured programming – “goto”-less programming  3 control structures to build any program  Sequence structure  Programs executed sequentially by default  Selection structures  if, if/else, switch  Repetition structures  while, do/while, for
  • 19. Keywords  C++ keywords  Cannot be used as identifiers or variable names C++ Keywords Keywords common to the C and C++ programming languages auto break case char const continue default do double else enum extern float for goto if int long register return short signed sizeof static struct switch typedef union unsigned void volatile while C++ only keywords asm bool catch class const_cast delete dynamic_cast explicit false friend inline mutable namespace new operator private protected public reinterpret_cast static_cast template this throw true try typeid typename using virtual wchar_t
  • 20. Control Structures  Flowchart  Graphical representation of an algorithm  Special-purpose symbols connected by arrows (flowlines)  Rectangle symbol (action symbol)  Any type of action  Oval symbol  Beginning or end of a program, or a section of code (circles) Exercise: Find greater of three numbers
  • 21. if/else Selection Structure  Ternary conditional operator (?:)  Three arguments (condition, value if true, value if false)  Code could be written: cout << ( grade >= 60 ? “Passed” : “Failed” ); truefalse print “Failed” print “Passed” grade >= 60 Condition Value if true Value if false
  • 22. while Repetition Structure  Repetition structure  Counter-controlled  While/do while loop: repeated until condition becomes false  For: loop repeated until counter reaches certain value Flowchart representation?  Sentinel value  Indicates “end of data entry”  Sentinel chosen so it cannot be confused with regular input  Example int product = 2; while ( product <= 1000 ) { product = 2 * product; cout << product; } Flowchart representation? What is the output?
  • 23. switch Multiple-Selection Structure  switch  Test variable for multiple values  Series of case labels and optional default case switch ( variable ) { case value1: // taken if variable == value1 statements break; // necessary to exit switch case value2: case value3: // taken if variable == value2 or == value3 statements break; default: // taken if none matches statements break; }
  • 24. break and continue Statements  break statement  Immediate exit from while, for, do/while, switch  Program continues with first statement after structure  Common uses  Escape early from a loop  Skip the remainder of switch
  • 25. Logical Operators  Used as conditions in loops, if statements  && (logical AND)  true if both conditions are true if ( gender == 1 && age >= 65 ) ++seniorFemales;  || (logical OR)  true if either of condition is true if ( semesterAverage >= 90 || finalExam >= 90 ) cout << "Student grade is A" << endl;
  • 26. Logical Operators  ! (logical NOT, logical negation)  Returns true when its condition is false, & vice versa if ( !( grade == sentinelValue ) ) cout << "The next grade is " << grade << endl; Alternative: if ( grade != sentinelValue ) cout << "The next grade is " << grade << endl;
  • 27. Confusing Equality (==) and Assignment (=) Operators  Common error  Does not typically cause syntax errors  Aspects of problem  Expressions that have a value can be used for decision  Zero = false, nonzero = true  Assignment statements produce a value (the value to be assigned) if == was replaced with = if ( payCode = 4 ) cout << "You get a bonus!" << endl; What happens?
  • 28. Confusing Equality (==) and Assignment (=) Operators  Lvalues  Expressions that can appear on left side of equation  Can be changed x = 4;  Rvalues  Only appear on right side of equation  Constants, such as numbers (i.e. cannot write 4 = x;)  Lvalues can be used as rvalues, but not vice versa
  • 29. Structured-Programming Summary  Structured programming  Programs easier to understand, test, debug and modify  Rules for structured programming  Only use single-entry/single-exit control structures  Rules 1) Begin with the “simplest flowchart” 2) Any rectangle (action) can be replaced by two rectangles (actions) in sequence 3) Any rectangle (action) can be replaced by any control structure (sequence, if, if/else, switch, while, do/while or for) 4) Rules 2 and 3 can be applied in any order and multiple times
  • 30. Structured-Programming Summary Representation of Rule 3 (replacing any rectangle with a control structure) Rule 3 Rule 3Rule 3
  • 31. Program Components in C++  Modules: functions and classes  Programs use new and “prepackaged” modules  New: programmer-defined functions, classes  Prepackaged: from the standard library  Functions invoked by function call  Function name and information (arguments) it needs  Function definitions  Only written once  Hidden from other functions
  • 32. Functions  Functions  Modularize a program  Software reusability  Call function multiple times  Local variables  Known only in the function in which they are defined  All variables declared in function definitions are local variables  Parameters  Local variables passed to function when called  Provide outside information
  • 33. Math Library Functions Perform common mathematical calculations Include the header file <cmath> Functions called by writing functionName (argument); or functionName (argument1, argument2, …); Example cout << sqrt( 900.0 ); All functions in math library return a double Function arguments can be Constants: sqrt( 4 ); Variables: sqrt( x ); Expressions:  sqrt( sqrt( x ) ) ;  sqrt( 3 - 6x ); Other functions  ceil(x), floor(x), log10(x), etc.
  • 34. Function Definitions Function prototype int square( int ); Calling/invoking a function square(x); Format for function definition return-value-type function-name( parameter-list ) { declarations and statements } Prototype must match function definition Function prototype double maximum( double, double, double ); Definition double maximum( double x, double y, double z ) { … }
  • 35. Function Definitions  Example function int square( int y ) { return y * y; }  return keyword  Returns data, and control goes to function’s caller  If no data to return, use return;  Function ends when reaches right brace  Control goes to caller  Functions cannot be defined inside other functions
  • 36. Function Prototypes  Function signature  Part of prototype with name and parameters  double maximum( double, double, double );  Argument Coercion  Force arguments to be of proper type  Converting int (4) to double (4.0) cout << sqrt(4)  Conversion rules  Arguments usually converted automatically  Changing from double to int can truncate data 3.4 to 3  Mixed type goes to highest type (promotion) Function signature
  • 37. Function Prototypes Data types long double double float unsigned long int (synonymous with unsigned long) long int (synonymous with long) unsigned int (synonymous with unsigned) int unsigned short int (synonymous with unsigned short) short int (synonymous with short) unsigned char char bool (false becomes 0, true becomes 1) Fig. 3.5 Promotion hierarc hy for built-in data types.
  • 38. Header Files  Header files contain  Function prototypes  Definitions of data types and constants  Header files ending with .h  Programmer-defined header files #include “myheader.h”  Library header files #include <cmath>
  • 39. Enumeration: enum  Enumeration  Set of integers with identifiers enum typeName {constant1, constant2…};  Constants start at 0 (default), incremented by 1  Constants need unique names  Cannot assign integer to enumeration variable  Must use a previously defined enumeration type  Example enum Status {CONTINUE, WON, LOST}; Status enumVar; enumVar = WON; // cannot do enumVar = 1
  • 40. Storage Classes  Variables have attributes  Have seen name, type, size, value  Storage class  How long variable exists in memory  Scope  Where variable can be referenced in program  Linkage  For multiple-file program which files can use it
  • 41. Storage Classes  Automatic storage class  Variable created when program enters its block  Variable destroyed when program leaves block  Only local variables of functions can be automatic  Automatic by default  keyword auto explicitly declares automatic  register keyword  Hint to place variable in high-speed register  Good for often-used items (loop counters)  Often unnecessary, compiler optimizes  Specify either register or auto, not both  register int counter = 1;
  • 42. Storage Classes  Static storage class  Variables exist for entire program  For functions, name exists for entire program  May not be accessible, scope rules still apply  auto and register keyword  local variables in function  register variables are kept in CPU registers  static keyword  Local variables in function  Keeps value between function calls  Only known in own function  extern keyword  Default for global variables/functions  Globals: defined outside of a function block  Known in any function that comes after it
  • 43. Scope Rules  Scope  Portion of program where identifier can be used  File scope  Defined outside a function, known in all functions  Global variables, function definitions and prototypes  Function scope  Can only be referenced inside defining function  Only labels, e.g., identifiers with a colon (case:)
  • 44. Scope Rules  Block scope  Begins at declaration, ends at right brace }  Can only be referenced in this range  Local variables, function parameters  Local static variables still have block scope  Storage class separate from scope  Function-prototype scope  Parameter list of prototype  Names in prototype optional  Compiler ignores  In a single prototype, name can be used once
  • 45. 1 // Example 2 2 // A scoping example. 3 #include <iostream> 4 5 using std::cout; 6 using std::endl; 7 8 void useLocal( void ); // function prototype 9 void useStaticLocal( void ); // function prototype 10 void useGlobal( void ); // function prototype 11 12 int x = 1; // global variable 13 14 int main() 15 { 16 int x = 5; // local variable to main 17 18 cout << "local x in main's outer scope is " << x << endl; 19 20 { // start new scope 21 22 int x = 7; 23 24 cout << "local x in main's inner scope is " << x << endl; 25 26 } // end new scope Local/global? Scope? Local/global? Scope? Local/global? Scope?
  • 46. 43 // useLocal reinitializes local variable x during each call 44 void useLocal( void ) 45 { 46 int x = 25; // initialized each time useLocal is called 47 48 cout << endl << "local x is " << x 49 << " on entering useLocal" << endl; 50 ++x; 51 cout << "local x is " << x 52 << " on exiting useLocal" << endl; 53 54 } // end function useLocal 55 Local/global? Scope?
  • 47. 56 // useStaticLocal initializes static local variable x only the 57 // first time the function is called; value of x is saved 58 // between calls to this function 59 void useStaticLocal( void ) 60 { 61 // initialized only first time useStaticLocal is called 62 static int x = 50; 63 64 cout << endl << "local static x is " << x 65 << " on entering useStaticLocal" << endl; 66 ++x; 67 cout << "local static x is " << x 68 << " on exiting useStaticLocal" << endl; 69 70 } // end function useStaticLocal 71 Local/global? Scope?
  • 48. Recursion  Recursive functions  Functions that call themselves  Can only solve a base case  If not base case  Break problem into smaller problem(s)  Launch new copy of function to work on the smaller problem (recursive call/recursive step)  Slowly converges towards base case  Function makes call to itself inside the return statement  Eventually base case gets solved  Answer works way back up, solves entire problem
  • 49. Recursion  Example: factorial n! = n * ( n – 1 ) * ( n – 2 ) * … * 1  Recursive relationship ( n! = n * ( n – 1 )! ) 5! = 5 * 4! 4! = 4 * 3!…  Base case (1! = 0! = 1)
  • 50. Example Using Recursion: Fibonacci Series  Fibonacci series: 0, 1, 1, 2, 3, 5, 8...  Each number sum of two previous ones  Example of a recursive formula:  fib(n) = fib(n-1) + fib(n-2)  C++ code for Fibonacci function long fibonacci( long n ) { if ???? // base case return ???; else ??? }
  • 51. Example Using Recursion: Fibonacci Series  Order of operations  return fibonacci( n - 1 ) + fibonacci( n - 2 );  Recursive function calls  Each level of recursion doubles the number of function calls  30th number = 2^30 ~ 4 billion function calls  Exponential complexity f( 3 ) f( 1 )f( 2 ) f( 1 ) f( 0 ) return 1 return 1 return 0 return + +return
  • 52. Recursion vs. Iteration  Repetition  Iteration: explicit loop  Recursion: repeated function calls  Termination  Iteration: loop condition fails  Recursion: base case recognized  Both can have infinite loops  Balance between performance (iteration) and good software engineering (recursion)
  • 53. Inline Functions  Inline functions  Keyword inline before function  Asks the compiler to copy code into program instead of making function call  Reduce function-call overhead  Compiler can ignore inline  Good for small, often-used functions  Example inline double cube( const double s ) { return s * s * s; }  const tells compiler that function does not modify s
  • 54. References and Reference Parameters  Call by value  Copy of data passed to function  Changes to copy do not change original  Prevent unwanted side effects  Call by reference  Function can directly access data  Changes affect original  Reference parameter  Alias for argument in function call  Passes parameter by reference  Use & after data type in prototype  void myFunction( int &data )  Read “data is a reference to an int”  Function call format the same  However, original can now be changed
  • 55. References and Reference Parameters  Pointers  Another way to pass-by-refernce  References as aliases to other variables  Refer to same variable  Can be used within a function int count = 1; // declare integer variable count int &cRef = count; // create cRef as an alias for count ++cRef; // increment count (using its alias)  References must be initialized when declared  Otherwise, compiler error  Dangling reference  Reference to undefined variable
  • 56. Default Arguments  Function call with omitted parameters  If not enough parameters, rightmost go to their defaults  Default values  Can be constants, global variables, or function calls  Set defaults in function prototype int myFunction( int x = 1, int y = 2, int z = 3 );  myFunction(3)  x = 3, y and z get defaults (rightmost)  myFunction(3, 5)  x = 3, y = 5 and z gets default
  • 57. Unitary Scope Resolution Operator  Unary scope resolution operator (::)  Access global variable if local variable has same name  Not needed if names are different  Use ::variable  y = ::x + 3;  Good to avoid using same names for locals and globals
  • 58. Function Overloading  Function overloading  Functions with same name and different parameters  Should perform similar tasks  i.e., function to square ints and function to square floats int square( int x) {return x * x;} float square(float x) { return x * x; }  Overloaded functions distinguished by signature  Based on name and parameter types (order matters)  Name mangling  Encode function identifier with no. and types of parameters  Type-safe linkage  Ensures proper overloaded function called
  • 59. Function Templates  Compact way to make overloaded functions  Generate separate function for different data types  Format  Begin with keyword template  Formal type parameters in brackets <>  Every type parameter preceded by typename or class (synonyms)  Placeholders for built-in types (i.e., int) or user-defined types  Specify arguments types, return types, declare variables  Function definition like normal, except formal types used
  • 60. Function Templates  Example template < class T > // or template< typename T > T square( T value1 ) { return value1 * value1; }  T is a formal type, used as parameter type  Above function returns variable of same type as parameter  In function call, T replaced by real type  If int, all T's become ints int x; int y = square(x);
  • 61. 1 // Example 3 2 // Using a function template. 3 #include <iostream> 4 5 using std::cout; 6 using std::cin; 7 using std::endl; 8 9 // definition of function template maximum 10 template < class T > // or template < typename T > 11 T maximum( T value1, T value2, T value3 ) 12 { 13 T max = value1; 14 15 if ( value2 > max ) 16 max = value2; 17 18 if ( value3 > max ) 19 max = value3; 20 21 return max; 22 23 } // end function template maximum 24 Formal type parameter T placeholder for type of data to be tested by maximum. maximum expects all parameters to be of the same type.
  • 62. 25 int main() 26 { 27 // demonstrate maximum with int values 28 int int1, int2, int3; 29 30 cout << "Input three integer values: "; 31 cin >> int1 >> int2 >> int3; 32 33 // invoke int version of maximum 34 cout << "The maximum integer value is: " 35 << maximum( int1, int2, int3 ); 36 37 // demonstrate maximum with double values 38 double double1, double2, double3; 39 40 cout << "nnInput three double values: "; 41 cin >> double1 >> double2 >> double3; 42 43 // invoke double version of maximum 44 cout << "The maximum double value is: " 45 << maximum( double1, double2, double3 ); 46 maximum called with various data types.
  • 63. 47 // demonstrate maximum with char values 48 char char1, char2, char3; 49 50 cout << "nnInput three characters: "; 51 cin >> char1 >> char2 >> char3; 52 53 // invoke char version of maximum 54 cout << "The maximum character value is: " 55 << maximum( char1, char2, char3 ) 56 << endl; 57 58 return 0; // indicates successful termination 59 60 } // end main Input three integer values: 1 2 3 The maximum integer value is: 3 Input three double values: 3.3 2.2 1.1 The maximum double value is: 3.3 Input three characters: A C B The maximum character value is: C
  • 64. Arrays  Array  Consecutive group of memory locations  Same name and type (int, char, etc.)  To refer to an element  Specify array name and position number (index)  Format: arrayname[ position number ]  First element at position 0  N-element array c c[ 0 ], c[ 1 ] … c[ n - 1 ]  Nth element as position N-1
  • 65. Declaring Arrays  When declaring arrays, specify  Name  Type of array  Any data type  Number of elements  type arrayName[ arraySize ]; int c[ 10 ]; // array of 10 integers float d[ 3284 ]; // array of 3284 floats  Declaring multiple arrays of same type  Use comma separated list, like regular variables int b[ 100 ], x[ 27 ];
  • 66. Examples Using Arrays  Initializing arrays  For loop  Set each element  Initializer list  Specify each element when array declared int n[ 5 ] = { 1, 2, 3, 4, 5 };  If not enough initializers, rightmost elements 0  If too many, syntax error  To set every element to 0 int n[ 5 ] = { 0 };  If array size omitted, initializers determine size int n[] = { 1, 2, 3, 4, 5 };  5 initializers, therefore 5 element array  static int array[3]; ??
  • 67. Examples Using Arrays  Strings  Arrays of characters  All strings end with null ('0')  Examples  char string1[] = "hello"; Null character implicitly added string1 has 6 elements  char string1[] = { 'h', 'e', 'l', 'l', 'o', '0’ };  Subscripting is the same String1[ 0 ] is 'h' string1[ 2 ] is 'l'
  • 68. Examples Using Arrays  Input from keyboard char string2[ 10 ]; cin >> string2;  Puts user input in string  Stops at first whitespace character  Adds null character  If too much text entered, data written beyond array  We want to avoid this  Printing strings  cout << string2 << endl;  Does not work for other array types  Characters printed until null found
  • 69. Passing Arrays to Functions  Specify name without brackets  To pass array myArray to myFunction int myArray[ 24 ]; myFunction( myArray, 24 );  Array size usually passed, but not required  Useful to iterate over all elements  Arrays passed-by-reference  Functions can modify original array data  Value of name of array is address of first element  Function knows where the array is stored  Can change original memory locations
  • 70. Passing Arrays to Functions  Functions taking arrays  Function prototype  void modifyArray( int b[], int arraySize );  void modifyArray( int [], int ); Names optional in prototype  Both take an integer array and a single integer  No need for array size between brackets  Ignored by compiler  If declare array parameter as const  Cannot be modified (compiler error)  void doNotModify( const int [] );
  • 71. Sorting Arrays  Example:  Go left to right, and exchange elements as necessary  One pass for each element  Original: 3 4 2 7 6  Pass 1: 3 2 4 6 7 (elements exchanged)  Pass 2: 2 3 4 6 7  Pass 3: 2 3 4 6 7 (no changes needed)  Pass 4: 2 3 4 6 7  Pass 5: 2 3 4 6 7  Small elements "bubble" to the top (like 2 in this example)
  • 72. Multiple-Subscripted Arrays Multiple subscripts a[ i ][ j ] Tables with rows and columns Specify row, then column “Array of arrays”  a[0] is an array of 4 elements  a[0][0] is the first element of that array Row 0 Row 1 Row 2 Column 0 Column 1 Column 2 Column 3 a[ 0 ][ 0 ] a[ 1 ][ 0 ] a[ 2 ][ 0 ] a[ 0 ][ 1 ] a[ 1 ][ 1 ] a[ 2 ][ 1 ] a[ 0 ][ 2 ] a[ 1 ][ 2 ] a[ 2 ][ 2 ] a[ 0 ][ 3 ] a[ 1 ][ 3 ] a[ 2 ][ 3 ] Row subscript Array name Column subscript To initialize Default of 0 Initializers grouped by row in braces int b[ 2 ][ 2 ]={ { 1, 2 }, { 3, 4 } }; int b[ 2 ][ 2 ] = { { 1 }, { 3, 4 } };
  • 73. Pointer  Pointer variables  Contain memory addresses as values  Normally, variable contains specific value (direct reference)  Pointers contain address of variable that has specific value (indirect reference)  Indirection  Referencing value through pointer  Pointer declarations  * indicates variable is pointer int *myPtr; declares pointer to int, pointer of type int *  Multiple pointers require multiple asterisks int *myPtr1, *myPtr2; count 7 countPtr count 7 Pointer Variable Declarations and Initialization
  • 74. Pointer Operators  & (address operator)  Returns memory address of its operand  Example int y = 5; int *yPtr; yPtr = &y; yPtr y 5 yptr 500000 600000 y 600000 5 address of y is value of yptr yPtr “points to” y * - indirection/ dereferencing operator) *yPtr returns y dereferenced pointer is lvalue *yptr = 9 ??
  • 75. Calling Functions by Reference  3 ways to pass arguments to function  Pass-by-value  Pass-by-reference with reference arguments  Pass-by-reference with pointer arguments  Arguments passed to function using reference arguments  Modify original values of arguments  More than one value “returned” int Cube(int *x) { …} Function call: Cube(&a)
  • 76. Using const with Pointers const qualifier Value of variable should not be modified const used when function does not need to change a variable Principle of least privilege const pointers Always point to same memory location Default for array name Must be initialized when declared Four ways to pass pointer to function Nonconstant pointer to nonconstant data  Highest amount of access Nonconstant pointer to constant data Constant pointer to nonconstant data Constant pointer to constant data  Least amount of access
  • 77. 1 // Example 3 2 // Attempting to modify a constant pointer to 3 // non-constant data. 4 5 int main() 6 { 7 int x, y; 8 9 // ptr is a constant pointer to an integer that can 10 // be modified through ptr, but ptr always points to the 11 // same memory location. 12 int * const ptr = &x; 13 14 *ptr = 7; // allowed: *ptr is not const 15 ptr = &y; // error: ptr is const; cannot assign new address 16 17 return 0; // indicates successful termination 18 19 } // end main d:cpphtp4_examplesch05Fig05_13.cpp(15) : error C2166: l-value specifies const object ptr is constant pointer to integer.Can modify x (pointed to by ptr) since x not constant.Cannot modify ptr to point to new address since ptr is constant. Line 15 generates compiler error by attempting to assign new address to constant pointer.
  • 78. 1 // Example 4 2 // Attempting to modify a constant pointer to constant data. 3 #include <iostream> 4 5 using std::cout; 6 using std::endl; 7 8 int main() 9 { 10 int x = 5, y; 11 12 // ptr is a constant pointer to a constant integer. 13 // ptr always points to the same location; the integer 14 // at that location cannot be modified. 15 const int *const ptr = &x; 16 17 cout << *ptr << endl; 18 19 *ptr = 7; // error: *ptr is const; cannot assign new value 20 ptr = &y; // error: ptr is const; cannot assign new address 21 22 return 0; // indicates successful termination 23 24 } // end main ptr is constant pointer to integer constant. Cannot modify x (pointed to by ptr) since *ptr declared constant. Cannot modify ptr to point to new address since ptr is constant.
  • 79. Pointer Expressions and Pointer Arithmetic Pointer arithmetic  Increment/decrement pointer (++ or --)  Add/subtract an integer to/from a pointer( + or += , - or -=)  Pointers may be subtracted from each other  Pointer arithmetic meaningless unless performed on pointer to array 5 element int array on a machine using 4 byte ints  vPtr points to first element v[ 0 ], which is at location 3000 vPtr = 3000  vPtr += 2; sets vPtr to 3008 vPtr points to v[ 2 ] pointer variable vPtr v[0] v[1] v[2] v[4]v[3] 3000 3004 3008 3012 3016 location
  • 80. Pointer Expressions and Pointer Arithmetic  Subtracting pointers  Returns number of elements between two addresses vPtr2 = v[ 2 ]; vPtr = v[ 0 ]; vPtr2 - vPtr == 2  Pointer assignment  Pointer can be assigned to another pointer if both of same type  If not same type, cast operator must be used  Exception: pointer to void (type void *)  Generic pointer, represents any type  No casting needed to convert pointer to void pointer  void pointers cannot be dereferenced
  • 81. Pointer Expressions and Pointer Arithmetic  Pointer comparison  Use equality and relational operators  Comparisons meaningless unless pointers point to members of same array  Compare addresses stored in pointers  Example: could show that one pointer points to higher numbered element of array than other pointer  Common use to determine whether pointer is 0 (does not point to anything)
  • 82. Relationship Between Pointers and Arrays  Arrays and pointers closely related  Array name like constant pointer  Pointers can do array subscripting operations  Accessing array elements with pointers  Element b[ n ] can be accessed by *( bPtr + n )  Called pointer/offset notation  Addresses  &b[ 3 ] same as bPtr + 3  Array name can be treated as pointer  b[ 3 ] same as *( b + 3 )  Pointers can be subscripted (pointer/subscript notation)  bPtr[ 3 ] same as b[ 3 ]
  • 83. Arrays of Pointers  Arrays can contain pointers  Commonly used to store array of strings char *suit[ 4 ] = {"Hearts", "Diamonds", "Clubs", "Spades" };  Each element of suit points to char * (a string)  Array does not store strings, only pointers to strings  suit array has fixed size, but strings can be of any size suit[3] suit[2] suit[1] suit[0] ’H’ ’e’ ’a’ ’r’ ’t’ ’s’ ’0’ ’D’ ’i’ ’a’ ’m’ ’o’ ’n’ ’d’ ’s’ ’0’ ’C’ ’l’ ’u’ ’b’ ’s’ ’0’ ’S’ ’p’ ’a’ ’d’ ’e’ ’s’ ’0’
  • 84. Function Pointers  Calling functions using pointers  Assume parameter:  bool ( *compare ) ( int, int )  Execute function with either  ( *compare ) ( int1, int2 ) Dereference pointer to function to execute OR  compare( int1, int2 ) Could be confusing  User may think compare name of actual function in program
  • 85. 1 // Example 5 2 // Multipurpose sorting program using function pointers. 3 #include <iostream> 4 5 using std::cout; 6 using std::cin; 7 using std::endl; 8 9 #include <iomanip> 10 11 using std::setw; 12 13 // prototypes 14 void bubble( int [], const int, bool (*)( int, int ) ); 15 void swap( int * const, int * const ); 16 bool ascending( int, int ); 17 bool descending( int, int ); 18 19 int main() 20 { 21 const int arraySize = 10; 22 int order; 23 int counter; 24 int a[ arraySize ] = { 2, 6, 4, 8, 10, 12, 89, 68, 45, 37 }; 25 Parameter is pointer to function that receives two integer parameters and returns bool result.
  • 86. 26 cout << "Enter 1 to sort in ascending order,n" 27 << "Enter 2 to sort in descending order: "; 28 cin >> order; 29 cout << "nData items in original ordern"; 30 31 // output original array 32 for ( counter = 0; counter < arraySize; counter++ ) 33 cout << setw( 4 ) << a[ counter ]; 34 35 // sort array in ascending order; pass function ascending 36 // as an argument to specify ascending sorting order 37 if ( order == 1 ) { 38 bubble( a, arraySize, ascending ); 39 cout << "nData items in ascending ordern"; 40 } 41 42 // sort array in descending order; pass function descending 43 // as an agrument to specify descending sorting order 44 else { 45 bubble( a, arraySize, descending ); 46 cout << "nData items in descending ordern"; 47 } 48
  • 87. 49 // output sorted array 50 for ( counter = 0; counter < arraySize; counter++ ) 51 cout << setw( 4 ) << a[ counter ]; 52 53 cout << endl; 54 55 return 0; // indicates successful termination 56 57 } // end main 58 59 // multipurpose bubble sort; parameter compare is a pointer to 60 // the comparison function that determines sorting order 61 void bubble( int work[], const int size, 62 bool (*compare)( int, int ) ) 63 { 64 // loop to control passes 65 for ( int pass = 1; pass < size; pass++ ) 66 67 // loop to control number of comparisons per pass 68 for ( int count = 0; count < size - 1; count++ ) 69 70 // if adjacent elements are out of order, swap them 71 if ( (*compare)( work[ count ], work[ count + 1 ] ) ) 72 swap( &work[ count ], &work[ count + 1 ] ); compare is pointer to function that receives two integer parameters and returns bool result. Parentheses necessary to indicate pointer to function Call passed function compare; dereference pointer to execute function.
  • 88. 73 74 } // end function bubble 75 76 // swap values at memory locations to which 77 // element1Ptr and element2Ptr point 78 void swap( int * const element1Ptr, int * const element2Ptr ) 79 { 80 int hold = *element1Ptr; 81 *element1Ptr = *element2Ptr; 82 *element2Ptr = hold; 83 84 } // end function swap 85 86 // determine whether elements are out of order 87 // for an ascending order sort 88 bool ascending( int a, int b ) 89 { 90 return b < a; // swap if b is less than a 91 92 } // end function ascending 93
  • 89. 94 // determine whether elements are out of order 95 // for a descending order sort 96 bool descending( int a, int b ) 97 { 98 return b > a; // swap if b is greater than a 99 100 } // end function descending Enter 1 to sort in ascending order, Enter 2 to sort in descending order: 1 Data items in original order 2 6 4 8 10 12 89 68 45 37 Data items in ascending order 2 4 6 8 10 12 37 45 68 89 Enter 1 to sort in ascending order, Enter 2 to sort in descending order: 2 Data items in original order 2 6 4 8 10 12 89 68 45 37 Data items in descending order 89 68 45 37 12 10 8 6 4 2
  • 90. Function Pointers  Arrays of pointers to functions  Menu-driven systems  Pointers to each function stored in array of pointers to functions  All functions must have same return type and same parameter types  Menu choice  subscript into array of function pointers
  • 91. 1 // Example 6 2 // Demonstrating an array of pointers to functions. 3 #include <iostream> 4 5 using std::cout; 6 using std::cin; 7 using std::endl; 8 9 // function prototypes 10 void function1( int ); 11 void function2( int ); 12 void function3( int ); 13 14 int main() 15 { 16 // initialize array of 3 pointers to functions that each 17 // take an int argument and return void 18 void (*f[ 3 ])( int ) = { function1, function2, function3 }; 19 20 int choice; 21 22 cout << "Enter a number between 0 and 2, 3 to end: "; 23 cin >> choice; 24 Array initialized with names of three functions; function names are pointers.
  • 92. 25 // process user's choice 26 while ( choice >= 0 && choice < 3 ) { 27 28 // invoke function at location choice in array f 29 // and pass choice as an argument 30 (*f[ choice ])( choice ); 31 32 cout << "Enter a number between 0 and 2, 3 to end: "; 33 cin >> choice; 34 } 35 36 cout << "Program execution completed." << endl; 37 38 return 0; // indicates successful termination 39 40 } // end main 41 42 void function1( int a ) 43 { 44 cout << "You entered " << a 45 << " so function1 was callednn"; 46 47 } // end function1 48 Call chosen function by dereferencing corresponding element in array.
  • 93. 25 // process user's choice 26 while ( choice >= 0 && choice < 3 ) { 27 28 // invoke function at location choice in array f 29 // and pass choice as an argument 30 (*f[ choice ])( choice ); 31 32 cout << "Enter a number between 0 and 2, 3 to end: "; 33 cin >> choice; 34 } 35 36 cout << "Program execution completed." << endl; 37 38 return 0; // indicates successful termination 39 40 } // end main 41 42 void function1( int a ) 43 { 44 cout << "You entered " << a 45 << " so function1 was callednn"; 46 47 } // end function1 48 Call chosen function by dereferencing corresponding element in array.
  • 94. Fundamentals of Characters and Strings  Character constant  Integer value represented as character in single quotes  'z' is integer value of z  122 in ASCII  String  Series of characters treated as single unit  Can include letters, digits, special characters +, -, * ...  String literal (string constants)  Enclosed in double quotes, for example: "I like C++"  Array of characters, ends with null character '0'  String is constant pointer  Pointer to string’s first character Like arrays
  • 95. Fundamentals of Characters and Strings  String assignment  Character array  char color[] = "blue"; Creates 5 element char array color  last element is '0'  Variable of type char *  char *colorPtr = "blue"; Creates pointer colorPtr to letter b in string “blue”  “blue” somewhere in memory  Alternative for character array  char color[] = { ‘b’, ‘l’, ‘u’, ‘e’, ‘0’ };
  • 96. Fundamentals of Characters and Strings  Reading strings  Assign input to character array word[ 20 ] cin >> word  Reads characters until whitespace or EOF  String could exceed array size cin >> setw( 20 ) >> word;  Reads 19 characters (space reserved for '0')
  • 97. Fundamentals of Characters and Strings  cin.getline  Read line of text  cin.getline( array, size, delimiter );  Copies input into specified array until either  One less than size is reached  delimiter character is input  Example char sentence[ 80 ]; cin.getline( sentence, 80, 'n' );
  • 98. String Manipulation Functions of the String- handling Library  String handling library <cstring> provides functions to  Manipulate string data  Compare strings  Search strings for characters and other strings  Tokenize strings (separate strings into logical pieces)
  • 99. String Manipulation Functions of the String- handling Library char *strcpy( char *s1, const char *s2 ); Copies the string s2 into the character array s1. The value of s1 is returned. char *strncpy( char *s1, const char *s2, size_t n ); Copies at most n characters of the string s2 into the character array s1. The value of s1 is returned. char *strcat( char *s1, const char *s2 ); Appends the string s2 to the string s1. The first character of s2 overwrites the terminating null character of s1. The value of s1 is returned. char *strncat( char *s1, const char *s2, size_t n ); Appends at most n characters of string s2 to string s1. The first character of s2 overwrites the terminating null character of s1. The value of s1 is returned. int strcmp( const char *s1, const char *s2 ); Compares the string s1 with the string s2. The function returns a value of zero, less than zero or greater than zero if s1 is equal to, less than or greater than s2, respectively.
  • 100. String Manipulation Functions of the String-handling Library int strncmp( const char *s1, const char *s2, size_t n ); Compares up to n characters of the string s1 with the string s2. The function returns zero, less than zero or greater than zero if s1 is equal to, less than or greater than s2, respectively. char *strtok( char *s1, const char *s2 ); A sequence of calls to strtok breaks string s1 into “tokens”—logical pieces such as words in a line of text— delimited by characters contained in string s2. The first call contains s1 as the first argument, and subsequent calls to continue tokenizing the same string contain NULL as the first argument. A pointer to the current token is returned by each call. If there are no more tokens when the function is called, NULL is returned. size_t strlen( const char *s ); Determines the length of string s. The number of characters preceding the terminating null character is returned.
  • 101. Structure Definitions  Structures  Aggregate data types built using elements of other types struct Time { int hour; int minute; int second; }; Structure member naming  In same struct: must have unique names  In different structs: can share name struct definition must end with semicolon Structure tag Structure members Structure
  • 102. Structure Definitions  Self-referential structure  Structure member cannot be instance of enclosing struct  Structure member can be pointer to instance of enclosing struct (self-referential structure)  Used for linked lists, queues, stacks and trees  struct definition  Creates new data type used to declare variables  Structure variables declared like variables of other types  Examples:  Time timeObject;  Time timeArray[ 10 ];  Time *timePtr;  Time &timeRef = timeObject;
  • 103. Accessing Structure Members  Member access operators  Dot operator (.) for structure and class members  Arrow operator (->) for structure and class members via pointer to object  Print member hour of timeObject: cout << timeObject.hour; OR timePtr = &timeObject; cout << timePtr->hour;  timePtr->hour same as ( *timePtr ).hour  Parentheses required * lower precedence than .
  • 104. Implementing a User-Defined Type Time with a struct  Default: structures passed by value  Pass structure by reference  Avoid overhead of copying structure  C-style structures  No “interface”  If implementation changes, all programs using that struct must change accordingly  Cannot print as unit  Must print/format member by member  Cannot compare in entirety  Must compare member by member
  • 105. 1 // Example 7 2 // Create a structure, set its members, and print it. 3 #include <iostream> 4 5 using std::cout; 6 using std::endl; 7 8 #include <iomanip> 9 10 using std::setfill; 11 using std::setw; 12 13 // structure definition 14 struct Time { 15 int hour; // 0-23 (24-hour clock format) 16 int minute; // 0-59 17 int second; // 0-59 18 19 }; // end struct Time 20 21 void printUniversal( const Time & ); // prototype 22 void printStandard( const Time & ); // prototype 23 Define structure type Time with three integer members. Pass references to constant Time objects to eliminate copying overhead.
  • 106. Class  Classes(keyword class)  Model objects  Attributes (data members)  Behaviors (member functions) Methods Invoked in response to messages  Member access specifiers: public, Private, protected:  Constructor function  Special member function  Initializes data members  Same name as class  Called when object instantiated  Several constructors  Function overloading  No return type
  • 107. Implementing a Time Abstract Data Type with a class  Objects of class  After class definition  Class name new type specifier  Object, array, pointer and reference declarations Member functions defined outside class Time sunset; // object of type Time Time arrayOfTimes[ 5 ]; // array of Time objects Time *pointerToTime; // pointer to a Time object Time &dinnerTime = sunset; // reference to a Time object Class name becomes new type specifier. Binary scope resolution (::) ReturnType ClassName::MemberFunctionName( ){…} Member functions defined inside class Do not need scope resolution operator, class name Compiler attempts inline Outside class, inline explicitly with keyword inline
  • 108. 1 // Example 8 2 // Time class. 3 #include <iostream> 4 5 using std::cout; 6 using std::endl; 7 8 #include <iomanip> 9 10 using std::setfill; 11 using std::setw; 12 13 // Time abstract data type (ADT) definition 14 class Time { 15 16 public: 17 Time(); // constructor 18 void setTime( int, int, int ); // set hour, minute, second 19 void printUniversal(); // print universal-time format 20 void printStandard(); // print standard-time format 21 Define class Time.
  • 109. 22 private: 23 int hour; // 0 - 23 (24-hour clock format) 24 int minute; // 0 - 59 25 int second; // 0 - 59 26 27 }; // end class Time 28 29 // Time constructor initializes each data member to zero and 30 // ensures all Time objects start in a consistent state 31 Time::Time() 32 { 33 hour = minute = second = 0; 34 35 } // end Time constructor 36 37 // set new Time value using universal time, perform validity 38 // checks on the data values and set invalid values to zero 39 void Time::setTime( int h, int m, int s ) 40 { 41 hour = ( h >= 0 && h < 24 ) ? h : 0; 42 minute = ( m >= 0 && m < 60 ) ? m : 0; 43 second = ( s >= 0 && s < 60 ) ? s : 0; 44 45 } // end function setTime 46 Constructor initializes private data members to 0. public member function checks parameter values for validity before setting private data members.
  • 110. 47 // print Time in universal format 48 void Time::printUniversal() 49 { 50 cout << setfill( '0' ) << setw( 2 ) << hour << ":" 51 << setw( 2 ) << minute << ":" 52 << setw( 2 ) << second; 53 54 } // end function printUniversal 55 56 // print Time in standard format 57 void Time::printStandard() 58 { 59 cout << ( ( hour == 0 || hour == 12 ) ? 12 : hour % 12 ) 60 << ":" << setfill( '0' ) << setw( 2 ) << minute 61 << ":" << setw( 2 ) << second 62 << ( hour < 12 ? " AM" : " PM" ); 63 64 } // end function printStandard 65 66 int main() 67 { 68 Time t; // instantiate object t of class Time 69 Declare variable t to be object of class Time. No arguments (implicitly “know” purpose is to print data members); member function calls more concise.
  • 111. 70 // output Time object t's initial values 71 cout << "The initial universal time is "; 72 t.printUniversal(); // 00:00:00 73 74 cout << "nThe initial standard time is "; 75 t.printStandard(); // 12:00:00 AM 76 77 t.setTime( 13, 27, 6 ); // change time 78 79 // output Time object t's new values 80 cout << "nnUniversal time after setTime is "; 81 t.printUniversal(); // 13:27:06 82 83 cout << "nStandard time after setTime is "; 84 t.printStandard(); // 1:27:06 PM 85 86 t.setTime( 99, 99, 99 ); // attempt invalid settings 87 88 // output t's values after specifying invalid values 89 cout << "nnAfter attempting invalid settings:" 90 << "nUniversal time: "; 91 t.printUniversal(); // 00:00:00 92 Invoke public member functions to print time. Set data members using public member function. Attempt to set data members to invalid values using public member function.
  • 112. 93 cout << "nStandard time: "; 94 t.printStandard(); // 12:00:00 AM 95 cout << endl; 96 97 return 0; 98 99 } // end main The initial universal time is 00:00:00 The initial standard time is 12:00:00 AM Universal time after setTime is 13:27:06 Standard time after setTime is 1:27:06 PM After attempting invalid settings: Universal time: 00:00:00 Standard time: 12:00:00 AM Data members set to 0 after attempting invalid settings.
  • 113. Classes  Destructors  Same name as class  Preceded with tilde (~)  No arguments  Cannot be overloaded  Performs “termination housekeeping”  Advantages of using classes  Simplify programming  Interfaces  Hide implementation  Software reuse  Composition (aggregation) Class objects included as members of other classes  Inheritance New classes derived from old
  • 114. Class Scope and Accessing Class Members  Class scope  Data members, member functions  Within class scope  Class members Immediately accessible by all member functions Referenced by name  Outside class scope  Referenced through handles Object name, reference to object, pointer to object  File scope  Nonmember functions
  • 115. Class Scope and Accessing Class Members Function scope Variables declared in member function Only known to function Variables with same name as class-scope variables  Class-scope variable “hidden” Access with scope resolution operator (::) ClassName::classVariableName Variables only known to function they are defined in Variables are destroyed after function completion Operators to access class members Identical to those for structs Dot member selection operator (.)  Object  Reference to object Arrow member selection operator (->)  Pointers
  • 116. 1 // Example 9 2 // Demonstrating the class member access operators . and -> 3 // 4 // CAUTION: IN FUTURE EXAMPLES WE AVOID PUBLIC DATA! 5 #include <iostream> 6 7 using std::cout; 8 using std::endl; 9 10 // class Count definition 11 class Count { 12 13 public: 14 int x; 15 16 void print() 17 { 18 cout << x << endl; 19 } 20 21 }; // end class Count 22 Data member x public to illustrate class member access operators; typically data members private.
  • 117. Separating Interface from Implementation Separating interface from implementation Advantage: Easier to modify programs Disadvantage  Header files Portions of implementation: Inline member functions Hints about other implementation: private members  Can hide more with proxy class Header files Class definitions and function prototypes Included in each file using class  #include File extension .h Source-code files Member function definitions Same base name  Convention Compiled and linked
  • 118. Controlling Access to Members  Access modes  private  Default access mode  Accessible to member functions and friends  public  Accessible to any function in program with handle to class object  protected (later)  Class member access  Default private  Explicitly set to private, public, protected  struct member access  Default public  Explicitly set to private, public, protected
  • 119. Access Functions and Utility Functions  Access to class’s private data  Controlled with access functions (accessor methods)  Get function - Read private data  Set function - Modify private data  Access functions  public  Read/display data  Predicate functions  Check conditions  Utility functions (helper functions)  private  Support operation of public member functions  Not intended for direct client use
  • 120. 1 // Example 10 2 // SalesPerson class definition. 3 // Member functions defined in salesp.cpp. 4 #ifndef SALESP_H 5 #define SALESP_H 6 7 class SalesPerson { 8 9 public: 10 SalesPerson(); // constructor 11 void getSalesFromUser(); // input sales from keyboard 12 void setSales( int, double ); // set sales for a month 13 void printAnnualSales(); // summarize and print sales 14 15 private: 16 double totalAnnualSales(); // utility function 17 double sales[ 12 ]; // 12 monthly sales figures 18 19 }; // end class SalesPerson 20 21 #endif Set access function performs validity checks. private utility function.
  • 121. 25 // get 12 sales figures from the user at the keyboard 26 void SalesPerson::getSalesFromUser() 27 { 28 double salesFigure; 29 30 for ( int i = 1; i <= 12; i++ ) { 31 cout << "Enter sales amount for month " << i << ": "; 32 cin >> salesFigure; 33 setSales( i, salesFigure ); 34 35 } // end for 36 37 } // end function getSalesFromUser 38 39 // set one of the 12 monthly sales figures; function subtracts 40 // one from month value for proper subscript in sales array 41 void SalesPerson::setSales( int month, double amount ) 42 { 43 // test for valid month and amount values 44 if ( month >= 1 && month <= 12 && amount > 0 ) 45 sales[ month - 1 ] = amount; // adjust for subscripts 0-11 46 47 else // invalid month or amount value 48 cout << "Invalid month or sales figure" << endl; Set access function performs validity checks.
  • 122. Initializing Class Objects: Constructors Constructors Initialize data members; no return type  Or can set later Same name as class Can specify default arguments Default constructors  Defaults all arguments OR  Explicitly requires no arguments  Can be invoked with no arguments  Only one per class Initializers Passed as arguments to constructor In parentheses to right of class name before semicolon Class-type ObjectName( value1,value2,…);
  • 123. 1 // Example 11 2 // Declaration of class Time. 3 // Member functions defined in time2.cpp. 4 5 // prevent multiple inclusions of header file 6 #ifndef TIME2_H 7 #define TIME2_H 8 9 // Time abstract data type definition 10 class Time { 11 12 public: 13 Time( int = 0, int = 0, int = 0); // default constructor 14 void setTime( int, int, int ); // set hour, minute, second 15 void printUniversal(); // print universal-time format 16 void printStandard(); // print standard-time format 17 18 private: 19 int hour; // 0 - 23 (24-hour clock format) 20 int minute; // 0 - 59 21 int second; // 0 - 59 22 23 }; // end class Time 24 25 #endif Default constructor specifying all arguments.
  • 124. 1 // Example 12 2 // Member-function definitions for class Time. 3 #include <iostream> 4 5 using std::cout; 6 7 #include <iomanip> 8 9 using std::setfill; 10 using std::setw; 11 12 // include definition of class Time from time2.h 13 #include "time2.h" 14 15 // Time constructor initializes each data member to zero; 16 // ensures all Time objects start in a consistent state 17 Time::Time( int hr, int min, int sec ) 18 { 19 setTime( hr, min, sec ); // validate and set time 20 21 } // end Time constructor 22 Constructor calls setTime to validate passed (or default) values.
  • 125. 23 // set new Time value using universal time, perform validity 24 // checks on the data values and set invalid values to zero 25 void Time::setTime( int h, int m, int s ) 26 { 27 hour = ( h >= 0 && h < 24 ) ? h : 0; 28 minute = ( m >= 0 && m < 60 ) ? m : 0; 29 second = ( s >= 0 && s < 60 ) ? s : 0; 30 31 } // end function setTime 32 33 // print Time in universal format 34 void Time::printUniversal() 35 { 36 cout << setfill( '0' ) << setw( 2 ) << hour << ":" 37 << setw( 2 ) << minute << ":" 38 << setw( 2 ) << second; 39 40 } // end function printUniversal 41
  • 126. 1 // Example 13 2 // Demonstrating a default constructor for class Time. 3 #include <iostream> 4 5 using std::cout; 6 using std::endl; 7 8 // include definition of class Time from time2.h 9 #include "time2.h" 10 11 int main() 12 { 13 Time t1; // all arguments defaulted 14 Time t2( 2 ); // minute and second defaulted 15 Time t3( 21, 34 ); // second defaulted 16 Time t4( 12, 25, 42 ); // all values specified 17 Time t5( 27, 74, 99 ); // all bad values specified 18 19 cout << "Constructed with:nn" 20 << "all default arguments:n "; 21 t1.printUniversal(); // 00:00:00 22 cout << "n "; 23 t1.printStandard(); // 12:00:00 AM 24 Initialize Time objects using default arguments. Initialize Time object with invalid values; validity checking will set values to 0.
  • 127. 25 cout << "nnhour specified; default minute and second:n "; 26 t2.printUniversal(); // 02:00:00 27 cout << "n "; 28 t2.printStandard(); // 2:00:00 AM 29 30 cout << "nnhour and minute specified; default second:n "; 31 t3.printUniversal(); // 21:34:00 32 cout << "n "; 33 t3.printStandard(); // 9:34:00 PM 34 35 cout << "nnhour, minute, and second specified:n "; 36 t4.printUniversal(); // 12:25:42 37 cout << "n "; 38 t4.printStandard(); // 12:25:42 PM 39 40 cout << "nnall invalid values specified:n "; 41 t5.printUniversal(); // 00:00:00 42 cout << "n "; 43 t5.printStandard(); // 12:00:00 AM 44 cout << endl; 45 46 return 0; 47 48 } // end main t5 constructed with invalid arguments; values set to 0.
  • 128. Destructors  Destructors  Special member function  Same name as class preceded with tilde (~)  No arguments; No return value  Cannot be overloaded  Performs “termination housekeeping”  Before system reclaims object’s memory Reuse memory for new objects  No explicit destructor  Compiler creates “empty destructor”  Constructors and destructors - Called implicitly by compiler  Order of function calls  Depends on when execution enters and exits scope of objects  Generally, destructor calls reverse order of constructor calls
  • 129. When Constructors and Destructors Are Called  Global scope objects  Constructors - Before any other function (including main)  Destructors When main terminates (or exit function called) Not called if program terminates with abort  Automatic local objects  Constructors - When objects defined & each time execution enters scope  Destructors When objects leave scope  Execution exits block in which object defined Not called if program ends with exit or abort  static local objects  Constructors Exactly once When execution reaches point where object defined  Destructors When main terminates or exit function called Not called if program ends with abort
  • 130. 1 // Example 14 2 // Demonstrating the order in which constructors and 3 // destructors are called. 4 #include <iostream> 5 6 using std::cout; 7 using std::endl; 8 9 // include CreateAndDestroy class definition from create.h 10 #include "create.h" 11 12 void create( void ); // prototype 13 14 // global object 15 CreateAndDestroy first( 1, "(global before main)" ); 16 17 int main() 18 { 19 cout << "nMAIN FUNCTION: EXECUTION BEGINS" << endl; 20 21 CreateAndDestroy second( 2, "(local automatic in main)" ); 22 23 static CreateAndDestroy third( 24 3, "(local static in main)" ); 25 Create variable with global scope. Create local automatic object. Create static local object.
  • 131. 26 create(); // call function to create objects 27 28 cout << "nMAIN FUNCTION: EXECUTION RESUMES" << endl; 29 30 CreateAndDestroy fourth( 4, "(local automatic in main)" ); 31 32 cout << "nMAIN FUNCTION: EXECUTION ENDS" << endl; 33 34 return 0; 35 36 } // end main 37 38 // function to create objects 39 void create( void ) 40 { 41 cout << "nCREATE FUNCTION: EXECUTION BEGINS" << endl; 42 43 CreateAndDestroy fifth( 5, "(local automatic in create)" ); 44 45 static CreateAndDestroy sixth( 46 6, "(local static in create)" ); 47 48 CreateAndDestroy seventh( 49 7, "(local automatic in create)" ); 50 cout << "nCREATE FUNCTION: EXECUTION ENDS" << endl; 52 53 } // end function create Create local automatic objects. Create local automatic object. Create local automatic object in function. Create static local object in function. Create local automatic object in function.
  • 132. Object 1 constructor runs (global before main) MAIN FUNCTION: EXECUTION BEGINS Object 2 constructor runs (local automatic in main) Object 3 constructor runs (local static in main) CREATE FUNCTION: EXECUTION BEGINS Object 5 constructor runs (local automatic in create) Object 6 constructor runs (local static in create) Object 7 constructor runs (local automatic in create) CREATE FUNCTION: EXECUTION ENDS Object 7 destructor runs (local automatic in create) Object 5 destructor runs (local automatic in create) MAIN FUNCTION: EXECUTION RESUMES Object 4 constructor runs (local automatic in main) MAIN FUNCTION: EXECUTION ENDS Object 4 destructor runs (local automatic in main) Object 2 destructor runs (local automatic in main) Object 6 destructor runs (local static in create) Object 3 destructor runs (local static in main) Object 1 destructor runs (global before main) Destructors for local automatic objects in main called in reverse order of constructors. Local static object exists until program termination.Global object constructed before main execution and destroyed last. Local automatic objects destroyed after function execution ends in reverse order of construction. Local static object constructed on first function call and destroyed after main execution ends.
  • 133. Using Set and Get Functions  Set functions  Perform validity checks before modifying private data  Notify if invalid values  Indicate with return values  Get functions  “Query” functions  Control format of data returned
  • 134. Subtle Trap: Returning a Reference to a private Data Member  Reference to object  &pRef = p;  Alias for name of object  Lvalue  Can receive value in assignment statement Changes original object  Returning references  public member functions can return non-const references to private data members  Client able to modify private data members
  • 135. 1 // Example 15 2 // Declaration of class Time. 3 // Member functions defined in time4.cpp 4 5 // prevent multiple inclusions of header file 6 #ifndef TIME4_H 7 #define TIME4_H 8 9 class Time { 10 11 public: 12 Time( int = 0, int = 0, int = 0 ); 13 void setTime( int, int, int ); 14 int getHour(); 15 16 int &badSetHour( int ); // DANGEROUS reference return 17 18 private: 19 int hour; 20 int minute; 21 int second; 22 23 }; // end class Time 24 25 #endif Function to demonstrate effects of returning reference to private data member.
  • 136. 25 // return hour value 26 int Time::getHour() 27 { 28 return hour; 29 30 } // end function getHour 31 32 // POOR PROGRAMMING PRACTICE: 33 // Returning a reference to a private data member. 34 int &Time::badSetHour( int hh ) 35 { 36 hour = ( hh >= 0 && hh < 24 ) ? hh : 0; 37 38 return hour; // DANGEROUS reference return 39 40 } // end function badSetHour Return reference to private data member hour.
  • 137. 1 // Example 16 2 // Demonstrating a public member function that 3 // returns a reference to a private data member. 4 #include <iostream> 5 6 using std::cout; 7 using std::endl; 8 9 // include definition of class Time from time4.h 10 #include "time4.h" 11 12 int main() 13 { 14 Time t; 15 16 // store in hourRef the reference returned by badSetHour 17 int &hourRef = t.badSetHour( 20 ); 18 19 cout << "Hour before modification: " << hourRef; 20 21 // use hourRef to set invalid value in Time object t 22 hourRef = 30; 23 24 cout << "nHour after modification: " << t.getHour(); 25 badSetHour returns reference to private data member hour. Reference allows setting of private data member hour.
  • 138. 26 // Dangerous: Function call that returns 27 // a reference can be used as an lvalue! 28 t.badSetHour( 12 ) = 74; 29 30 cout << "nn*********************************n" 31 << "POOR PROGRAMMING PRACTICE!!!!!!!!n" 32 << "badSetHour as an lvalue, Hour: " 33 << t.getHour() 34 << "n*********************************" << endl; 35 36 return 0; 37 38 } // end main Hour before modification: 20 Hour after modification: 30 ********************************* POOR PROGRAMMING PRACTICE!!!!!!!! badSetHour as an lvalue, Hour: 74 ********************************* Can use function call as lvalue to set invalid value. Returning reference allowed invalid setting of private data member hour.
  • 139. Default Memberwise Assignment  Assigning objects  Assignment operator (=)  Can assign one object to another of same type  Default: memberwise assignment Each right member assigned individually to left member  Passing, returning objects  Objects passed as function arguments  Objects returned from functions  Default: pass-by-value  Copy of object passed, returned Copy constructor  Copy original values into new object
  • 140. 1 // Example 17 2 // Demonstrating that class objects can be assigned 3 // to each other using default memberwise assignment. 4 #include <iostream> 5 6 using std::cout; 7 using std::endl; 8 9 // class Date definition 10 class Date { 11 12 public: 13 Date( int = 1, int = 1, int = 1990 ); // default constructor 14 void print(); 15 16 private: 17 int month; 18 int day; 19 int year; 20 21 }; // end class Date 22
  • 141. Software Reusability  Software reusability  Class libraries  Well-defined  Carefully tested  Well-documented  Portable  Widely available  Speeds development of powerful, high-quality software  Rapid applications development (RAD)  Resulting problems  Cataloging schemes  Licensing schemes  Protection mechanisms
  • 142. const (Constant) Objects and const Member Functions  Keyword const  Specify object not modifiable  Compiler error if attempt to modify const object  Example const Time noon( 12, 0, 0 );  Declares const object noon of class Time  Initializes to 12  const member functions  Member functions for const objects must also be const  Cannot modify object  Specify const in both prototype and definition  Prototype After parameter list  Definition Before beginning left brace
  • 143. const (Constant) Objects and const Member Functions  Constructors and destructors  Cannot be const  Must be able to modify objects  Constructor Initializes objects  Destructor Performs termination housekeeping  Member initializer syntax  Initializing with member initializer syntax  Can be used for All data members  Must be used for const data members Data members that are references
  • 144. 1 // Example 18 2 // Using a member initializer to initialize a 3 // constant of a built-in data type. 4 #include <iostream> 5 6 using std::cout; 7 using std::endl; 8 9 class Increment { 10 11 public: 12 Increment( int c = 0, int i = 1 ); // default constructor 13 14 void addIncrement() 15 { 16 count += increment; 17 18 } // end function addIncrement 19 20 void print() const; // prints count and increment 21
  • 145. 22 private: 23 int count; 24 const int increment; // const data member 25 26 }; // end class Increment 27 28 // constructor 29 Increment::Increment( int c, int i ) 30 : count( c ), // initializer for non-const member 31 increment( i ) // required initializer for const member 32 { 33 // empty body 34 35 } // end Increment constructor 36 37 // print count and increment values 38 void Increment::print() const 39 { 40 cout << "count = " << count 41 << ", increment = " << increment << endl; 42 43 } // end function print 44 Declare increment as const data member. Member initializer list separated from parameter list by colon. Member initializer syntax can be used for non-const data member count. Member initializer syntax must be used for const data member increment. Member initializer consists of data member name (increment) followed by parentheses containing initial value (c).
  • 146. Composition: Objects as Members of Classes  Composition  Class has objects of other classes as members  Construction of objects  Member objects constructed in order declared  Not in order of constructor’s member initializer list  Constructed before enclosing class objects (host objects)
  • 147. 1 // Example 19 2 // Date class definition. 3 // Member functions defined in date1.cpp 4 #ifndef DATE1_H 5 #define DATE1_H 6 7 class Date { 8 9 public: 10 Date( int = 1, int = 1, int = 1900 ); // default constructor 11 void print() const; // print date in month/day/year format 12 ~Date(); // provided to confirm destruction order 13 14 private: 15 int month; // 1-12 (January-December) 16 int day; // 1-31 based on month 17 int year; // any year 18 19 // utility function to test proper day for month and year 20 int checkDay( int ) const; 21 22 }; // end class Date 23 24 #endif Note no constructor with parameter of type Date. Recall compiler provides default copy constructor.
  • 148. 1 // EXAMPLE 20 2 // Employee class definition. 3 // Member functions defined in employee1.cpp. 4 #ifndef EMPLOYEE1_H 5 #define EMPLOYEE1_H 6 7 // include Date class definition from date1.h 8 #include "date1.h" 9 10 class Employee { 11 12 public: 13 Employee( 14 const char *, const char *, const Date &, const Date & ); 15 16 void print() const; 17 ~Employee(); // provided to confirm destruction order 18 19 private: 20 char firstName[ 25 ]; 21 char lastName[ 25 ]; 22 const Date birthDate; // composition: member object 23 const Date hireDate; // composition: member object 24 25 }; // end class Employee Using composition; Employee object contains Date objects as data members.
  • 149. 13 // constructor uses member initializer list to pass initializer 14 // values to constructors of member objects birthDate and 15 // hireDate [Note: This invokes the so-called "default copy 16 // constructor" which the C++ compiler provides implicitly.] 17 Employee::Employee( const char *first, const char *last, 18 const Date &dateOfBirth, const Date &dateOfHire ) 19 : birthDate( dateOfBirth ), // initialize birthDate 20 hireDate( dateOfHire ) // initialize hireDate 21 { 22 // copy first into firstName and be sure that it fits 23 int length = strlen( first ); 24 length = ( length < 25 ? length : 24 ); 25 strncpy( firstName, first, length ); 26 firstName[ length ] = '0'; 27 28 // copy last into lastName and be sure that it fits 29 length = strlen( last ); 30 length = ( length < 25 ? length : 24 ); 31 strncpy( lastName, last, length ); 32 lastName[ length ] = '0'; 33 34 // output Employee object to show when constructor is called 35 cout << "Employee object constructor: " 36 << firstName << ' ' << lastName << endl; 37 Member initializer syntax to initialize Date data members birthDate and hireDate; compiler uses default copy constructor. Output to show timing of constructors.
  • 150. 1 // Example 21 2 // Demonstrating composition--an object with member objects. 3 #include <iostream> 4 5 using std::cout; 6 using std::endl; 7 8 #include "employee1.h" // Employee class definition 9 10 int main() 11 { 12 Date birth( 7, 24, 1949 ); 13 Date hire( 3, 12, 1988 ); 14 Employee manager( "Bob", "Jones", birth, hire ); 15 16 cout << 'n'; 17 manager.print(); 18 19 cout << "nTest Date constructor with invalid values:n"; 20 Date lastDayOff( 14, 35, 1994 ); // invalid month and day 21 cout << endl; 22 23 return 0; 24 25 } // end main Create Date objects to pass to Employee constructor.
  • 151. friend Functions and friend Classes  friend function  Defined outside class’s scope  Right to access non-public members  Declaring friends  Function  Precede function prototype with keyword friend  Want to make all member functions of class ClassTwo as friends of class ClassOne  Place declaration of form friend class ClassTwo; in ClassOne definition
  • 152. friend Functions and friend Classes  Properties of friendship  Friendship granted, not taken  Class B friend of class A Class A must explicitly declare class B friend  Not symmetric  Class B friend of class A  Class A not necessarily friend of class B  Not transitive  Class A friend of class B  Class B friend of class C  Class A not necessarily friend of Class C
  • 153. 1 // Example 22 2 // Friends can access private members of a class. 3 #include <iostream> 4 5 using std::cout; 6 using std::endl; 7 8 // Count class definition 9 class Count { 10 friend void setX( Count &, int ); // friend declaration 11 12 public: 13 14 // constructor 15 Count() 16 : x( 0 ) // initialize x to 0 17 { 18 // empty body 19 20 } // end Count constructor 21 Precede function prototype with keyword friend.
  • 154. 22 // output x 23 void print() const 24 { 25 cout << x << endl; 26 27 } // end function print 28 29 private: 30 int x; // data member 31 32 }; // end class Count 33 34 // function setX can modify private data of Count 35 // because setX is declared as a friend of Count 36 void setX( Count &c, int val ) 37 { 38 c.x = val; // legal: setX is a friend of Count 39 40 } // end function setX 41 Pass Count object since C- style, standalone function. Since setX friend of Count, can access and modify private data member x.
  • 155. 42 int main() 43 { 44 Count counter; // create Count object 45 46 cout << "counter.x after instantiation: "; 47 counter.print(); 48 49 setX( counter, 8 ); // set x with a friend 50 51 cout << "counter.x after call to setX friend function: "; 52 counter.print(); 53 54 return 0; 55 56 } // end main counter.x after instantiation: 0 counter.x after call to setX friend function: 8 Use friend function to access and modify private data member x.
  • 156. Using the this Pointer  this pointer  Allows object to access own address  Not part of object itself  Implicit argument to non-static member function call  Implicitly reference member data and functions  Type of this pointer depends on  Type of object  Whether member function is const  In non-const member function of Employee this has type Employee * const  Constant pointer to non-constant Employee object  In const member function of Employee this has type const Employee * const  Constant pointer to constant Employee object
  • 157. 1 // Example 23 2 // Using the this pointer to refer to object members. 3 #include <iostream> 4 5 using std::cout; 6 using std::endl; 7 8 class Test { 9 10 public: 11 Test( int = 0 ); // default constructor 12 void print() const; 13 14 private: 15 int x; 16 17 }; // end class Test 18 19 // constructor 20 Test::Test( int value ) 21 : x( value ) // initialize x to value 22 { 23 // empty body 24 25 } // end Test constructor
  • 158. 26 27 // print x using implicit and explicit this pointers; 28 // parentheses around *this required 29 void Test::print() const 30 { 31 // implicitly use this pointer to access member x 32 cout << " x = " << x; 33 34 // explicitly use this pointer to access member x 35 cout << "n this->x = " << this->x; 36 37 // explicitly use dereferenced this pointer and 38 // the dot operator to access member x 39 cout << "n(*this).x = " << ( *this ).x << endl; 40 41 } // end function print 42 43 int main() 44 { 45 Test testObject( 12 ); 46 47 testObject.print(); 48 49 return 0; 50 Implicitly use this pointer; only specify name of data member (x). Explicitly use this pointer with arrow operator. Explicitly use this pointer; dereference this pointer first, then use dot operator. 51 } // end main x = 12 this->x = 12 (*this).x = 12
  • 159. Using the this Pointer  Cascaded member function calls  Multiple functions invoked in same statement  Function returns reference pointer to same object { return *this; }  Other functions operate on that pointer  Functions that do not return references must be called last
  • 160. 1 // Example 24 2 // Cascading member function calls. 3 4 // Time class definition. 5 // Member functions defined in time6.cpp. 6 #ifndef TIME6_H 7 #define TIME6_H 8 9 class Time { 10 11 public: 12 Time( int = 0, int = 0, int = 0 ); // default constructor 13 14 // set functions 15 Time &setTime( int, int, int ); // set hour, minute, second 16 Time &setHour( int ); // set hour 17 Time &setMinute( int ); // set minute 18 Time &setSecond( int ); // set second 19 20 // get functions (normally declared const) 21 int getHour() const; // return hour 22 int getMinute() const; // return minute 23 int getSecond() const; // return second 24 Set functions return reference to Time object to enable cascaded member function calls.
  • 161. 25 // print functions (normally declared const) 26 void printUniversal() const; // print universal time 27 void printStandard() const; // print standard time 28 29 private: 30 int hour; // 0 - 23 (24-hour clock format) 31 int minute; // 0 - 59 32 int second; // 0 - 59 33 34 }; // end class Time 35 36 #endif
  • 162. 1 // Example 25 2 // Member-function definitions for Time class. 3 #include <iostream> 4 5 using std::cout; 6 7 #include <iomanip> 8 9 using std::setfill; 10 using std::setw; 11 12 #include "time6.h" // Time class definition 13 14 // constructor function to initialize private data; 15 // calls member function setTime to set variables; 16 // default values are 0 (see class definition) 17 Time::Time( int hr, int min, int sec ) 18 { 19 setTime( hr, min, sec ); 20 21 } // end Time constructor 22
  • 163. 23 // set values of hour, minute, and second 24 Time &Time::setTime( int h, int m, int s ) 25 { 26 setHour( h ); 27 setMinute( m ); 28 setSecond( s ); 29 30 return *this; // enables cascading 31 32 } // end function setTime 33 34 // set hour value 35 Time &Time::setHour( int h ) 36 { 37 hour = ( h >= 0 && h < 24 ) ? h : 0; 38 39 return *this; // enables cascading 40 41 } // end function setHour 42 Return *this as reference to enable cascaded member function calls. Return *this as reference to enable cascaded member function calls.
  • 164. 43 // set minute value 44 Time &Time::setMinute( int m ) 45 { 46 minute = ( m >= 0 && m < 60 ) ? m : 0; 47 48 return *this; // enables cascading 49 50 } // end function setMinute 51 52 // set second value 53 Time &Time::setSecond( int s ) 54 { 55 second = ( s >= 0 && s < 60 ) ? s : 0; 56 57 return *this; // enables cascading 58 59 } // end function setSecond 60 61 // get hour value 62 int Time::getHour() const 63 { 64 return hour; 65 66 } // end function getHour 67 Return *this as reference to enable cascaded member function calls. Return *this as reference to enable cascaded member function calls.
  • 165. 68 // get minute value 69 int Time::getMinute() const 70 { 71 return minute; 72 73 } // end function getMinute 74 75 // get second value 76 int Time::getSecond() const 77 { 78 return second; 79 80 } // end function getSecond 81 82 // print Time in universal format 83 void Time::printUniversal() const 84 { 85 cout << setfill( '0' ) << setw( 2 ) << hour << ":" 86 << setw( 2 ) << minute << ":" 87 << setw( 2 ) << second; 88 89 } // end function printUniversal 90
  • 166. 91 // print Time in standard format 92 void Time::printStandard() const 93 { 94 cout << ( ( hour == 0 || hour == 12 ) ? 12 : hour % 12 ) 95 << ":" << setfill( '0' ) << setw( 2 ) << minute 96 << ":" << setw( 2 ) << second 97 << ( hour < 12 ? " AM" : " PM" ); 98 99 } // end function printStandard
  • 167. 1 // Example 26 2 // Cascading member function calls with the this pointer. 3 #include <iostream> 4 5 using std::cout; 6 using std::endl; 7 8 #include "time6.h" // Time class definition 9 10 int main() 11 { 12 Time t; 13 14 // cascaded function calls 15 t.setHour( 18 ).setMinute( 30 ).setSecond( 22 ); 16 17 // output time in universal and standard formats 18 cout << "Universal time: "; 19 t.printUniversal(); 20 21 cout << "nStandard time: "; 22 t.printStandard(); 23 24 cout << "nnNew standard time: "; 25 Cascade member function calls; recall dot operator associates from left to right.
  • 168. 26 // cascaded function calls 27 t.setTime( 20, 20, 20 ).printStandard(); 28 29 cout << endl; 30 31 return 0; 32 33 } // end main Universal time: 18:30:22 Standard time: 6:30:22 PM New standard time: 8:20:20 PM Function call to printStandard must appear last; printStandard does not return reference to t.
  • 169. Dynamic Memory Management with Operators new and delete Dynamic memory management Control allocation and deallocation of memory Operators new and delete  Include standard header <new> new Time *timePtr; timePtr = new Time; Creates object of proper size for type Time  Error if no space in memory for object Calls default constructor for object Returns pointer of specified type Providing initializers double *ptr = new double( 3.14159 ); Time *timePtr = new Time( 12, 0, 0 ); Allocating arrays int *gradesArray = new int[ 10 ];
  • 170. Dynamic Memory Management with Operators new and delete  delete  Destroy dynamically allocated object and free space  Consider delete timePtr;  Operator delete  Calls destructor for object  Deallocates memory associated with object Memory can be reused to allocate other objects  Deallocating arrays delete [] gradesArray; Deallocates array to which gradesArray points  If pointer to array of objects  First calls destructor for each object in array  Then deallocates memory
  • 171. static Class Members  static class variable  “Class-wide” data  Property of class, not specific object of class  Efficient when single copy of data is enough  Only the static variable has to be updated  May seem like global variables, but have class scope  Only accessible to objects of same class  Initialized exactly once at file scope  Exist even if no objects of class exist  Can be public, private or protected
  • 172. static Class Members Accessing static class variables  Accessible through any object of class  public static variables  Can also be accessed using binary scope resolution operator(::) Employee::count  private static variables  When no class member objects exist: Can only be accessed via public static member function Employee::getCount() static member functions  Cannot access non-static data or functions  No this pointer for static functions  static data members and static member functions exist independent of objects
  • 173. 1 // Example 26 2 // Employee class definition. 3 #ifndef EMPLOYEE2_H 4 #define EMPLOYEE2_H 5 6 class Employee { 7 8 public: 9 Employee( const char *, const char * ); // constructor 10 ~Employee(); // destructor 11 const char *getFirstName() const; // return first name 12 const char *getLastName() const; // return last name 13 14 // static member function 15 static int getCount(); // return # objects instantiated 16 17 private: 18 char *firstName; 19 char *lastName; 20 21 // static data member 22 static int count; // number of objects instantiated 23 24 }; // end class Employee 25 static member function can only access static data members and member functions. static data member is class-wide data.
  • 174. 1 // Example 27 2 // Member-function definitions for class Employee. 3 #include <iostream> 4 5 using std::cout; 6 using std::endl; 7 8 #include <new> // C++ standard new operator 9 #include <cstring> // strcpy and strlen prototypes 10 11 #include "employee2.h" // Employee class definition 12 13 // define and initialize static data member 14 int Employee::count = 0; 15 16 // define static member function that returns number of 17 // Employee objects instantiated 18 int Employee::getCount() 19 { 20 return count; 21 22 } // end static function getCount Initialize static data member exactly once at file scope. static member function accesses static data member count.
  • 175. 23 24 // constructor dynamically allocates space for 25 // first and last name and uses strcpy to copy 26 // first and last names into the object 27 Employee::Employee( const char *first, const char *last ) 28 { 29 firstName = new char[ strlen( first ) + 1 ]; 30 strcpy( firstName, first ); 31 32 lastName = new char[ strlen( last ) + 1 ]; 33 strcpy( lastName, last ); 34 35 ++count; // increment static count of employees 36 37 cout << "Employee constructor for " << firstName 38 << ' ' << lastName << " called." << endl; 39 40 } // end Employee constructor 41 42 // destructor deallocates dynamically allocated memory 43 Employee::~Employee() 44 { 45 cout << "~Employee() called for " << firstName 46 << ' ' << lastName << endl; 47 new operator dynamically allocates space. Use static data member to store total count of employees.
  • 176. 48 delete [] firstName; // recapture memory 49 delete [] lastName; // recapture memory 50 51 --count; // decrement static count of employees 52 53 } // end destructor ~Employee 54 55 // return first name of employee 56 const char *Employee::getFirstName() const 57 { 58 // const before return type prevents client from modifying 59 // private data; client should copy returned string before 60 // destructor deletes storage to prevent undefined pointer 61 return firstName; 62 63 } // end function getFirstName 64 65 // return last name of employee 66 const char *Employee::getLastName() const 67 { 68 // const before return type prevents client from modifying 69 // private data; client should copy returned string before 70 // destructor deletes storage to prevent undefined pointer 71 return lastName; 72 73 } // end function getLastName Operator delete deallocates memory. Use static data member to store total count of employees.
  • 177. Data Abstraction and Information Hiding  Information hiding  Classes hide implementation details from clients  Example: stack data structure  Data elements added (pushed) onto top  Data elements removed (popped) from top  Last-in, first-out (LIFO) data structure  Client only wants LIFO data structure Does not care how stack implemented  Data abstraction  Describe functionality of class independent of implementation
  • 178. Data Abstraction and Information Hiding  Abstract data types (ADTs)  Approximations/models of real-world concepts and behaviors  int, float are models for a numbers  Data representation  Operations allowed on those data  C++ extensible  Standard data types cannot be changed, but new data types can be created
  • 179. Proxy Classes  Proxy class  Hide implementation details of another class  Knows only public interface of class being hidden  Enables clients to use class’s services without giving access to class’s implementation  Forward class declaration  Used when class definition only uses pointer to another class  Prevents need for including header file  Declares class before referencing  Format: class ClassToLoad;
  • 180. 1 // Example 28 2 // Header file for class Implementation 3 4 class Implementation { 5 6 public: 7 8 // constructor 9 Implementation( int v ) 10 : value( v ) // initialize value with v 11 { 12 // empty body 13 14 } // end Implementation constructor 15 16 // set value to v 17 void setValue( int v ) 18 { 19 value = v; // should validate v 20 21 } // end function setValue 22 public member function. 23 // return value 24 int getValue() const 25 { 26 return value; 27 28 } // end function getValue 29 30 private: 31 int value; 32 33 }; // end class Implementation
  • 181. 1 // Example 29 2 // Header file for interface.cpp 3 4 class Implementation; // forward class declaration 5 6 class Interface { 7 8 public: 9 Interface( int ); 10 void setValue( int ); // same public interface as 11 int getValue() const; // class Implementation 12 ~Interface(); 13 14 private: 15 16 // requires previous forward declaration (line 4) 17 Implementation *ptr; 18 19 }; // end class Interface Provide same public interface as class Implementation; recall setValue and getValue only public member functions. Pointer to Implementation object requires forward class declaration.
  • 182. 1 // Example 30 2 // Definition of class Interface 3 #include "interface.h" // Interface class definition 4 #include "implementation.h" // Implementation class definition 5 6 // constructor 7 Interface::Interface( int v ) 8 : ptr ( new Implementation( v ) ) // initialize ptr 9 { 10 // empty body 11 12 } // end Interface constructor 13 14 // call Implementation's setValue function 15 void Interface::setValue( int v ) 16 { 17 ptr->setValue( v ); 18 19 } // end function setValue 20 Proxy class Interface includes header file for class Implementation. Maintain pointer to underlying Implementation object. Invoke corresponding function on underlying Implementation object.
  • 183. 21 // call Implementation's getValue function 22 int Interface::getValue() const 23 { 24 return ptr->getValue(); 25 26 } // end function getValue 27 28 // destructor 29 Interface::~Interface() 30 { 31 delete ptr; 32 33 } // end destructor ~Interface Invoke corresponding function on underlying Implementation object. Deallocate underlying Implementation object.
  • 184. 1 // Example 30 2 // Hiding a class’s private data with a proxy class. 3 #include <iostream> 4 5 using std::cout; 6 using std::endl; 7 8 #include "interface.h" // Interface class definition 9 10 int main() 11 { 12 Interface i( 5 ); 13 14 cout << "Interface contains: " << i.getValue() 15 << " before setValue" << endl; 16 17 i.setValue( 10 ); 18 19 cout << "Interface contains: " << i.getValue() 20 << " after setValue" << endl; 21 22 return 0; 23 24 } // end main Interface contains: 5 before setValue Interface contains: 10 after setValue Only include proxy class header file. Create object of proxy class Interface; note no mention of Implementation class. Invoke member functions via proxy class object.
  • 185. Fundamentals of Operator Overloading  Use operators with objects (operator overloading)  Clearer than function calls for certain classes  Operator sensitive to context  Types  Built in (int, char) or user-defined  Can use existing operators with user-defined types  Cannot create new operators  Overloading operators  Create a function for the class  Name function operator followed by symbol  Operator+ for the addition operator +
  • 186. Fundamentals of Operator Overloading  Using operators on a class object  It must be overloaded for that class  Exceptions:  Assignment operator, = May be used without explicit overloading Memberwise assignment between objects  Address operator, & May be used on any class without overloading Returns address of object  Both can be overloaded
  • 187. Restrictions on Operator Overloading  Cannot change  How operators act on built-in data types  I.e., cannot change integer addition  Precedence of operator (order of evaluation)  Use parentheses to force order-of-operations  Associativity (left-to-right or right-to-left)  Number of operands  & is unitary, only acts on one operand  Cannot create new operators  Operators must be overloaded explicitly  Overloading + does not overload +=
  • 188. Restrictions on Operator Overloading Operators that cannot be overloaded . .* :: ?: sizeof Operators that can be overloaded + - * / % ^ & | ~ ! = < > += -= *= /= %= ^= &= |= << >> >>= <<= == != <= >= && || ++ -- ->* , -> [] () new delete new[] delete[]
  • 189. Operator Functions As Class Members Vs. As Friend Functions  Operator functions  Member functions  Use this keyword to implicitly get argument  Gets left operand for binary operators (like +)  Leftmost object must be of same class as operator  Non member functions  Need parameters for both operands  Can have object of different class than operator  Must be a friend to access private or protected data  Example Overloaded << operator  Left operand of type ostream &  Such as cout object in cout << classObject  Similarly, overloaded >> needs istream &  Thus, both must be non-member functions
  • 190. Operator Functions As Class Members Vs. As Friend Functions  Commutative operators  May want + to be commutative  So both “a + b” and “b + a” work  Suppose we have two different classes  Overloaded operator can only be member function when its class is on left  HugeIntClass + Long int  Can be member function  When other way, need a non-member overload function  Long int + HugeIntClass
  • 191. Overloading Stream-Insertion and Stream-Extraction Operators  << and >>  Already overloaded to process each built-in type  Can also process a user-defined class  Example program  Class PhoneNumber  Holds a telephone number  Print out formatted number automatically  (123) 456-7890
  • 192. 1 // Example 31 2 // Overloading the stream-insertion and 3 // stream-extraction operators. 4 #include <iostream> 5 6 using std::cout; 7 using std::cin; 8 using std::endl; 9 using std::ostream; 10 using std::istream; 11 12 #include <iomanip> 13 14 using std::setw; 15 16 // PhoneNumber class definition 17 class PhoneNumber { 18 friend ostream &operator<<( ostream&, const PhoneNumber & ); 19 friend istream &operator>>( istream&, PhoneNumber & ); 20 21 private: 22 char areaCode[ 4 ]; // 3-digit area code and null 23 char exchange[ 4 ]; // 3-digit exchange and null 24 char line[ 5 ]; // 4-digit line and null 25 26 }; // end class PhoneNumber Notice function prototypes for overloaded operators >> and << They must be non-member friend functions, since the object of class Phonenumber appears on the right of the operator. cin << object cout >> object
  • 193. 27 28 // overloaded stream-insertion operator; cannot be 29 // a member function if we would like to invoke it with 30 // cout << somePhoneNumber; 31 ostream &operator<<( ostream &output, const PhoneNumber &num ) 32 { 33 output << "(" << num.areaCode << ") " 34 << num.exchange << "-" << num.line; 35 36 return output; // enables cout << a << b << c; 37 38 } // end function operator<< 39 40 // overloaded stream-extraction operator; cannot be 41 // a member function if we would like to invoke it with 42 // cin >> somePhoneNumber; 43 istream &operator>>( istream &input, PhoneNumber &num ) 44 { 45 input.ignore(); // skip ( 46 input >> setw( 4 ) >> num.areaCode; // input area code 47 input.ignore( 2 ); // skip ) and space 48 input >> setw( 4 ) >> num.exchange; // input exchange 49 input.ignore(); // skip dash (-) 50 input >> setw( 5 ) >> num.line; // input line 51 52 return input; // enables cin >> a >> b >> c; The expression: cout << phone; is interpreted as the function call: operator<<(cout, phone); output is an alias for cout. This allows objects to be cascaded. cout << phone1 << phone2; first calls operator<<(cout, phone1), and returns cout. Next, cout << phone2 executes. Stream manipulator setw restricts number of characters read. setw(4) allows 3 characters to be read, leaving room for the null character.
  • 194. 53 54 } // end function operator>> 55 56 int main() 57 { 58 PhoneNumber phone; // create object phone 59 60 cout << "Enter phone number in the form (123) 456-7890:n"; 61 62 // cin >> phone invokes operator>> by implicitly issuing 63 // the non-member function call operator>>( cin, phone ) 64 cin >> phone; 65 66 cout << "The phone number entered was: " ; 67 68 // cout << phone invokes operator<< by implicitly issuing 69 // the non-member function call operator<<( cout, phone ) 70 cout << phone << endl; 71 72 return 0; 73 74 } // end main Enter phone number in the form (123) 456-7890: (800) 555-1212 The phone number entered was: (800) 555-1212
  • 195. Overloading Unary Operators  Overloading unary operators  Non-static member function, no arguments  Non-member function, one argument  Argument must be class object or reference to class object  Remember, static functions only access static data
  • 196. Overloading Operators Overloading unary operators (! to test for empty string)  Non-static member function: !s becomes s.operator!() bool operator!() const;  Non-member function:!s becomes operator!(s) friend bool operator!( const String & ) Overloading binary operators  Non-member function (arg. must be class object or reference) friend const String &operator+=(String &, const String & );  Non-static member function: const String &operator+=( const String & );  y += z equivalent to y.operator+=( z )
  • 197. Case Study: Array class  Arrays in C++  No range checking  Cannot be compared meaningfully with ==  No array assignment (array names const pointers)  Cannot input/output entire arrays at once  Example:Implement an Array class with  Range checking  Array assignment  Arrays that know their size  Outputting/inputting entire arrays with << and >>  Array comparisons with == and !=
  • 198. Case Study: Array class  Copy constructor  Used whenever copy of object needed  Passing by value (return value or parameter)  Initializing an object with a copy of another Array newArray( oldArray ); newArray copy of oldArray  Prototype for class Array  Array( const Array & );  Must take reference Otherwise, pass by value Tries to make copy by calling copy constructor… Infinite loop
  • 199. 1 // Example 32 2 // Array class for storing arrays of integers. 3 #ifndef ARRAY1_H 4 #define ARRAY1_H 5 6 #include <iostream> 7 8 using std::ostream; 9 using std::istream; 10 11 class Array { 12 friend ostream &operator<<( ostream &, const Array & ); 13 friend istream &operator>>( istream &, Array & ); 14 15 public: 16 Array( int = 10 ); // default constructor 17 Array( const Array & ); // copy constructor 18 ~Array(); // destructor 19 int getSize() const; // return size 20 21 // assignment operator 22 const Array &operator=( const Array & ); 23 24 // equality operator 25 bool operator==( const Array & ) const; 26 Most operators overloaded as member functions (except << and >>, which must be non- member functions). Prototype for copy constructor.
  • 200. 27 // inequality operator; returns opposite of == operator 28 bool operator!=( const Array &right ) const 29 { 30 return ! ( *this == right ); // invokes Array::operator== 31 32 } // end function operator!= 33 34 // subscript operator for non-const objects returns lvalue 35 int &operator[]( int ); 36 37 // subscript operator for const objects returns rvalue 38 const int &operator[]( int ) const; 39 40 private: 41 int size; // array size 42 int *ptr; // pointer to first element of array 43 44 }; // end class Array 45 46 #endif != operator simply returns opposite of == operator. Thus, only need to define the == operator.
  • 201. 1 // Example 33 2 // Member function definitions for class Array 3 #include <iostream> 4 5 using std::cout; 6 using std::cin; 7 using std::endl; 8 9 #include <iomanip> 10 11 using std::setw; 12 13 #include <new> // C++ standard "new" operator 14 15 #include <cstdlib> // exit function prototype 16 17 #include "array1.h" // Array class definition 18 19 // default constructor for class Array (default size 10) 20 Array::Array( int arraySize ) 21 { 22 // validate arraySize 23 size = ( arraySize > 0 ? arraySize : 10 ); 24 25 ptr = new int[ size ]; // create space for array 26
  • 202. 27 for ( int i = 0; i < size; i++ ) 28 ptr[ i ] = 0; // initialize array 29 30 } // end Array default constructor 31 32 // copy constructor for class Array; 33 // must receive a reference to prevent infinite recursion 34 Array::Array( const Array &arrayToCopy ) 35 : size( arrayToCopy.size ) 36 { 37 ptr = new int[ size ]; // create space for array 38 39 for ( int i = 0; i < size; i++ ) 40 ptr[ i ] = arrayToCopy.ptr[ i ]; // copy into object 41 42 } // end Array copy constructor 43 44 // destructor for class Array 45 Array::~Array() 46 { 47 delete [] ptr; // reclaim array space 48 49 } // end destructor 50 We must declare a new integer array so the objects do not point to the same memory.
  • 203. 51 // return size of array 52 int Array::getSize() const 53 { 54 return size; 55 56 } // end function getSize 57 58 // overloaded assignment operator; 59 // const return avoids: ( a1 = a2 ) = a3 60 const Array &Array::operator=( const Array &right ) 61 { 62 if ( &right != this ) { // check for self-assignment 63 64 // for arrays of different sizes, deallocate original 65 // left-side array, then allocate new left-side array 66 if ( size != right.size ) { 67 delete [] ptr; // reclaim space 68 size = right.size; // resize this object 69 ptr = new int[ size ]; // create space for array copy 70 71 } // end inner if 72 73 for ( int i = 0; i < size; i++ ) 74 ptr[ i ] = right.ptr[ i ]; // copy array into object 75 76 } // end outer if Want to avoid self-assignment.
  • 204. 77 78 return *this; // enables x = y = z, for example 79 80 } // end function operator= 81 82 // determine if two arrays are equal and 83 // return true, otherwise return false 84 bool Array::operator==( const Array &right ) const 85 { 86 if ( size != right.size ) 87 return false; // arrays of different sizes 88 89 for ( int i = 0; i < size; i++ ) 90 91 if ( ptr[ i ] != right.ptr[ i ] ) 92 return false; // arrays are not equal 93 94 return true; // arrays are equal 95 96 } // end function operator== 97
  • 205. 98 // overloaded subscript operator for non-const Arrays 99 // reference return creates an lvalue 100 int &Array::operator[]( int subscript ) 101 { 102 // check for subscript out of range error 103 if ( subscript < 0 || subscript >= size ) { 104 cout << "nError: Subscript " << subscript 105 << " out of range" << endl; 106 107 exit( 1 ); // terminate program; subscript out of range 108 109 } // end if 110 111 return ptr[ subscript ]; // reference return 112 113 } // end function operator[] 114 integers1[5] calls integers1.operator[]( 5 ) exit() (header <cstdlib>) ends the program.
  • 206. 115 // overloaded subscript operator for const Arrays 116 // const reference return creates an rvalue 117 const int &Array::operator[]( int subscript ) const 118 { 119 // check for subscript out of range error 120 if ( subscript < 0 || subscript >= size ) { 121 cout << "nError: Subscript " << subscript 122 << " out of range" << endl; 123 124 exit( 1 ); // terminate program; subscript out of range 125 126 } // end if 127 128 return ptr[ subscript ]; // const reference return 129 130 } // end function operator[] 131 132 // overloaded input operator for class Array; 133 // inputs values for entire array 134 istream &operator>>( istream &input, Array &a ) 135 { 136 for ( int i = 0; i < a.size; i++ ) 137 input >> a.ptr[ i ]; 138 139 return input; // enables cin >> x >> y; 140 141 } // end function
  • 207. 142 143 // overloaded output operator for class Array 144 ostream &operator<<( ostream &output, const Array &a ) 145 { 146 int i; 147 148 // output private ptr-based array 149 for ( i = 0; i < a.size; i++ ) { 150 output << setw( 12 ) << a.ptr[ i ]; 151 152 if ( ( i + 1 ) % 4 == 0 ) // 4 numbers per row of output 153 output << endl; 154 155 } // end for 156 157 if ( i % 4 != 0 ) // end last line of output 158 output << endl; 159 160 return output; // enables cout << x << y; 161 162 } // end function operator<<
  • 208. Converting between Types  Cast operator (conversion operator)  Convert from One class to another built-in type  Must be non-static member function - Cannot be friend  Do not specify return type Implicitly returns type to which you are converting  Example: A::operator char *() const;  Casts class A to a temporary char *  (char *)s calls s.operator char*() A::operator int() const; A::operator OtherClass() const;  Casting can prevent need for overloading  Suppose class String can be cast to char *  cout << s; // cout expects char *; s is a String  Compiler implicitly calls the function to convert s to char *  Do not have to overload << for String
  • 209. Case Study: A String Class  Build class String  String creation, manipulation  Class string in standard library (more Chapter 15)  Conversion constructor  Single-argument constructor  Turns objects of other types into class objects  String s1(“hi”);  Creates a String from a char *  Any single-argument constructor is a conversion constructor
  • 210. Overloading ++ and --  Increment/decrement operators can be overloaded  Add 1 to a Date object, d1  Prototype (member function)  Date &operator++();  ++d1 same as d1.operator++()  Prototype (non-member)  Friend Date &operator++( Date &);  ++d1 same as operator++( d1 )
  • 211. Overloading ++ and --  To distinguish pre/post increment  Post increment has a dummy parameter  int of 0  Prototype (member function)  Date operator++( int );  d1++ same as d1.operator++( 0 )  Prototype (non-member)  friend Date operator++( Data &, int );  d1++ same as operator++( d1, 0 )  Integer parameter does not have a name  Not even in function definition
  • 212. Overloading ++ and --  Return values  Preincrement  Returns by reference (Date &)  lvalue (can be assigned)  Postincrement  Returns by value  Returns temporary object with old value  rvalue (cannot be on left side of assignment)  Example Date class  Overloaded increment operator  Change day, month and year  Overloaded += operator  Function to test for leap years  Function to determine if day is last of month
  • 213. 1 // Example 34 2 // Date class definition. 3 #ifndef DATE1_H 4 #define DATE1_H 5 #include <iostream> 6 7 using std::ostream; 8 9 class Date { 10 friend ostream &operator<<( ostream &, const Date & ); 11 12 public: 13 Date( int m = 1, int d = 1, int y = 1900 ); // constructor 14 void setDate( int, int, int ); // set the date 15 16 Date &operator++(); // preincrement operator 17 Date operator++( int ); // postincrement operator 18 19 const Date &operator+=( int ); // add days, modify object 20 21 bool leapYear( int ) const; // is this a leap year? 22 bool endOfMonth( int ) const; // is this end of month? Note difference between pre and post increment.
  • 214. 23 24 private: 25 int month; 26 int day; 27 int year; 28 29 static const int days[]; // array of days per month 30 void helpIncrement(); // utility function 31 32 }; // end class Date 33 34 #endif 35 Date &Date::operator++() 36 { 37 helpIncrement(); 37 return *this; // reference return to create an lvalue 39 } // end function operator++ 40 41 // overloaded postincrement operator; note that the dummy 42 // integer parameter does not have a parameter name 43 Date Date::operator++( int ) 44 { 45 Date temp = *this; // hold current state of object 46 helpIncrement(); 48 // return unincremented, saved, temporary object 49 return temp; // value return; not a reference return 51 } // end function operator++
  • 215. Inheritance  Inheritance  Software reusability  Create new class from existing class  Absorb existing class’s data and behaviors  Enhance with new capabilities  Derived class inherits from base class  Derived class More specialized group of objects Behaviors inherited from base class  Can customize Additional behaviors
  • 216. Inheritance  Class hierarchy  Direct base class  Inherited explicitly (one level up hierarchy)  Indirect base class  Inherited two or more levels up hierarchy  Single inheritance  Inherits from one base class  Multiple inheritance  Inherits from multiple base classes Base classes possibly unrelated  Chapter 22
  • 217. Inheritance  Three types of inheritance  public  Every object of derived class also object of base class Base-class objects not objects of derived classes Example: All cars vehicles, but not all vehicles cars  Can access non-private members of base class Derived class can effect change to private base-class members  Through inherited non-private member functions  private  Alternative to composition  Chapter 17  protected  Rarely used
  • 218. Inheritance  Abstraction  Focus on commonalities among objects in system  “is-a” vs. “has-a”  “is-a”  Inheritance  Derived class object treated as base class object  Example: Car is a vehicle Vehicle properties/behaviors also car properties/behaviors  “has-a”  Composition  Object contains one or more objects of other classes as members  Example: Car has a steering wheel
  • 219. Base Classes and Derived Classes  Base classes and derived classes  Object of one class “is an” object of another class  Example: Rectangle is quadrilateral.  Base class typically represents larger set of objects than derived classes  Example: Base class: Vehicle  Cars, trucks, boats, bicycles, … Derived class: Car  Smaller, more-specific subset of vehicles
  • 220. Base Classes and Derived Classes  Inheritance examples Base class Derived classes Student GraduateStudent UndergraduateStudent Shape Circle Triangle Rectangle Loan CarLoan HomeImprovementLoan MortgageLoan Employee FacultyMember StaffMember Account CheckingAccount SavingsAccount
  • 221. Base Classes and Derived Classes  Inheritance hierarchy  Inheritance relationships: tree-like hierarchy structure  Each class becomes  Base class Supply data/behaviors to other classes OR  Derived class Inherit data/behaviors from other classes
  • 223. Shape TwoDimensionalShape ThreeDimensionalShape Circle Square Triangle Sphere Cube Tetrahedron Fig. 9.3 Inheritance hierarchy for Shapes. Inheritance hierarchy
  • 224. Base Classes and Derived Classes  public inheritance  Specify with: Class TwoDimensionalShape : public Shape  Class TwoDimensionalShape inherits from class Shape  Base class private members  Not accessible directly  Still inherited - manipulate through inherited member functions  Base class public and protected members  Inherited with original member access  friend functions  Not inherited
  • 225. protected Members  protected access  Intermediate level of protection between public and private  protected members accessible to  Base class members  Base class friends  Derived class members  Derived class friends  Derived-class members  Refer to public and protected members of base class Simply use member names
  • 226. Relationship between Base Classes and Derived Classes  Base class and derived class relationship  Example: Point/circle inheritance hierarchy  Point x-y coordinate pair  Circle x-y coordinate pair Radius
  • 227. Relationship between Base Classes and Derived Classes  Using protected data members  Advantages  Derived classes can modify values directly  Slight increase in performance Avoid set/get function call overhead  Disadvantages  No validity checking Derived class can assign illegal value  Implementation dependent Derived class member functions more likely dependent on base class implementation Base class implementation changes may result in derived class modifications  Fragile (brittle) software
  • 228. Case Study: Three-Level Inheritance Hierarchy  Three level point/circle/cylinder hierarchy  Point  x-y coordinate pair  Circle  x-y coordinate pair  Radius  Cylinder  x-y coordinate pair  Radius  Height
  • 229. Constructors and Destructors in Derived Classes  Instantiating derived-class object  Chain of constructor calls  Derived-class constructor invokes base class constructor Implicitly or explicitly  Base of inheritance hierarchy Last constructor called in chain First constructor body to finish executing Example: Point3/Circle4/Cylinder hierarchy  Point3 constructor called last  Point3 constructor body finishes execution first  Initializing data members Each base-class constructor initializes data members inherited by derived class
  • 230. Constructors and Destructors in Derived Classes  Destroying derived-class object  Chain of destructor calls  Reverse order of constructor chain  Destructor of derived-class called first  Destructor of next base class up hierarchy next Continue up hierarchy until final base reached  After final base-class destructor, object removed from memory  Base-class constructors, destructors, assignment operators  Not inherited by derived classes  Derived class constructors, assignment operators can call  Constructors  Assignment operators
  • 231. public, protected and private Inheritance Type of inheritanceBase class member access specifier public inheritance protected inheritance private inheritance Public public in derived class. Can be accessed directly by any non-static member functions, friend functions and non- member functions. protected in derived class. Can be accessed directly by all non-static member functions and friend functions. private in derived class. Can be accessed directly by all non-static member functions and friend functions. Protected protected in derived class. Can be accessed directly by all non-static member functions and friend functions. protected in derived class. Can be accessed directly by all non-static member functions and friend functions. private in derived class. Can be accessed directly by all non-static member functions and friend functions. Private Hidden in derived class. Can be accessed by non-static member functions and friend functions through public or protected member functions of the base class. Hidden in derived class. Can be accessed by non-static member functions and friend functions through public or protected member functions of the base class. Hidden in derived class. Can be accessed by non-static member functions and friend functions through public or protected member functions of the base class.
  • 232. 1 // Example 35 2 // Point class definition represents an x-y coordinate pair. 3 #ifndef POINT_H 4 #define POINT_H 5 6 class Point { 7 8 public: 9 Point( int = 0, int = 0 ); // default constructor 10 11 void setX( int ); // set x in coordinate pair 12 int getX() const; // return x from coordinate pair 13 14 void setY( int ); // set y in coordinate pair 15 int getY() const; // return y from coordinate pair 16 17 void print() const; // output Point object 18 19 private: 20 int x; // x part of coordinate pair 21 int y; // y part of coordinate pair 22 23 }; // end class Point 24 25 #endif Maintain x- and y- coordinates as private data members.
  • 233. 1 // Example 36 2 // Circle2 class contains x-y coordinate pair and radius. 3 #ifndef CIRCLE2_H 4 #define CIRCLE2_H 5 6 #include "point.h" // Point class definition 7 8 class Circle2 : public Point { 9 10 public: 11 12 // default constructor 13 Circle2( int = 0, int = 0, double = 0.0 ); 14 15 void setRadius( double ); // set radius 16 double getRadius() const; // return radius 17 18 double getDiameter() const; // return diameter 19 double getCircumference() const; // return circumference 20 double getArea() const; // return area 21 22 void print() const; // output Circle2 object 23 24 private: 25 double radius; // Circle2's radius Class Circle2 inherits from class Point. Maintain private data member radius. Colon indicates inheritance.Keyword public indicates type of inheritance.
  • 234. 26 27 }; // end class Circle2 28 29 #endif 1 // Fig. 9.11: circle2.cpp 2 // Circle2 class member-function definitions. 3 #include <iostream> 4 5 using std::cout; 6 7 #include "circle2.h" // Circle2 class definition 8 9 // default constructor 10 Circle2::Circle2( int xValue, int yValue, double radiusValue ) 11 { 12 x = xValue; 13 y = yValue; 14 setRadius( radiusValue ); 15 16 } // end Circle2 constructor 17 Attempting to access base class Point’s private data members x and y results in syntax errors.
  • 235. 18 // set radius 19 void Circle2::setRadius( double radiusValue ) 20 { 21 radius = ( radiusValue < 0.0 ? 0.0 : radiusValue ); 22 23 } // end function setRadius 24 25 // return radius 26 double Circle2::getRadius() const 27 { 28 return radius; 29 30 } // end function getRadius 31 32 // calculate and return diameter 33 double Circle2::getDiameter() const 34 { 35 return 2 * radius; 36 37 } // end function getDiameter 38
  • 236. 39 // calculate and return circumference 40 double Circle2::getCircumference() const 41 { 42 return 3.14159 * getDiameter(); 43 44 } // end function getCircumference 45 46 // calculate and return area 47 double Circle2::getArea() const 48 { 49 return 3.14159 * radius * radius; 50 51 } // end function getArea 52 53 // output Circle2 object 54 void Circle2::print() const 55 { 56 cout << "Center = [" << x << ", " << y << ']' 57 << "; Radius = " << radius; 58 59 } // end function print Attempting to access base class Point’s private data members x and y results in syntax errors.
  • 237. 1 // Example 37 2 // Point class definition represents an x-y coordinate pair. 3 #ifndef POINT_H 4 #define POINT_H 5 6 class Point { 7 8 public: 9 Point( int = 0, int = 0 ); // default constructor 10 11 void setX( int ); // set x in coordinate pair 12 int getX() const; // return x from coordinate pair 13 14 void setY( int ); // set y in coordinate pair 15 int getY() const; // return y from coordinate pair 16 17 void print() const; // output Point object 18 19 private: 20 int x; // x part of coordinate pair 21 int y; // y part of coordinate pair 22 23 }; // end class Point 24 25 #endif Maintain x- and y- coordinates as private data members.
  • 238. 1 // Example 38 2 // Point class member-function definitions. 3 #include <iostream> 4 5 using std::cout; 6 7 #include "point.h" // Point class definition 8 9 // default constructor 10 Point::Point( int xValue, int yValue ) 11 { 12 x = xValue; 13 y = yValue; 14 15 } // end Point constructor 16 17 // set x in coordinate pair 18 void Point::setX( int xValue ) 19 { 20 x = xValue; // no need for validation 21 22 } // end function setX 23
  • 239. 24 // return x from coordinate pair 25 int Point::getX() const 26 { 27 return x; 28 29 } // end function getX 30 31 // set y in coordinate pair 32 void Point::setY( int yValue ) 33 { 34 y = yValue; // no need for validation 35 36 } // end function setY 37 38 // return y from coordinate pair 39 int Point::getY() const 40 { 41 return y; 42 43 } // end function getY 44
  • 240. 45 // output Point object 46 void Point::print() const 47 { 48 cout << '[' << x << ", " << y << ']'; 49 50 } // end function print
  • 241. 1 // Example 39 2 // Testing class Point. 3 #include <iostream> 4 5 using std::cout; 6 using std::endl; 7 8 #include "point.h" // Point class definition 9 10 int main() 11 { 12 Point point( 72, 115 ); // instantiate Point object 13 14 // display point coordinates 15 cout << "X coordinate is " << point.getX() 16 << "nY coordinate is " << point.getY(); 17 18 point.setX( 10 ); // set x-coordinate 19 point.setY( 10 ); // set y-coordinate 20 21 // display new point value 22 cout << "nnThe new location of point is "; 23 point.print(); 24 cout << endl; 25 Create a Point object. Invoke set functions to modify private data. Invoke public function print to display new coordinates.
  • 242. 26 return 0; // indicates successful termination 27 28 } // end main X coordinate is 72 Y coordinate is 115 The new location of point is [10, 10]
  • 243. 1 // Example 40 2 // Circle class contains x-y coordinate pair and radius. 3 #ifndef CIRCLE_H 4 #define CIRCLE_H 5 6 class Circle { 7 8 public: 9 10 // default constructor 11 Circle( int = 0, int = 0, double = 0.0 ); 12 13 void setX( int ); // set x in coordinate pair 14 int getX() const; // return x from coordinate pair 15 16 void setY( int ); // set y in coordinate pair 17 int getY() const; // return y from coordinate pair 18 19 void setRadius( double ); // set radius 20 double getRadius() const; // return radius 21 22 double getDiameter() const; // return diameter 23 double getCircumference() const; // return circumference 24 double getArea() const; // return area 25 Note code similar to Point code.
  • 244. 26 void print() const; // output Circle object 27 28 private: 29 int x; // x-coordinate of Circle's center 30 int y; // y-coordinate of Circle's center 31 double radius; // Circle's radius 32 33 }; // end class Circle 34 35 #endif Maintain x-y coordinates and radius as private data members. Note code similar to Point code.
  • 245. 1 // Example 41 2 // Circle class member-function definitions. 3 #include <iostream> 4 5 using std::cout; 6 7 #include "circle.h" // Circle class definition 8 9 // default constructor 10 Circle::Circle( int xValue, int yValue, double radiusValue ) 11 { 12 x = xValue; 13 y = yValue; 14 setRadius( radiusValue ); 15 16 } // end Circle constructor 17 18 // set x in coordinate pair 19 void Circle::setX( int xValue ) 20 { 21 x = xValue; // no need for validation 22 23 } // end function setX 24
  • 246. 25 // return x from coordinate pair 26 int Circle::getX() const 27 { 28 return x; 29 30 } // end function getX 31 32 // set y in coordinate pair 33 void Circle::setY( int yValue ) 34 { 35 y = yValue; // no need for validation 36 37 } // end function setY 38 39 // return y from coordinate pair 40 int Circle::getY() const 41 { 42 return y; 43 44 } // end function getY 45
  • 247. 46 // set radius 47 void Circle::setRadius( double radiusValue ) 48 { 49 radius = ( radiusValue < 0.0 ? 0.0 : radiusValue ); 50 51 } // end function setRadius 52 53 // return radius 54 double Circle::getRadius() const 55 { 56 return radius; 57 58 } // end function getRadius 59 60 // calculate and return diameter 61 double Circle::getDiameter() const 62 { 63 return 2 * radius; 64 65 } // end function getDiameter 66 Ensure non-negative value for radius.
  • 248. 67 // calculate and return circumference 68 double Circle::getCircumference() const 69 { 70 return 3.14159 * getDiameter(); 71 72 } // end function getCircumference 73 74 // calculate and return area 75 double Circle::getArea() const 76 { 77 return 3.14159 * radius * radius; 78 79 } // end function getArea 80 81 // output Circle object 82 void Circle::print() const 83 { 84 cout << "Center = [" << x << ", " << y << ']' 85 << "; Radius = " << radius; 86 87 } // end function print
  • 249. 1 // Example 42 2 // Testing class Circle. 3 #include <iostream> 4 5 using std::cout; 6 using std::endl; 7 using std::fixed; 8 9 #include <iomanip> 10 11 using std::setprecision; 12 13 #include "circle.h" // Circle class definition 14 15 int main() 16 { 17 Circle circle( 37, 43, 2.5 ); // instantiate Circle object 18 19 // display point coordinates 20 cout << "X coordinate is " << circle.getX() 21 << "nY coordinate is " << circle.getY() 22 << "nRadius is " << circle.getRadius(); 23 Create Circle object.
  • 250. 24 circle.setX( 2 ); // set new x-coordinate 25 circle.setY( 2 ); // set new y-coordinate 26 circle.setRadius( 4.25 ); // set new radius 27 28 // display new point value 29 cout << "nnThe new location and radius of circle aren"; 30 circle.print(); 31 32 // display floating-point values with 2 digits of precision 33 cout << fixed << setprecision( 2 ); 34 35 // display Circle's diameter 36 cout << "nDiameter is " << circle.getDiameter(); 37 38 // display Circle's circumference 39 cout << "nCircumference is " << circle.getCircumference(); 40 41 // display Circle's area 42 cout << "nArea is " << circle.getArea(); 43 44 cout << endl; 45 46 return 0; // indicates successful termination 47 48 } // end main Use set functions to modify private data. Invoke public function print to display new coordinates.
  • 251. X coordinate is 37 Y coordinate is 43 Radius is 2.5 The new location and radius of circle are Center = [2, 2]; Radius = 4.25 Diameter is 8.50 Circumference is 26.70 Area is 56.74
  • 252. 1 // Example 43 2 // Circle2 class contains x-y coordinate pair and radius. 3 #ifndef CIRCLE2_H 4 #define CIRCLE2_H 5 6 #include "point.h" // Point class definition 7 8 class Circle2 : public Point { 9 10 public: 11 12 // default constructor 13 Circle2( int = 0, int = 0, double = 0.0 ); 14 15 void setRadius( double ); // set radius 16 double getRadius() const; // return radius 17 18 double getDiameter() const; // return diameter 19 double getCircumference() const; // return circumference 20 double getArea() const; // return area 21 22 void print() const; // output Circle2 object 23 24 private: 25 double radius; // Circle2's radius Class Circle2 inherits from class Point. Maintain private data member radius. Colon indicates inheritance.Keyword public indicates type of inheritance.
  • 253. 26 27 }; // end class Circle2 28 29 #endif 1 // Fig. 9.11: circle2.cpp 2 // Circle2 class member-function definitions. 3 #include <iostream> 4 5 using std::cout; 6 7 #include "circle2.h" // Circle2 class definition 8 9 // default constructor 10 Circle2::Circle2( int xValue, int yValue, double radiusValue ) 11 { 12 x = xValue; 13 y = yValue; 14 setRadius( radiusValue ); 15 16 } // end Circle2 constructor 17 Attempting to access base class Point’s private data members x and y results in syntax errors.
  • 254. 18 // set radius 19 void Circle2::setRadius( double radiusValue ) 20 { 21 radius = ( radiusValue < 0.0 ? 0.0 : radiusValue ); 22 23 } // end function setRadius 24 25 // return radius 26 double Circle2::getRadius() const 27 { 28 return radius; 29 30 } // end function getRadius 31 32 // calculate and return diameter 33 double Circle2::getDiameter() const 34 { 35 return 2 * radius; 36 37 } // end function getDiameter 38
  • 255. 39 // calculate and return circumference 40 double Circle2::getCircumference() const 41 { 42 return 3.14159 * getDiameter(); 43 44 } // end function getCircumference 45 46 // calculate and return area 47 double Circle2::getArea() const 48 { 49 return 3.14159 * radius * radius; 50 51 } // end function getArea 52 53 // output Circle2 object 54 void Circle2::print() const 55 { 56 cout << "Center = [" << x << ", " << y << ']' 57 << "; Radius = " << radius; 58 59 } // end function print Attempting to access base class Point’s private data members x and y results in syntax errors.
  • 256. C:cpphtp4examplesch09CircleTestcircle2.cpp(12) : error C2248: 'x' : cannot access private member declared in class 'Point' C:cpphtp4examplesch09circletestpoint.h(20) : see declaration of 'x' C:cpphtp4examplesch09CircleTestcircle2.cpp(13) : error C2248: 'y' : cannot access private member declared in class 'Point' C:cpphtp4examplesch09circletestpoint.h(21) : see declaration of 'y' C:cpphtp4examplesch09CircleTestcircle2.cpp(56) : error C2248: 'x' : cannot access private member declared in class 'Point' C:cpphtp4examplesch09circletestpoint.h(20) : see declaration of 'x' C:cpphtp4examplesch09CircleTestcircle2.cpp(56) : error C2248: 'y' : cannot access private member declared in class 'Point' C:cpphtp4examplesch09circletestpoint.h(21) : see declaration of 'y' Attempting to access base class Point’s private data members x and y results in syntax errors.
  • 257. 1 // Example 44 2 // Point2 class definition represents an x-y coordinate pair. 3 #ifndef POINT2_H 4 #define POINT2_H 5 6 class Point2 { 7 8 public: 9 Point2( int = 0, int = 0 ); // default constructor 10 11 void setX( int ); // set x in coordinate pair 12 int getX() const; // return x from coordinate pair 13 14 void setY( int ); // set y in coordinate pair 15 int getY() const; // return y from coordinate pair 16 17 void print() const; // output Point2 object 18 19 protected: 20 int x; // x part of coordinate pair 21 int y; // y part of coordinate pair 22 23 }; // end class Point2 24 25 #endif Maintain x- and y- coordinates as protected data, accessible to derived classes.
  • 258. 1 // Example 45 2 // Point2 class member-function definitions. 3 #include <iostream> 4 5 using std::cout; 6 7 #include "point2.h" // Point2 class definition 8 9 // default constructor 10 Point2::Point2( int xValue, int yValue ) 11 { 12 x = xValue; 13 y = yValue; 14 15 } // end Point2 constructor 16 17 // set x in coordinate pair 18 void Point2::setX( int xValue ) 19 { 20 x = xValue; // no need for validation 21 22 } // end function setX 23
  • 259. 24 // return x from coordinate pair 25 int Point2::getX() const 26 { 27 return x; 28 29 } // end function getX 30 31 // set y in coordinate pair 32 void Point2::setY( int yValue ) 33 { 34 y = yValue; // no need for validation 35 36 } // end function setY 37 38 // return y from coordinate pair 39 int Point2::getY() const 40 { 41 return y; 42 43 } // end function getY 44
  • 260. 45 // output Point2 object 46 void Point2::print() const 47 { 48 cout << '[' << x << ", " << y << ']'; 49 50 } // end function print
  • 261. 1 // Example 46 2 // Circle3 class contains x-y coordinate pair and radius. 3 #ifndef CIRCLE3_H 4 #define CIRCLE3_H 5 6 #include "point2.h" // Point2 class definition 7 8 class Circle3 : public Point2 { 9 10 public: 11 12 // default constructor 13 Circle3( int = 0, int = 0, double = 0.0 ); 14 15 void setRadius( double ); // set radius 16 double getRadius() const; // return radius 17 18 double getDiameter() const; // return diameter 19 double getCircumference() const; // return circumference 20 double getArea() const; // return area 21 22 void print() const; // output Circle3 object 23 24 private: 25 double radius; // Circle3's radius Class Circle3 inherits from class Point2. Maintain private data member radius.
  • 262. 26 27 }; // end class Circle3 28 29 #endif
  • 263. 1 // Example 47 2 // Circle3 class member-function definitions. 3 #include <iostream> 4 5 using std::cout; 6 7 #include "circle3.h" // Circle3 class definition 8 9 // default constructor 10 Circle3::Circle3( int xValue, int yValue, double radiusValue ) 11 { 12 x = xValue; 13 y = yValue; 14 setRadius( radiusValue ); 15 16 } // end Circle3 constructor 17 18 // set radius 19 void Circle3::setRadius( double radiusValue ) 20 { 21 radius = ( radiusValue < 0.0 ? 0.0 : radiusValue ); 22 23 } // end function setRadius 24 Modify inherited data members x and y, declared protected in base class Point2. Constructor first implicitly calls base class’s default constructor.
  • 264. 25 // return radius 26 double Circle3::getRadius() const 27 { 28 return radius; 29 30 } // end function getRadius 31 32 // calculate and return diameter 33 double Circle3::getDiameter() const 34 { 35 return 2 * radius; 36 37 } // end function getDiameter 38 39 // calculate and return circumference 40 double Circle3::getCircumference() const 41 { 42 return 3.14159 * getDiameter(); 43 44 } // end function getCircumference 45
  • 265. 46 // calculate and return area 47 double Circle3::getArea() const 48 { 49 return 3.14159 * radius * radius; 50 51 } // end function getArea 52 53 // output Circle3 object 54 void Circle3::print() const 55 { 56 cout << "Center = [" << x << ", " << y << ']' 57 << "; Radius = " << radius; 58 59 } // end function print Access inherited data members x and y, declared protected in base class Point2.
  • 266. 1 // Example 48 2 // Testing class Circle3. 3 #include <iostream> 4 5 using std::cout; 6 using std::endl; 7 using std::fixed; 8 9 #include <iomanip> 10 11 using std::setprecision; 12 13 #include "circle3.h" // Circle3 class definition 14 15 int main() 16 { 17 Circle3 circle( 37, 43, 2.5 ); // instantiate Circle3 object 18 19 // display point coordinates 20 cout << "X coordinate is " << circle.getX() 21 << "nY coordinate is " << circle.getY() 22 << "nRadius is " << circle.getRadius(); 23 Use inherited get functions to access inherited protected data x and y. Create Circle3 object. Use Circle3 get function to access private data radius.
  • 267. 24 circle.setX( 2 ); // set new x-coordinate 25 circle.setY( 2 ); // set new y-coordinate 26 circle.setRadius( 4.25 ); // set new radius 27 28 // display new point value 29 cout << "nnThe new location and radius of circle aren"; 30 circle.print(); 31 32 // display floating-point values with 2 digits of precision 33 cout << fixed << setprecision( 2 ); 34 35 // display Circle3's diameter 36 cout << "nDiameter is " << circle.getDiameter(); 37 38 // display Circle3's circumference 39 cout << "nCircumference is " << circle.getCircumference(); 40 41 // display Circle3's area 42 cout << "nArea is " << circle.getArea(); 43 44 cout << endl; 45 46 return 0; // indicates successful termination 47 48 } // end main Use inherited set functions to modify inherited protected data x and y. Use Circle3 set function to modify private data radius.
  • 268. X coordinate is 37 Y coordinate is 43 Radius is 2.5 The new location and radius of circle are Center = [2, 2]; Radius = 4.25 Diameter is 8.50 Circumference is 26.70 Area is 56.74
  • 269. Relationship between Base Classes and Derived Classes  Using protected data members  Advantages  Derived classes can modify values directly  Slight increase in performance Avoid set/get function call overhead  Disadvantages  No validity checking Derived class can assign illegal value  Implementation dependent Derived class member functions more likely dependent on base class implementation Base class implementation changes may result in derived class modifications  Fragile (brittle) software
  • 270. 1 // Example 49 2 // Point3 class definition represents an x-y coordinate pair. 3 #ifndef POINT3_H 4 #define POINT3_H 5 6 class Point3 { 7 8 public: 9 Point3( int = 0, int = 0 ); // default constructor 10 11 void setX( int ); // set x in coordinate pair 12 int getX() const; // return x from coordinate pair 13 14 void setY( int ); // set y in coordinate pair 15 int getY() const; // return y from coordinate pair 16 17 void print() const; // output Point3 object 18 19 private: 20 int x; // x part of coordinate pair 21 int y; // y part of coordinate pair 22 23 }; // end class Point3 24 25 #endif Better software-engineering practice: private over protected when possible.
  • 271. 1 // Example 50 2 // Point3 class member-function definitions. 3 #include <iostream> 4 5 using std::cout; 6 7 #include "point3.h" // Point3 class definition 8 9 // default constructor 10 Point3::Point3( int xValue, int yValue ) 11 : x( xValue ), y( yValue ) 12 { 13 // empty body 14 15 } // end Point3 constructor 16 17 // set x in coordinate pair 18 void Point3::setX( int xValue ) 19 { 20 x = xValue; // no need for validation 21 22 } // end function setX 23 Member initializers specify values of x and y.
  • 272. 24 // return x from coordinate pair 25 int Point3::getX() const 26 { 27 return x; 28 29 } // end function getX 30 31 // set y in coordinate pair 32 void Point3::setY( int yValue ) 33 { 34 y = yValue; // no need for validation 35 36 } // end function setY 37 38 // return y from coordinate pair 39 int Point3::getY() const 40 { 41 return y; 42 43 } // end function getY 44
  • 273. 45 // output Point3 object 46 void Point3::print() const 47 { 48 cout << '[' << getX() << ", " << getY() << ']'; 49 50 } // end function print Invoke non-private member functions to access private data.
  • 274. 1 // Example 51 2 // Circle4 class contains x-y coordinate pair and radius. 3 #ifndef CIRCLE4_H 4 #define CIRCLE4_H 5 6 #include "point3.h" // Point3 class definition 7 8 class Circle4 : public Point3 { 9 10 public: 11 12 // default constructor 13 Circle4( int = 0, int = 0, double = 0.0 ); 14 15 void setRadius( double ); // set radius 16 double getRadius() const; // return radius 17 18 double getDiameter() const; // return diameter 19 double getCircumference() const; // return circumference 20 double getArea() const; // return area 21 22 void print() const; // output Circle4 object 23 24 private: 25 double radius; // Circle4's radius Class Circle4 inherits from class Point3. Maintain private data member radius.
  • 275. 26 27 }; // end class Circle4 28 29 #endif
  • 276. 1 // Example 52 2 // Circle4 class member-function definitions. 3 #include <iostream> 4 5 using std::cout; 6 7 #include "circle4.h" // Circle4 class definition 8 9 // default constructor 10 Circle4::Circle4( int xValue, int yValue, double radiusValue ) 11 : Point3( xValue, yValue ) // call base-class constructor 12 { 13 setRadius( radiusValue ); 14 15 } // end Circle4 constructor 16 17 // set radius 18 void Circle4::setRadius( double radiusValue ) 19 { 20 radius = ( radiusValue < 0.0 ? 0.0 : radiusValue ); 21 22 } // end function setRadius 23 Base-class initializer syntax passes arguments to base class Point3.
  • 277. 24 // return radius 25 double Circle4::getRadius() const 26 { 27 return radius; 28 29 } // end function getRadius 30 31 // calculate and return diameter 32 double Circle4::getDiameter() const 33 { 34 return 2 * getRadius(); 35 36 } // end function getDiameter 37 38 // calculate and return circumference 39 double Circle4::getCircumference() const 40 { 41 return 3.14159 * getDiameter(); 42 43 } // end function getCircumference 44 Invoke function getRadius rather than directly accessing data member radius.
  • 278. 45 // calculate and return area 46 double Circle4::getArea() const 47 { 48 return 3.14159 * getRadius() * getRadius(); 49 50 } // end function getArea 51 52 // output Circle4 object 53 void Circle4::print() const 54 { 55 cout << "Center = "; 56 Point3::print(); // invoke Point3's print function 57 cout << "; Radius = " << getRadius(); 58 59 } // end function print Invoke function getRadius rather than directly accessing data member radius. Redefine class Point3’s member function print. Invoke base-class Point3’s print function using binary scope-resolution operator (::).
  • 279. 1 // Example 53 2 // Testing class Circle4. 3 #include <iostream> 4 5 using std::cout; 6 using std::endl; 7 using std::fixed; 8 9 #include <iomanip> 10 11 using std::setprecision; 12 13 #include "circle4.h" // Circle4 class definition 14 15 int main() 16 { 17 Circle4 circle( 37, 43, 2.5 ); // instantiate Circle4 object 18 19 // display point coordinates 20 cout << "X coordinate is " << circle.getX() 21 << "nY coordinate is " << circle.getY() 22 << "nRadius is " << circle.getRadius(); 23 Create Circle4 object. Use inherited get functions to access inherited protected data x and y. Use Circle3 get function to access private data radius.
  • 280. 24 circle.setX( 2 ); // set new x-coordinate 25 circle.setY( 2 ); // set new y-coordinate 26 circle.setRadius( 4.25 ); // set new radius 27 28 // display new circle value 29 cout << "nnThe new location and radius of circle aren"; 30 circle.print(); 31 32 // display floating-point values with 2 digits of precision 33 cout << fixed << setprecision( 2 ); 34 35 // display Circle4's diameter 36 cout << "nDiameter is " << circle.getDiameter(); 37 38 // display Circle4's circumference 39 cout << "nCircumference is " << circle.getCircumference(); 40 41 // display Circle4's area 42 cout << "nArea is " << circle.getArea(); 43 44 cout << endl; 45 46 return 0; // indicates successful termination 47 48 } // end main Use inherited set functions to modify inherited protected data x and y.Use Circle3 set function to modify private data radius.
  • 281. X coordinate is 37 Y coordinate is 43 Radius is 2.5 The new location and radius of circle are Center = [2, 2]; Radius = 4.25 Diameter is 8.50 Circumference is 26.70 Area is 56.74
  • 282. Case Study: Three-Level Inheritance Hierarchy  Three level point/circle/cylinder hierarchy  Point  x-y coordinate pair  Circle  x-y coordinate pair  Radius  Cylinder  x-y coordinate pair  Radius  Height
  • 283. 1 // Example 54 2 // Cylinder class inherits from class Circle4. 3 #ifndef CYLINDER_H 4 #define CYLINDER_H 5 6 #include "circle4.h" // Circle4 class definition 7 8 class Cylinder : public Circle4 { 9 10 public: 11 12 // default constructor 13 Cylinder( int = 0, int = 0, double = 0.0, double = 0.0 ); 14 15 void setHeight( double ); // set Cylinder's height 16 double getHeight() const; // return Cylinder's height 17 18 double getArea() const; // return Cylinder's area 19 double getVolume() const; // return Cylinder's volume 20 void print() const; // output Cylinder 21 22 private: 23 double height; // Cylinder's height 24 25 }; // end class Cylinder Class Cylinder inherits from class Circle4. Maintain private data member height.
  • 284. 26 27 #endif 1 // Fig. 9.23: cylinder.cpp 2 // Cylinder class inherits from class Circle4. 3 #include <iostream> 4 5 using std::cout; 6 7 #include "cylinder.h" // Cylinder class definition 8 9 // default constructor 10 Cylinder::Cylinder( int xValue, int yValue, double radiusValue, 11 double heightValue ) 12 : Circle4( xValue, yValue, radiusValue ) 13 { 14 setHeight( heightValue ); 15 16 } // end Cylinder constructor 17 Base-class initializer syntax passes arguments to base class Circle4.
  • 285. 18 // set Cylinder's height 19 void Cylinder::setHeight( double heightValue ) 20 { 21 height = ( heightValue < 0.0 ? 0.0 : heightValue ); 22 23 } // end function setHeight 24 25 // get Cylinder's height 26 double Cylinder::getHeight() const 27 { 28 return height; 29 30 } // end function getHeight 31 32 // redefine Circle4 function getArea to calculate Cylinder area 33 double Cylinder::getArea() const 34 { 35 return 2 * Circle4::getArea() + 36 getCircumference() * getHeight(); 37 38 } // end function getArea 39 Redefine base class Circle4’s member function getArea to return Cylinder surface area. Invoke base-class Circle4’s getArea function using binary scope- resolution operator (::).
  • 286. 40 // calculate Cylinder volume 41 double Cylinder::getVolume() const 42 { 43 return Circle4::getArea() * getHeight(); 44 45 } // end function getVolume 46 47 // output Cylinder object 48 void Cylinder::print() const 49 { 50 Circle4::print(); 51 cout << "; Height = " << getHeight(); 52 53 } // end function print Redefine class Circle4’s member function print.Invoke base-class Circle4’s print function using binary scope-resolution operator (::). Invoke base-class Circle4’s getArea function using binary scope- resolution operator (::).
  • 287. 1 // Example 55 2 // Testing class Cylinder. 3 #include <iostream> 4 5 using std::cout; 6 using std::endl; 7 using std::fixed; 8 9 #include <iomanip> 10 11 using std::setprecision; 12 13 #include "cylinder.h" // Cylinder class definition 14 15 int main() 16 { 17 // instantiate Cylinder object 18 Cylinder cylinder( 12, 23, 2.5, 5.7 ); 19 20 // display point coordinates 21 cout << "X coordinate is " << cylinder.getX() 22 << "nY coordinate is " << cylinder.getY() 23 << "nRadius is " << cylinder.getRadius() 24 << "nHeight is " << cylinder.getHeight(); 25 Invoke indirectly inherited Point3 member functions. Invoke directly inherited Circle4 member function. Invoke Cylinder member function.
  • 288. 26 cylinder.setX( 2 ); // set new x-coordinate 27 cylinder.setY( 2 ); // set new y-coordinate 28 cylinder.setRadius( 4.25 ); // set new radius 29 cylinder.setHeight( 10 ); // set new height 30 31 // display new cylinder value 32 cout << "nnThe new location and radius of circle aren"; 33 cylinder.print(); 34 35 // display floating-point values with 2 digits of precision 36 cout << fixed << setprecision( 2 ); 37 38 // display cylinder's diameter 39 cout << "nnDiameter is " << cylinder.getDiameter(); 40 41 // display cylinder's circumference 42 cout << "nCircumference is " 43 << cylinder.getCircumference(); 44 45 // display cylinder's area 46 cout << "nArea is " << cylinder.getArea(); 47 48 // display cylinder's volume 49 cout << "nVolume is " << cylinder.getVolume(); 50 Invoke indirectly inherited Point3 member functions. Invoke directly inherited Circle4 member function.Invoke Cylinder member function. Invoke redefined print function. Invoke redefined getArea function.
  • 289. 51 cout << endl; 52 53 return 0; // indicates successful termination 54 55 } // end main X coordinate is 12 Y coordinate is 23 Radius is 2.5 Height is 5.7 The new location and radius of circle are Center = [2, 2]; Radius = 4.25; Height = 10 Diameter is 8.50 Circumference is 26.70 Area is 380.53 Volume is 567.45
  • 290. Software Engineering with Inheritance  Customizing existing software  Inherit from existing classes  Include additional members  Redefine base-class members  No direct access to base class’s source code Link to object code  Independent software vendors (ISVs)  Develop proprietary code for sale/license Available in object-code format  Users derive new classes Without accessing ISV proprietary source code
  • 291. Introduction  Polymorphism  “Program in the general”  Derived-class object can be treated as base-class object  “is-a” relationship  Base class is not a derived class object  Virtual functions and dynamic binding  Makes programs extensible  New classes added easily, can still be processed  Examples  Use abstract base class Shape  Defines common interface (functionality)  Point, Circle and Cylinder inherit from Shape Polymorphism
  • 292. Invoking Base-Class Functions from Derived- Class Objects  Pointers to base/derived objects  Base pointer aimed at derived object  “is a” relationship Circle “is a” Point  Will invoke base class functions  Can cast base-object’s address to derived-class pointer  Called down-casting  Allows derived-class functionality  Key point  Base-pointer can aim at derived-object - but can only call base-class functions  Data type of pointer/reference determines functions it can call
  • 293. 1 // Example 56 2 // Aiming base-class and derived-class pointers at base-class 3 // and derived-class objects, respectively. 4 #include <iostream> 5 6 using std::cout; 7 using std::endl; 8 using std::fixed; 9 10 #include <iomanip> 11 12 using std::setprecision; 13 14 #include "point.h" // Point class definition 15 #include "circle.h" // Circle class definition 16 17 int main() 18 { 19 Point point( 30, 50 ); 20 Point *pointPtr = 0; // base-class pointer 21 22 Circle circle( 120, 89, 2.7 ); 23 Circle *circlePtr = 0; // derived-class pointer 24
  • 294. 25 // set floating-point numeric formatting 26 cout << fixed << setprecision( 2 ); 27 28 // output objects point and circle 29 cout << "Print point and circle objects:" 30 << "nPoint: "; 31 point.print(); // invokes Point's print 32 cout << "nCircle: "; 33 circle.print(); // invokes Circle's print 34 35 // aim base-class pointer at base-class object and print 36 pointPtr = &point; 37 cout << "nnCalling print with base-class pointer to " 38 << "nbase-class object invokes base-class print " 39 << "function:n"; 40 pointPtr->print(); // invokes Point's print 41 42 // aim derived-class pointer at derived-class object 43 // and print 44 circlePtr = &circle; 45 cout << "nnCalling print with derived-class pointer to " 46 << "nderived-class object invokes derived-class " 47 << "print function:n"; 48 circlePtr->print(); // invokes Circle's print 49 Use objects and pointers to call the print function. The pointers and objects are of the same class, so the proper print function is called.
  • 295. 50 // aim base-class pointer at derived-class object and print 51 pointPtr = &circle; 52 cout << "nnCalling print with base-class pointer to " 53 << "derived-class objectninvokes base-class print " 54 << "function on that derived-class object:n"; 55 pointPtr->print(); // invokes Point's print 56 cout << endl; 57 58 return 0; 59 60 } // end main Aiming a base-class pointer at a derived object is allowed (the Circle “is a” Point). However, it calls Point’s print function, determined by the pointer type. virtual functions allow us to change this.
  • 296. 1 // Example 57 2 // Aiming a derived-class pointer at a base-class object. 3 #include "point.h" // Point class definition 4 #include "circle.h" // Circle class definition 5 6 int main() 7 { 8 Point point( 30, 50 ); 9 Circle *circlePtr = 0; 10 11 // aim derived-class pointer at base-class object 12 circlePtr = &point; // Error: a Point is not a Circle 13 14 return 0; 15 16 } // end main C:cpphtp4examplesch10fig10_06Fig10_06.cpp(12) : error C2440: '=' : cannot convert from 'class Point *' to 'class Circle *' Types pointed to are unrelated; conversion requires reinterpret_cast, C-style cast or function-style cast
  • 297. 1 // Example 58 2 // Attempting to invoke derived-class-only member functions 3 // through a base-class pointer. 4 #include "point.h" // Point class definition 5 #include "circle.h" // Circle class definition 6 7 int main() 8 { 9 Point *pointPtr = 0; 10 Circle circle( 120, 89, 2.7 ); 11 12 // aim base-class pointer at derived-class object 13 pointPtr = &circle; 14 15 // invoke base-class member functions on derived-class 16 // object through base-class pointer 17 int x = pointPtr->getX(); 18 int y = pointPtr->getY(); 19 pointPtr->setX( 10 ); 20 pointPtr->setY( 10 ); 21 pointPtr->print(); 22
  • 298. 23 // attempt to invoke derived-class-only member functions 24 // on derived-class object through base-class pointer 25 double radius = pointPtr->getRadius(); 26 pointPtr->setRadius( 33.33 ); 27 double diameter = pointPtr->getDiameter(); 28 double circumference = pointPtr->getCircumference(); 29 double area = pointPtr->getArea(); 30 31 return 0; 32 33 } // end main These functions are only defined in Circle. However, pointPtr is of class Point.
  • 299. Virtual Functions  virtual functions  Object (not pointer) determines function called  Why useful?  Suppose Circle, Triangle, Rectangle derived from Shape  Each has own draw function  To draw any shape  Have base class Shape pointer, call draw  Program determines proper draw function at run time (dynamically)  Treat all shapes generically
  • 300. Virtual Functions  Declare draw as virtual in base class  Override draw in each derived class  Like redefining, but new function must have same signature  If function declared virtual, can only be overridden  virtual void draw() const;  Once declared virtual, virtual in all derived classes Good practice to explicitly declare virtual  Dynamic binding  Choose proper function to call at run time  Only occurs off pointer handles  If function called from object, uses that object’s definition
  • 301. Virtual Functions  Polymorphism  Same message, “print”, given to many objects  All through a base pointer  Message takes on “many forms”  Summary  Base-pointer to base-object, derived-pointer to derived  Straightforward  Base-pointer to derived object  Can only call base-class functions  Derived-pointer to base-object  Compiler error  Allowed if explicit cast made
  • 302. Polymorphism Examples  Suppose designing video game  Base class SpaceObject  Derived Martian, SpaceShip, LaserBeam  Base function draw  To refresh screen  Screen manager has vector of base-class pointers to objects  Send draw message to each object  Same message has “many forms” of results  Easy to add class Mercurian  Inherits from SpaceObject  Provides own definition for draw  Screen manager does not need to change code  Calls draw regardless of object’s type  Mercurian objects “plug right in”
  • 303. Type Fields and switch Structures  One way to determine object's class  Give base class an attribute  shapeType in class Shape  Use switch to call proper print function  Many problems  May forget to test for case in switch  If add/remove a class, must update switch structures  Time consuming and error prone  Better to use polymorphism  Less branching logic, simpler programs, less debugging
  • 304. Abstract Classes  Abstract classes  Sole purpose: to be a base class (called abstract base classes)  Incomplete  Derived classes fill in "missing pieces"  Cannot make objects from abstract class  However, can have pointers and references  Concrete classes  Can instantiate objects  Implement all functions they define  Provide specifics
  • 305. Abstract Classes  Abstract classes not required, but helpful  To make a class abstract  Need one or more "pure" virtual functions  Declare function with initializer of 0 virtual void draw() const = 0;  Regular virtual functions  Have implementations, overriding is optional  Pure virtual functions  No implementation, must be overridden  Abstract classes can have data and concrete functions  Required to have one or more pure virtual functions
  • 306. Case Study: Inheriting Interface and Implementation  Make abstract base class Shape  Pure virtual functions (must be implemented)  getName, print  Default implementation does not make sense  Virtual functions (may be redefined)  getArea, getVolume Initially return 0.0  If not redefined, uses base class definition  Derive classes Point, Circle, Cylinder
  • 307. Case Study: Inheriting Interface and Implementation 0.0 0.0 = 0 = 0 0.0 0.0 "Point" [x,y] pr2 0.0 "Circle" center=[x,y]; radius=r 2pr2 +2prh pr2h "Cylinder" center=[x,y]; radius=r; height=h getArea printgetNamegetVolume Shape Point Circle Cylinder
  • 308. 1 // Example 59 2 // Shape abstract-base-class definition. 3 #ifndef SHAPE_H 4 #define SHAPE_H 5 6 #include <string> // C++ standard string class 7 8 using std::string; 9 10 class Shape { 11 12 public: 13 14 // virtual function that returns shape area 15 virtual double getArea() const; 16 17 // virtual function that returns shape volume 18 virtual double getVolume() const; 19 20 // pure virtual functions; overridden in derived classes 21 virtual string getName() const = 0; // return shape name 22 virtual void print() const = 0; // output shape 23 24 }; // end class Shape 25 26 #endif Virtual and pure virtual functions.
  • 309. 1 // Example 60 2 // Shape class member-function definitions. 3 #include <iostream> 4 5 using std::cout; 6 7 #include "shape.h" // Shape class definition 8 9 // return area of shape; 0.0 by default 10 double getArea() const 11 { 12 return 0.0; 13 14 } // end function getArea 15 16 // return volume of shape; 0.0 by default 17 double getVolume() const 18 { 19 return 0.0; 20 21 } // end function getVolume
  • 310. Polymorphism, Virtual Functions and Dynamic Binding “Under the Hood”  Polymorphism has overhead  Not used in STL (Standard Template Library) to optimize performance  virtual function table (vtable)  Every class with a virtual function has a vtable  For every virtual function, vtable has pointer to the proper function  If derived class has same function as base class  Function pointer aims at base-class function
  • 311. Virtual Destructors  Base class pointer to derived object  If destroyed using delete, behavior unspecified  Simple fix  Declare base-class destructor virtual  Makes derived-class destructors virtual  Now, when delete used appropriate destructor called  When derived-class object destroyed  Derived-class destructor executes first  Base-class destructor executes afterwards  Constructors cannot be virtual
  • 312. Case Study: Payroll System Using Polymorphism  Create a payroll program  Use virtual functions and polymorphism  Problem statement  4 types of employees, paid weekly  Salaried (fixed salary, no matter the hours)  Hourly (overtime [>40 hours] pays time and a half)  Commission (paid percentage of sales)  Base-plus-commission (base salary + percentage of sales) Boss wants to raise pay by 10%
  • 313. Payroll System Using Polymorphism  Base class Employee  Pure virtual function earnings (returns pay)  Pure virtual because need to know employee type  Cannot calculate for generic employee  Other classes derive from Employee Employee SalariedEmployee HourlyEmployeeCommissionEmployee BasePlusCommissionEmployee
  • 314. Dynamic Cast  Downcasting  dynamic_cast operator  Determine object's type at runtime  Returns 0 if not of proper type (cannot be cast) NewClass *ptr = dynamic_cast < NewClass *> objectPtr;  Keyword typeid  Header <typeinfo>  Usage: typeid(object)  Returns type_info object  Has information about type of operand, including name  typeid(object).name()
  • 315. 1 // Example 61 2 // Employee abstract base class. 3 #ifndef EMPLOYEE_H 4 #define EMPLOYEE_H 5 6 #include <string> // C++ standard string class 7 8 using std::string; 9 10 class Employee { 11 12 public: 13 Employee( const string &, const string &, const string & ); 14 15 void setFirstName( const string & ); 16 string getFirstName() const; 17 18 void setLastName( const string & ); 19 string getLastName() const; 20 21 void setSocialSecurityNumber( const string & ); 22 string getSocialSecurityNumber() const; 23
  • 316. 24 // pure virtual function makes Employee abstract base class 25 virtual double earnings() const = 0; // pure virtual 26 virtual void print() const; // virtual 27 28 private: 29 string firstName; 30 string lastName; 31 string socialSecurityNumber; 32 33 }; // end class Employee 34 35 #endif // EMPLOYEE_H
  • 317. 1 // Example 62 2 // Abstract-base-class Employee member-function definitions. 3 // Note: No definitions are given for pure virtual functions. 4 #include <iostream> 5 6 using std::cout; 7 using std::endl; 8 9 #include "employee.h" // Employee class definition 10 11 // constructor 12 Employee::Employee( const string &first, const string &last, 13 const string &SSN ) 14 : firstName( first ), 15 lastName( last ), 16 socialSecurityNumber( SSN ) 17 { 18 // empty body 19 20 } // end Employee constructor 21
  • 318. 22 // return first name 23 string Employee::getFirstName() const 24 { 25 return firstName; 26 27 } // end function getFirstName 28 29 // return last name 30 string Employee::getLastName() const 31 { 32 return lastName; 33 34 } // end function getLastName 35 36 // return social security number 37 string Employee::getSocialSecurityNumber() const 38 { 39 return socialSecurityNumber; 40 41 } // end function getSocialSecurityNumber 42 43 // set first name 44 void Employee::setFirstName( const string &first ) 45 { 46 firstName = first; 47 48 } // end function setFirstName 49
  • 319. 50 // set last name 51 void Employee::setLastName( const string &last ) 52 { 53 lastName = last; 54 55 } // end function setLastName 56 57 // set social security number 58 void Employee::setSocialSecurityNumber( const string &number ) 59 { 60 socialSecurityNumber = number; // should validate 61 62 } // end function setSocialSecurityNumber 63 64 // print Employee's information 65 void Employee::print() const 66 { 67 cout << getFirstName() << ' ' << getLastName() 68 << "nsocial security number: " 69 << getSocialSecurityNumber() << endl; 70 71 } // end function print Default implementation for virtual function print.
  • 320. 1 // Example 63 2 // SalariedEmployee class derived from Employee. 3 #ifndef SALARIED_H 4 #define SALARIED_H 5 6 #include "employee.h" // Employee class definition 7 8 class SalariedEmployee : public Employee { 9 10 public: 11 SalariedEmployee( const string &, const string &, 12 const string &, double = 0.0 ); 13 14 void setWeeklySalary( double ); 15 double getWeeklySalary() const; 16 17 virtual double earnings() const; 18 virtual void print() const; // "salaried employee: " 19 20 private: 21 double weeklySalary; 22 23 }; // end class SalariedEmployee 24 25 #endif // SALARIED_H New functions for the SalariedEmployee class. earnings must be overridden. print is overridden to specify that this is a salaried employee.
  • 321. 1 // Example 64 2 // SalariedEmployee class member-function definitions. 3 #include <iostream> 4 5 using std::cout; 6 7 #include "salaried.h" // SalariedEmployee class definition 8 9 // SalariedEmployee constructor 10 SalariedEmployee::SalariedEmployee( const string &first, 11 const string &last, const string &socialSecurityNumber, 12 double salary ) 13 : Employee( first, last, socialSecurityNumber ) 14 { 15 setWeeklySalary( salary ); 16 17 } // end SalariedEmployee constructor 18 19 // set salaried employee's salary 20 void SalariedEmployee::setWeeklySalary( double salary ) 21 { 22 weeklySalary = salary < 0.0 ? 0.0 : salary; 23 24 } // end function setWeeklySalary 25 Use base class constructor for basic fields.
  • 322. 26 // calculate salaried employee's pay 27 double SalariedEmployee::earnings() const 28 { 29 return getWeeklySalary(); 30 31 } // end function earnings 32 33 // return salaried employee's salary 34 double SalariedEmployee::getWeeklySalary() const 35 { 36 return weeklySalary; 37 38 } // end function getWeeklySalary 39 40 // print salaried employee's name 41 void SalariedEmployee::print() const 42 { 43 cout << "nsalaried employee: "; 44 Employee::print(); // code reuse 45 46 } // end function print Must implement pure virtual functions.
  • 323. 1 // Example 65 2 // HourlyEmployee class definition. 3 #ifndef HOURLY_H 4 #define HOURLY_H 5 6 #include "employee.h" // Employee class definition 7 8 class HourlyEmployee : public Employee { 9 10 public: 11 HourlyEmployee( const string &, const string &, 12 const string &, double = 0.0, double = 0.0 ); 13 14 void setWage( double ); 15 double getWage() const; 16 17 void setHours( double ); 18 double getHours() const; 19 20 virtual double earnings() const; 21 virtual void print() const; 22 23 private: 24 double wage; // wage per hour 25 double hours; // hours worked for week 26 27 }; // end class HourlyEmployee 28 29 #endif // HOURLY_H
  • 324. 1 // Example 66 2 // HourlyEmployee class member-function definitions. 3 #include <iostream> 4 5 using std::cout; 6 7 #include "hourly.h" 8 9 // constructor for class HourlyEmployee 10 HourlyEmployee::HourlyEmployee( const string &first, 11 const string &last, const string &socialSecurityNumber, 12 double hourlyWage, double hoursWorked ) 13 : Employee( first, last, socialSecurityNumber ) 14 { 15 setWage( hourlyWage ); 16 setHours( hoursWorked ); 17 18 } // end HourlyEmployee constructor 19 20 // set hourly employee's wage 21 void HourlyEmployee::setWage( double wageAmount ) 22 { 23 wage = wageAmount < 0.0 ? 0.0 : wageAmount; 24 25 } // end function setWage
  • 325. 26 27 // set hourly employee's hours worked 28 void HourlyEmployee::setHours( double hoursWorked ) 29 { 30 hours = ( hoursWorked >= 0.0 && hoursWorked <= 168.0 ) ? 31 hoursWorked : 0.0; 32 33 } // end function setHours 34 35 // return hours worked 36 double HourlyEmployee::getHours() const 37 { 38 return hours; 39 40 } // end function getHours 41 42 // return wage 43 double HourlyEmployee::getWage() const 44 { 45 return wage; 46 47 } // end function getWage 48
  • 326. 49 // get hourly employee's pay 50 double HourlyEmployee::earnings() const 51 { 52 if ( hours <= 40 ) // no overtime 53 return wage * hours; 54 else // overtime is paid at wage * 1.5 55 return 40 * wage + ( hours - 40 ) * wage * 1.5; 56 57 } // end function earnings 58 59 // print hourly employee's information 60 void HourlyEmployee::print() const 61 { 62 cout << "nhourly employee: "; 63 Employee::print(); // code reuse 64 65 } // end function print
  • 327. 1 // Example 67 2 // CommissionEmployee class derived from Employee. 3 #ifndef COMMISSION_H 4 #define COMMISSION_H 5 6 #include "employee.h" // Employee class definition 7 8 class CommissionEmployee : public Employee { 9 10 public: 11 CommissionEmployee( const string &, const string &, 12 const string &, double = 0.0, double = 0.0 ); 13 14 void setCommissionRate( double ); 15 double getCommissionRate() const; 16 17 void setGrossSales( double ); 18 double getGrossSales() const; 19 20 virtual double earnings() const; 21 virtual void print() const; 22 23 private: 24 double grossSales; // gross weekly sales 25 double commissionRate; // commission percentage 26 27 }; // end class CommissionEmployee 28 29 #endif // COMMISSION_H Must set rate and sales.
  • 328. 1 // Example 68 2 // CommissionEmployee class member-function definitions. 3 #include <iostream> 4 5 using std::cout; 6 7 #include "commission.h" // Commission class 8 9 // CommissionEmployee constructor 10 CommissionEmployee::CommissionEmployee( const string &first, 11 const string &last, const string &socialSecurityNumber, 12 double grossWeeklySales, double percent ) 13 : Employee( first, last, socialSecurityNumber ) 14 { 15 setGrossSales( grossWeeklySales ); 16 setCommissionRate( percent ); 17 18 } // end CommissionEmployee constructor 19 20 // return commission employee's rate 21 double CommissionEmployee::getCommissionRate() const 22 { 23 return commissionRate; 24 25 } // end function getCommissionRate
  • 329. 26 27 // return commission employee's gross sales amount 28 double CommissionEmployee::getGrossSales() const 29 { 30 return grossSales; 31 32 } // end function getGrossSales 33 34 // set commission employee's weekly base salary 35 void CommissionEmployee::setGrossSales( double sales ) 36 { 37 grossSales = sales < 0.0 ? 0.0 : sales; 38 39 } // end function setGrossSales 40 41 // set commission employee's commission 42 void CommissionEmployee::setCommissionRate( double rate ) 43 { 44 commissionRate = ( rate > 0.0 && rate < 1.0 ) ? rate : 0.0; 45 46 } // end function setCommissionRate 47
  • 330. 48 // calculate commission employee's earnings 49 double CommissionEmployee::earnings() const 50 { 51 return getCommissionRate() * getGrossSales(); 52 53 } // end function earnings 54 55 // print commission employee's name 56 void CommissionEmployee::print() const 57 { 58 cout << "ncommission employee: "; 59 Employee::print(); // code reuse 60 61 } // end function print
  • 331. 1 // Example 69 2 // BasePlusCommissionEmployee class derived from Employee. 3 #ifndef BASEPLUS_H 4 #define BASEPLUS_H 5 6 #include "commission.h" // Employee class definition 7 8 class BasePlusCommissionEmployee : public CommissionEmployee { 9 10 public: 11 BasePlusCommissionEmployee( const string &, const string &, 12 const string &, double = 0.0, double = 0.0, double = 0.0 ); 13 14 void setBaseSalary( double ); 15 double getBaseSalary() const; 16 17 virtual double earnings() const; 18 virtual void print() const; 19 20 private: 21 double baseSalary; // base salary per week 22 23 }; // end class BasePlusCommissionEmployee 24 25 #endif // BASEPLUS_H Inherits from CommissionEmployee (and from Employee indirectly).
  • 332. 1 // Example 70 2 // BasePlusCommissionEmployee member-function definitions. 3 #include <iostream> 4 5 using std::cout; 6 7 #include "baseplus.h" 8 9 // constructor for class BasePlusCommissionEmployee 10 BasePlusCommissionEmployee::BasePlusCommissionEmployee( 11 const string &first, const string &last, 12 const string &socialSecurityNumber, 13 double grossSalesAmount, double rate, 14 double baseSalaryAmount ) 15 : CommissionEmployee( first, last, socialSecurityNumber, 16 grossSalesAmount, rate ) 17 { 18 setBaseSalary( baseSalaryAmount ); 19 20 } // end BasePlusCommissionEmployee constructor 21 22 // set base-salaried commission employee's wage 23 void BasePlusCommissionEmployee::setBaseSalary( double salary ) 24 { 25 baseSalary = salary < 0.0 ? 0.0 : salary; 26 27 } // end function setBaseSalary
  • 333. 28 29 // return base-salaried commission employee's base salary 30 double BasePlusCommissionEmployee::getBaseSalary() const 31 { 32 return baseSalary; 33 34 } // end function getBaseSalary 35 36 // return base-salaried commission employee's earnings 37 double BasePlusCommissionEmployee::earnings() const 38 { 39 return getBaseSalary() + CommissionEmployee::earnings(); 40 41 } // end function earnings 42 43 // print base-salaried commission employee's name 44 void BasePlusCommissionEmployee::print() const 45 { 46 cout << "nbase-salaried commission employee: "; 47 Employee::print(); // code reuse 48 49 } // end function print
  • 334. 1 // Example 71 2 // Driver for Employee hierarchy. 3 #include <iostream> 4 5 using std::cout; 6 using std::endl; 7 using std::fixed; 8 9 #include <iomanip> 10 11 using std::setprecision; 12 13 #include <vector> 14 15 using std::vector; 16 17 #include <typeinfo> 18 19 #include "employee.h" // Employee base class 20 #include "salaried.h" // SalariedEmployee class 21 #include "commission.h" // CommissionEmployee class 22 #include "baseplus.h" // BasePlusCommissionEmployee class 23 #include "hourly.h" // HourlyEmployee class 24
  • 335. 25 int main() 26 { 27 // set floating-point output formatting 28 cout << fixed << setprecision( 2 ); 29 30 // create vector employees 31 vector < Employee * > employees( 4 ); 32 33 // initialize vector with Employees 34 employees[ 0 ] = new SalariedEmployee( "John", "Smith", 35 "111-11-1111", 800.00 ); 36 employees[ 1 ] = new CommissionEmployee( "Sue", "Jones", 37 "222-22-2222", 10000, .06 ); 38 employees[ 2 ] = new BasePlusCommissionEmployee( "Bob", 39 "Lewis", "333-33-3333", 300, 5000, .04 ); 40 employees[ 3 ] = new HourlyEmployee( "Karen", "Price", 41 "444-44-4444", 16.75, 40 ); 42
  • 336. 43 // generically process each element in vector employees 44 for ( int i = 0; i < employees.size(); i++ ) { 45 46 // output employee information 47 employees[ i ]->print(); 48 49 // downcast pointer 50 BasePlusCommissionEmployee *commissionPtr = 51 dynamic_cast < BasePlusCommissionEmployee * > 52 ( employees[ i ] ); 53 54 // determine whether element points to base-salaried 55 // commission employee 56 if ( commissionPtr != 0 ) { 57 cout << "old base salary: $" 58 << commissionPtr->getBaseSalary() << endl; 59 commissionPtr->setBaseSalary( 60 1.10 * commissionPtr->getBaseSalary() ); 61 cout << "new base salary with 10% increase is: $" 62 << commissionPtr->getBaseSalary() << endl; 63 64 } // end if 65 66 cout << "earned $" << employees[ i ]->earnings() << endl; 67 68 } // end for 69 Use downcasting to cast the employee object into a BasePlusCommissionEmployee. If it points to the correct type of object, the pointer is non-zero. This way, we can give a raise to only BasePlusCommissionEmployees.
  • 337. 70 // release memory held by vector employees 71 for ( int j = 0; j < employees.size(); j++ ) { 72 73 // output class name 74 cout << "ndeleting object of " 75 << typeid( *employees[ j ] ).name(); 76 77 delete employees[ j ]; 78 79 } // end for 80 81 cout << endl; 82 83 return 0; 84 85 } // end main typeid returns a type_info object. This object contains information about the operand, including its name.
  • 338. salaried employee: John Smith social security number: 111-11-1111 earned $800.00 commission employee: Sue Jones social security number: 222-22-2222 earned $600.00 base-salaried commission employee: Bob Lewis social security number: 333-33-3333 old base salary: $300.00 new base salary with 10% increase is: $330.00 earned $530.00 hourly employee: Karen Price social security number: 444-44-4444 earned $670.00 deleting object of class SalariedEmployee deleting object of class CommissionEmployee deleting object of class BasePlusCommissionEmployee deleting object of class HourlyEmployee
  • 339. Multiple Inheritance  Multiple inheritance  Derived class has several base classes  Powerful, but can cause ambiguity problems  If both base classes have functions of the same name  Solution: specify exact function using :: myObject.BaseClass1::function()  Format  Use comma-separated list class Derived : public Base1, public Base2{ contents }
  • 340. 1 // Example 72 2 // Definition of class Base1 3 #ifndef BASE1_H 4 #define BASE1_H 5 6 // class Base1 definition 7 class Base1 { 8 public: 9 Base1( int parameterValue ) { value = parameterValue; } 10 int getData() const { return value; } 11 12 protected: // accessible to derived classes 13 int value; // inherited by derived class 14 15 }; // end class Base1 16 17 #endif // BASE1_H There are two base classes in this example, each has its own getData function. This base class contains an int.
  • 341. 1 // Example 73 2 // Definition of class Base2 3 #ifndef BASE2_H 4 #define BASE2_H 5 6 // class Base2 definition 7 class Base2 { 8 public: 9 Base2( char characterData ) { letter = characterData; } 10 char getData() const { return letter; } 11 12 protected: // accessible to derived classes 13 char letter; // inherited by derived class 14 15 }; // end class Base2 16 17 #endif // BASE2_H
  • 342. 1 // Example 74 2 // Definition of class Derived which inherits 3 // multiple base classes (Base1 and Base2). 4 #ifndef DERIVED_H 5 #define DERIVED_H 6 7 #include <iostream> 8 9 using std::ostream; 10 11 #include "base1.h" 12 #include "base2.h" 13 14 // class Derived definition 15 class Derived : public Base1, public Base2 { 16 friend ostream &operator<<( ostream &, const Derived & ); 17 18 public: 19 Derived( int, char, double ); 20 double getReal() const; 21 22 private: 23 double real; // derived class's private data 24 25 }; // end class Derived 26 27 #endif // DERIVED_H Use comma-separated list.
  • 343. 1 // Example 75 2 // Member function definitions for class Derived 3 #include "derived.h" 4 5 // constructor for Derived calls constructors for 6 // class Base1 and class Base2. 7 // use member initializers to call base-class constructors 8 Derived::Derived( int integer, char character, double double1 ) 9 : Base1( integer ), Base2( character ), real( double1 ) { } 10 11 // return real 12 double Derived::getReal() const { return real; } 13 14 // display all data members of Derived 15 ostream &operator<<( ostream &output, const Derived &derived ) 16 { 17 output << " Integer: " << derived.value 18 << "n Character: " << derived.letter 19 << "nReal number: " << derived.real; 20 21 return output; // enables cascaded calls 22 23 } // end operator<< Note use of base-class constructors in derived class constructor.
  • 344. 1 // Example 76 2 // Driver for multiple inheritance example. 3 #include <iostream> 4 5 using std::cout; 6 using std::endl; 7 8 #include "base1.h" 9 #include "base2.h" 10 #include "derived.h" 11 12 int main() 13 { 14 Base1 base1( 10 ), *base1Ptr = 0; // create Base1 object 15 Base2 base2( 'Z' ), *base2Ptr = 0; // create Base2 object 16 Derived derived( 7, 'A', 3.5 ); // create Derived object 17 18 // print data members of base-class objects 19 cout << "Object base1 contains integer " 20 << base1.getData() 21 << "nObject base2 contains character " 22 << base2.getData() 23 << "nObject derived contains:n" << derived << "nn"; 24
  • 345. 25 // print data members of derived-class object 26 // scope resolution operator resolves getData ambiguity 27 cout << "Data members of Derived can be" 28 << " accessed individually:" 29 << "n Integer: " << derived.Base1::getData() 30 << "n Character: " << derived.Base2::getData() 31 << "nReal number: " << derived.getReal() << "nn"; 32 33 cout << "Derived can be treated as an " 34 << "object of either base class:n"; 35 36 // treat Derived as a Base1 object 37 base1Ptr = &derived; 38 cout << "base1Ptr->getData() yields " 39 << base1Ptr->getData() << 'n'; 40 41 // treat Derived as a Base2 object 42 base2Ptr = &derived; 43 cout << "base2Ptr->getData() yields " 44 << base2Ptr->getData() << endl; 45 46 return 0; 47 48 } // end main Note calls to specific base class functions. Can treat derived-class pointer as either base-class pointer.
  • 346. Object base1 contains integer 10 Object base2 contains character Z Object derived contains: Integer: 7 Character: A Real number: 3.5 Data members of Derived can be accessed individually: Integer: 7 Character: A Real number: 3.5 Derived can be treated as an object of either base class: base1Ptr->getData() yields 7 base2Ptr->getData() yields A
  • 347. Multiple Inheritance and virtual Base Classes  Ambiguities from multiple inheritance  iostream could have duplicate subobjects  Data from ios inherited into ostream and istream  Upcasting iostream pointer to ios object is a problem  Two ios subobjects could exist, which is used?  Ambiguous, results in syntax error  iostream does not actually have this problem ios ostream istream iostream
  • 348. Multiple Inheritance and virtual Base Classes  Solution: use virtual base class inheritance  Only one subobject inherited into multiply derived class Second Derived Class Base Class First Derived Class Multiply-Derived Class virtual inheritance virtual inheritance
  • 349. 1 // Example 77 2 // Attempting to polymorphically call a function that is 3 // multiply inherited from two base classes. 4 #include <iostream> 5 6 using std::cout; 7 using std::endl; 8 9 // class Base definition 10 class Base { 11 public: 12 virtual void print() const = 0; // pure virtual 13 14 }; // end class Base 15 16 // class DerivedOne definition 17 class DerivedOne : public Base { 18 public: 19 20 // override print function 21 void print() const { cout << "DerivedOnen"; } 22 23 }; // end class DerivedOne 24 This example will demonstrate the ambiguity of multiple inheritance.
  • 350. 25 // class DerivedTwo definition 26 class DerivedTwo : public Base { 27 public: 28 29 // override print function 30 void print() const { cout << "DerivedTwon"; } 31 32 }; // end class DerivedTwo 33 34 // class Multiple definition 35 class Multiple : public DerivedOne, public DerivedTwo { 36 public: 37 38 // qualify which version of function print 39 void print() const { DerivedTwo::print(); } 40 41 }; // end class Multiple 42
  • 351. 43 int main() 44 { 45 Multiple both; // instantiate Multiple object 46 DerivedOne one; // instantiate DerivedOne object 47 DerivedTwo two; // instantiate DerivedTwo object 48 49 // create array of base-class pointers 50 Base *array[ 3 ]; 51 52 array[ 0 ] = &both; // ERROR--ambiguous 53 array[ 1 ] = &one; 54 array[ 2 ] = &two; 55 56 // polymorphically invoke print 57 for ( int i = 0; i < 3; i++ ) 58 array[ i ] -> print(); 59 60 return 0; 61 62 } // end main Which base subobject will be used?
  • 352. 1 // Example 78 2 // Using virtual base classes. 3 #include <iostream> 4 5 using std::cout; 6 using std::endl; 7 8 // class Base definition 9 class Base { 10 public: 11 12 // implicit default constructor 13 14 virtual void print() const = 0; // pure virtual 15 16 }; // end Base class 17 18 // class DerivedOne definition 19 class DerivedOne : virtual public Base { 20 public: 21 22 // implicit default constructor calls 23 // Base default constructor 24 25 // override print function 26 void print() const { cout << "DerivedOnen"; } 27 28 }; // end DerivedOne class Use virtual inheritance to solve the ambiguity problem. The compiler generates default constructors, which greatly simplifies the hierarchy.
  • 353. 29 30 // class DerivedTwo definition 31 class DerivedTwo : virtual public Base { 32 public: 33 34 // implicit default constructor calls 35 // Base default constructor 36 37 // override print function 38 void print() const { cout << "DerivedTwon"; } 39 40 }; // end DerivedTwo class 41 42 // class Multiple definition 43 class Multiple : public DerivedOne, public DerivedTwo { 44 public: 45 46 // implicit default constructor calls 47 // DerivedOne and DerivedTwo default constructors 48 49 // qualify which version of function print 50 void print() const { DerivedTwo::print(); } 51 52 }; // end Multiple class Use virtual inheritance, as before.
  • 354. 53 54 int main() 55 { 56 Multiple both; // instantiate Multiple object 57 DerivedOne one; // instantiate DerivedOne object 58 DerivedTwo two; // instantiate DerivedTwo object 59 60 // declare array of base-class pointers and initialize 61 // each element to a derived-class type 62 Base *array[ 3 ]; 63 64 array[ 0 ] = &both; 65 array[ 1 ] = &one; 66 array[ 2 ] = &two; 67 68 // polymorphically invoke function print 69 for ( int i = 0; i < 3; i++ ) 70 array[ i ]->print(); 71 72 return 0; 73 74 } // end main DerivedTwo DerivedOne DerivedTwo
  • 355. Program Design and Software Tools Template, Standard Template Library Template
  • 356. Introduction  Overloaded functions  Similar operations but Different types of data  Function templates  Specify entire range of related (overloaded) functions  Function-template specializations  Identical operations  Different types of data  Single function template  Compiler generates separate object-code functions  Unlike Macros they allow Type checking  Class templates  Specify entire range of related classes  Class-template specializations
  • 357. Function Templates  Function-template definitions  Keyword template  List formal type parameters in angle brackets (< and >)  Each parameter preceded by keyword class or typename class and typename interchangeable template< class T > template< typename ElementType > template< class BorderType, class FillType >  Specify types of Arguments to function Return type of function Variables within function
  • 358. 1 // Example 79 2 // Using template functions. 3 #include <iostream> 4 5 using std::cout; 6 using std::endl; 7 8 // function template printArray definition 9 template< class T > 10 void printArray( const T *array, const int count ) 11 { 12 for ( int i = 0; i < count; i++ ) 13 cout << array[ i ] << " "; 14 15 cout << endl; 16 17 } // end function printArray 18 19 int main() 20 { 21 const int aCount = 5; 22 const int bCount = 7; 23 const int cCount = 6; 24 Function template definition; declare single formal type parameter T. T is type parameter; use any valid identifier. If T is user-defined type, stream-insertion operator must be overloaded for class T.
  • 359. 25 int a[ aCount ] = { 1, 2, 3, 4, 5 }; 26 double b[ bCount ] = { 1.1, 2.2, 3.3, 4.4, 5.5, 6.6, 7.7 }; 27 char c[ cCount ] = "HELLO"; // 6th position for null 28 29 cout << "Array a contains:" << endl; 30 31 // call integer function-template specialization 32 printArray( a, aCount ); 33 34 cout << "Array b contains:" << endl; 35 36 // call double function-template specialization 37 printArray( b, bCount ); 38 39 cout << "Array c contains:" << endl; 40 41 // call character function-template specialization 42 printArray( c, cCount ); 43 44 return 0; 45 46 } // end main Creates complete function-template specialization for printing array of ints: void printArray( const int *array, const int count ) { for ( int i = 0; i < count; i++ ) cout << array[ i ] << " " cout << endl; } // end function printArray Compiler infers T is double; instantiates function-template specialization where T is double. Compiler infers T is char; instantiates function-template specialization where T is char.
  • 360. Overloading Function Templates  Related function-template specializations  Same name  Compiler uses overloading resolution  Function template overloading  Other function templates with same name  Different parameters  Non-template functions with same name  Different function arguments  Compiler performs matching process  Tries to find precise match of function name and argument types  If fails, function template Generate function-template specialization with precise match
  • 361. Class Templates  Stack  LIFO (last-in-first-out) structure  Class templates  Generic programming  Describe notion of stack generically  Instantiate type-specific version  Parameterized types  Require one or more type parameters Customize “generic class” template to form class-template specialization
  • 362. 1 // Example 80 2 // Stack class template. 3 #ifndef TSTACK1_H 4 #define TSTACK1_H 5 6 template< class T > 7 class Stack { 8 9 public: 10 Stack( int = 10 ); // default constructor (stack size 10) 11 12 // destructor 13 ~Stack() 14 { 15 delete [] stackPtr; 16 17 } // end ~Stack destructor 18 19 bool push( const T& ); // push an element onto the stack 20 bool pop( T& ); // pop an element off the stack 21 Specify class-template definition; type parameter T indicates type of Stack class to be created. Function parameters of type T.
  • 363. 22 // determine whether Stack is empty 23 bool isEmpty() const 24 { 25 return top == -1; 26 27 } // end function isEmpty 28 29 // determine whether Stack is full 30 bool isFull() const 31 { 32 return top == size - 1; 33 34 } // end function isFull 35 36 private: 37 int size; // # of elements in the stack 38 int top; // location of the top element 39 T *stackPtr; // pointer to the stack 40 41 }; // end class Stack 42 Array of elements of type T.
  • 364. 43 // constructor 44 template< class T > 45 Stack< T >::Stack( int s ) 46 { 47 size = s > 0 ? s : 10; 48 top = -1; // Stack initially empty 49 stackPtr = new T[ size ]; // allocate memory for elements 50 51 } // end Stack constructor 52 53 // push element onto stack; 54 // if successful, return true; otherwise, return false 55 template< class T > 56 bool Stack< T >::push( const T &pushValue ) 57 { 58 if ( !isFull() ) { 59 stackPtr[ ++top ] = pushValue; // place item on Stack 60 return true; // push successful 61 62 } // end if 63 64 return false; // push unsuccessful 65 66 } // end function push 67 Member functions preceded with header template< class T > Use binary scope resolution operator (::) with class- template name (Stack< T >) to tie definition to class template’s scope. Constructor creates array of type T. For example, compiler generates stackPtr = new T[ size ]; for class-template specialization Stack< double >.
  • 365. 68 // pop element off stack; 69 // if successful, return true; otherwise, return false 70 template< class T > 71 bool Stack< T >::pop( T &popValue ) 72 { 73 if ( !isEmpty() ) { 74 popValue = stackPtr[ top-- ]; // remove item from Stack 75 return true; // pop successful 76 77 } // end if 78 79 return false; // pop unsuccessful 80 81 } // end function pop 82 83 #endif Member function preceded with header template< class T >Use binary scope resolution operator (::) with class- template name (Stack< T >) to tie definition to class template’s scope.
  • 366. 1 // Example 81 2 // Stack-class-template test program. 3 #include <iostream> 4 5 using std::cout; 6 using std::cin; 7 using std::endl; 8 9 #include "tstack1.h" // Stack class template definition 10 11 int main() 12 { 13 Stack< double > doubleStack( 5 ); 14 double doubleValue = 1.1; 15 16 cout << "Pushing elements onto doubleStackn"; 17 18 while ( doubleStack.push( doubleValue ) ) { 19 cout << doubleValue << ' '; 20 doubleValue += 1.1; 21 22 } // end while 23 24 cout << "nStack is full. Cannot push " << doubleValue 25 << "nnPopping elements from doubleStackn"; Link to class template definition. Instantiate object of class Stack< double >. Invoke function push of class-template specialization Stack< double >.
  • 367. 26 27 while ( doubleStack.pop( doubleValue ) ) 28 cout << doubleValue << ' '; 29 30 cout << "nStack is empty. Cannot popn"; 31 32 Stack< int > intStack; 33 int intValue = 1; 34 cout << "nPushing elements onto intStackn"; 35 36 while ( intStack.push( intValue ) ) { 37 cout << intValue << ' '; 38 ++intValue; 39 40 } // end while 41 42 cout << "nStack is full. Cannot push " << intValue 43 << "nnPopping elements from intStackn"; 44 45 while ( intStack.pop( intValue ) ) 46 cout << intValue << ' '; 47 48 cout << "nStack is empty. Cannot popn"; 49 50 return 0; Invoke function pop of class- template specialization Stack< double >. Note similarity of code for Stack< int > to code for Stack< double >.
  • 368. 51 52 } // end main Pushing elements onto doubleStack 1.1 2.2 3.3 4.4 5.5 Stack is full. Cannot push 6.6 Popping elements from doubleStack 5.5 4.4 3.3 2.2 1.1 Stack is empty. Cannot pop Pushing elements onto intStack 1 2 3 4 5 6 7 8 9 10 Stack is full. Cannot push 11 Popping elements from intStack 10 9 8 7 6 5 4 3 2 1 Stack is empty. Cannot pop
  • 369. 1 // Example 82 2 // Stack class template test program. Function main uses a 3 // function template to manipulate objects of type Stack< T >. 4 #include <iostream> 5 6 using std::cout; 7 using std::cin; 8 using std::endl; 9 10 #include "tstack1.h" // Stack class template definition 11 12 // function template to manipulate Stack< T > 13 template< class T > 14 void testStack( 15 Stack< T > &theStack, // reference to Stack< T > 16 T value, // initial value to push 17 T increment, // increment for subsequent values 18 const char *stackName ) // name of the Stack < T > object 19 { 20 cout << "nPushing elements onto " << stackName << 'n'; 21 22 while ( theStack.push( value ) ) { 23 cout << value << ' '; 24 value += increment; 25 26 } // end while Function template to manipulat Stack< T > eliminates simil code from previous file for Stack< double > and Stack< int >.
  • 370. 27 28 cout << "nStack is full. Cannot push " << value 29 << "nnPopping elements from " << stackName << 'n'; 30 31 while ( theStack.pop( value ) ) 32 cout << value << ' '; 33 34 cout << "nStack is empty. Cannot popn"; 35 36 } // end function testStack 37 38 int main() 39 { 40 Stack< double > doubleStack( 5 ); 41 Stack< int > intStack; 42 43 testStack( doubleStack, 1.1, 1.1, "doubleStack" ); 44 testStack( intStack, 1, 1, "intStack" ); 45 46 return 0; 47 48 } // end main
  • 371. Pushing elements onto doubleStack 1.1 2.2 3.3 4.4 5.5 Stack is full. Cannot push 6.6 Popping elements from doubleStack 5.5 4.4 3.3 2.2 1.1 Stack is empty. Cannot pop Pushing elements onto intStack 1 2 3 4 5 6 7 8 9 10 Stack is full. Cannot push 11 Popping elements from intStack 10 9 8 7 6 5 4 3 2 1 Stack is empty. Cannot pop Note output identical to that of fig11_03.cpp.
  • 372. Class templates Nontype parameters  Default arguments  Treated as consts template< class T, int elements > Stack< double, 100 > mostRecentSalesFigures; Declares object of type Stack< double, 100> Type parameter  Default type example: template< class T = string > Overriding class templates Class for specific type  Does not match common class template Example: template<> Class Array< Martian > { // body of class definition }; Class Templates and Nontype Parameters
  • 373. Templates and Inheritance  Several ways of relating templates and inheritance  Class template derived from class-template specialization  Class template derived from non-template class  Class-template specialization derived from class-template specialization  Non-template class derived from class-template specialization  Friendships between class template and  Global function  Member function of another class  Entire class
  • 374. Templates and Friends  friend functions  Inside definition of template< class T > class X  friend void f1(); f1() friend of all class-template specializations  friend void f2( X< T > & ); f2( X< float > & ) friend of X< float > only, f2( X< double > & ) friend of X< double > only, f2( X< int > & ) friend of X< int > only, …  friend void A::f4(); Member function f4 of class A friend of all class-template specializations
  • 375. Templates and Friends  friend functions  Inside definition of template< class T > class X  friend void C< T >::f5( X< T > & ); Member function C<float>::f5( X< float> & ) friend of class X<float> only  friend classes  Inside definition of template< class T > class X  friend class Y; Every member function of Y friend of every class-template specialization  friend class Z<T>; class Z<float> friend of class-template specialization X<float>, etc.
  • 376. Templates and static Members  Non-template class  static data members shared between all objects  Class-template specialization  Each has own copy of static data members  static variables initialized at file scope  Each has own copy of static member functions
  • 377. Introduction to the Standard Template Library (STL)  STL  Powerful, template-based components  Containers: template data structures  Iterators: like pointers, access elements of containers  Algorithms: data manipulation, searching, sorting, etc.  Object- oriented programming: reuse, reuse, reuse  Only an introduction to STL, a huge class library
  • 378. Introduction to Containers  Three types of containers  Sequence containers: vector; deque; list  Linear data structures (vectors, linked lists)  First-class container  Associative containers: set; multiset; map; multimap  Non-linear, can find elements quickly  Key/value pairs  First-class container  Container adapters:stack; queue; priority_queue  Near containers  Similar to containers, with reduced functionality  Containers have some common functions
  • 379. Common STL Member Functions  Member functions for all containers  Default constructor, copy constructor, destructor  empty  max_size, size  = < <= > >= == !=  swap  Functions for first-class containers  begin, end  rbegin, rend  erase, clear
  • 380. Common STL typedefs  typedefs for first-class containers  value_type  reference  const_reference  pointer  iterator  const_iterator  reverse_iterator  const_reverse_iterator  difference_type  size_type
  • 381. Introduction to Iterators  Iterators similar to pointers  Point to first element in a container  Iterator operators same for all containers  * dereferences  ++ points to next element  begin() returns iterator to first element  end() returns iterator to last element  Use iterators with sequences (ranges)  Containers  Input sequences: istream_iterator  Output sequences: ostream_iterator
  • 382. Iterators  Usage  std::istream_iterator< int > inputInt( cin )  Can read input from cin  *inputInt: Dereference to read first int from cin  ++inputInt: Go to next int in stream  std::ostream_iterator< int > outputInt(cout)  Can output ints to cout  *outputInt = 7: Outputs 7 to cout  ++outputInt: Advances iterator so we can output next int  Example int number1 = *inputInt; ++inputInt int number1 = *inputInt; cout << "The sum is: "; *outputInt = number1 + number2;
  • 383. Iterator Categories  Input  Read elements from container, can only move forward  Output  Write elements to container, only forward  Forward  Combines input and output, retains position  Bidirectional  Like forward, but can move backwards as well  Multi-pass (can pass through sequence twice)  Random access  Like bidirectional, but can also jump to any element
  • 384. Iterator Types Supported  Sequence containers  vector: random access  deque: random access  list: bidirectional  Associative containers (all bidirectional)  set  multiset  Map  multimap  Container adapters (no iterators supported)  stack  queue  priority_queue
  • 385. Iterator Operations  All  ++p, p++  Input iterators  *p (to use as rvalue)  p = p1  p == p1, p != p1  Output iterators  *p  p = p1 Forward iterators Have functionality of input and output iterators Bidirectional --p, p-- Random access p + i, p += i p - i, p -= i p[i] p < p1, p <= p1 p > p1, p >= p1
  • 386. Introduction to Algorithms  STL has algorithms used generically across containers  Operate on elements indirectly via iterators  Often operate on sequences of elements  Defined by pairs of iterators  First and last element  Algorithms often return iterators  find()  Returns iterator to element, or end() if not found  Premade algorithms save programmers time and effort
  • 387. vector Sequence Container  vector  Has random access iterators  Data structure with contiguous memory locations  Access elements with []  Use when data must be sorted and easily accessible  When memory exhausted  Allocates larger, contiguous area of memory  Copies itself there  Deallocates old memory  Declarations  std::vector <type> v;  type: int, float, etc.
  • 388. vector Sequence Container  Iterators  std::vector<type>::const_iterator iterVar;  const_iterator cannot modify elements (read)  std::vector<type>::reverse_iterator iterVar;  Visits elements in reverse order (end to beginning)  Use rbegin to get starting point  Use rend to get ending point  vector functions  v.push_back(value)  Add element to end (found in all sequence containers).  v.size()  Current size of vector  v.capacity()  How much vector can hold before reallocating memory  Reallocation doubles size  vector<type> v(a, a + SIZE)  Creates vector v with elements from array a up to (not including) a + SIZE
  • 389. vector Sequence Container  vector functions  v.insert(iterator, value )  Inserts value before location of iterator  v.insert(iterator, array , array + SIZE)  Inserts array elements (up to, but not including array + SIZE) into vector  v.erase( iterator )  Remove element from container  v.erase( iter1, iter2 )  Remove elements starting from iter1 and up to (not including) iter2  v.clear()  Erases entire container  vector functions operations  v.front(), v.back()  Return first and last element  v.[elementNumber] = value;  Assign value to an element  v.at[elementNumber] = value;  As above, with range checking  out_of_bounds exception
  • 390. vector Sequence Container  ostream_iterator  std::ostream_iterator< type > Name( outputStream, separator );  type: outputs values of a certain type  outputStream: iterator output location  separator: character separating outputs  Example  std::ostream_iterator< int > output( cout, " " );  std::copy( iterator1, iterator2, output );  Copies elements from iterator1 up to (not including) iterator2 to output, an ostream_iterator
  • 391. list Sequence Container  list container : Header <list>  Efficient insertion/deletion anywhere in container  Doubly-linked list (two pointers per node)  Bidirectional iterators  std::list< type > name;  list functions for object t  t.sort()  Sorts in ascending order  t.splice(iterator, otherObject );  Inserts values from otherObject before iterator  t.merge( otherObject )  Removes otherObject and inserts it into t, sorted  t.unique()  Removes duplicate elements  t.swap(otherObject);  Exchange contents  t.assign(iterator1, iterator2)  Replaces contents with elements in range of iterators  t.remove(value)  Erases all instances of value
  • 392. deque Sequence Container  deque ("deek"): double-ended queue  Header <deque>  Indexed access using []  Efficient insertion/deletion in front and back  Non-contiguous memory: has "smarter" iterators  Same basic operations as vector  Also has  push_front (insert at front of deque)  pop_front (delete from front)
  • 393. Associative Containers  Associative containers  Direct access to store/retrieve elements  Uses keys (search keys)  4 types: multiset, set, multimap and map  Keys in sorted order  multiset and multimap allow duplicate keys  multimap and map have keys and associated values  multiset and set only have values
  • 394. multiset Associative Container  multiset  Header <set>  Fast storage, retrieval of keys (no values)  Allows duplicates  Bidirectional iterators  Ordering of elements  Done by comparator function object  Used when creating multiset  For integer multiset  less<int> comparator function object  multiset< int, std::less<int> > myObject;  Elements will be sorted in ascending order
  • 395. Multiset Associative Container  Multiset functions  ms.insert(value)  Inserts value into multiset  ms.count(value)  Returns number of occurrences of value  ms.find(value)  Returns iterator to first instance of value  ms.lower_bound(value)  Returns iterator to first location of value  ms.upper_bound(value)  Returns iterator to location after last occurrence of value  Class pair  Manipulate pairs of values  Pair objects contain first and second  const_iterators  For a pair object q q = ms.equal_range(value)  Sets first and second to lower_bound and upper_bound for a given value
  • 396. 1 // Example 83 2 // Testing Standard Library class multiset 3 #include <iostream> 4 5 using std::cout; 6 using std::endl; 7 8 #include <set> // multiset class-template definition 9 10 // define short name for multiset type used in this program 11 typedef std::multiset< int, std::less< int > > ims; 12 13 #include <algorithm> // copy algorithm 14 15 int main() 16 { 17 const int SIZE = 10; 18 int a[ SIZE ] = { 7, 22, 9, 1, 18, 30, 100, 22, 85, 13 }; 19 20 ims intMultiset; // ims is typedef for "integer multiset" 21 std::ostream_iterator< int > output( cout, " " ); 22 23 cout << "There are currently " << intMultiset.count( 15 ) 24 << " values of 15 in the multisetn"; 25 typedefs help clarify program. This declares an integer multiset that stores values in ascending order.
  • 397. 26 intMultiset.insert( 15 ); // insert 15 in intMultiset 27 intMultiset.insert( 15 ); // insert 15 in intMultiset 28 29 cout << "After inserts, there are " 30 << intMultiset.count( 15 ) 31 << " values of 15 in the multisetnn"; 32 33 // iterator that cannot be used to change element values 34 ims::const_iterator result; 35 36 // find 15 in intMultiset; find returns iterator 37 result = intMultiset.find( 15 ); 38 39 if ( result != intMultiset.end() ) // if iterator not at end 40 cout << "Found value 15n"; // found search value 15 41 42 // find 20 in intMultiset; find returns iterator 43 result = intMultiset.find( 20 ); 44 45 if ( result == intMultiset.end() ) // will be true hence 46 cout << "Did not find value 20n"; // did not find 20 47 48 // insert elements of array a into intMultiset 49 intMultiset.insert( a, a + SIZE ); 50 51 cout << "nAfter insert, intMultiset contains:n"; 52 std::copy( intMultiset.begin(), intMultiset.end(), output ); 53 Use member function find.
  • 398. 54 // determine lower and upper bound of 22 in intMultiset 55 cout << "nnLower bound of 22: " 56 << *( intMultiset.lower_bound( 22 ) ); 57 cout << "nUpper bound of 22: " 58 << *( intMultiset.upper_bound( 22 ) ); 59 60 // p represents pair of const_iterators 61 std::pair< ims::const_iterator, ims::const_iterator > p; 62 63 // use equal_range to determine lower and upper bound 64 // of 22 in intMultiset 65 p = intMultiset.equal_range( 22 ); 66 67 cout << "nnequal_range of 22:" 68 << "n Lower bound: " << *( p.first ) 69 << "n Upper bound: " << *( p.second ); 70 71 cout << endl; 72 73 return 0; 74 75 } // end main Use a pair object to get the lower and upper bound for 22.
  • 399. There are currently 0 values of 15 in the multiset After inserts, there are 2 values of 15 in the multiset Found value 15 Did not find value 20 After insert, intMultiset contains: 1 7 9 13 15 15 18 22 22 30 85 100 Lower bound of 22: 22 Upper bound of 22: 30 equal_range of 22: Lower bound: 22 Upper bound: 30
  • 400. Set Associative Container  Set: Header <set>  Implementation identical to multiset  Unique keys: Duplicates ignored and not inserted  Supports bidirectional iterators (but not random access)  std::set< type, std::less<type> > name;  Multimap: Header <map>  Fast storage and retrieval of keys and associated values  Has key/value pairs  Duplicate keys allowed (multiple values for a single key) One-to-many relationship I.e., one student can take many courses  Insert pair objects (with a key and value)  Bidirectional iterators
  • 401. Multimap Associative Container  Example std::multimap< int, double, std::less< int > > mmapObject; Key type int Value type double Sorted in ascending order  Use typedef to simplify code typedef std::multimap<int, double, std::less<int>> mmid; mmid mmapObject; mmapObject.insert( mmid::value_type( 1, 3.4 ) ); Inserts key 1 with value 3.4  mmid::value_type creates a pair object
  • 402. 1 // Example 84 2 // Standard library class multimap test program. 3 #include <iostream> 4 5 using std::cout; 6 using std::endl; 7 8 #include <map> // map class-template definition 9 10 // define short name for multimap type used in this program 11 typedef std::multimap< int, double, std::less< int > > mmid; 12 13 int main() 14 { 15 mmid pairs; 16 17 cout << "There are currently " << pairs.count( 15 ) 18 << " pairs with key 15 in the multimapn"; 19 20 // insert two value_type objects in pairs 21 pairs.insert( mmid::value_type( 15, 2.7 ) ); 22 pairs.insert( mmid::value_type( 15, 99.3 ) ); 23 24 cout << "After inserts, there are " 25 << pairs.count( 15 ) 26 << " pairs with key 15nn"; Definition for a multimap that maps integer keys to double values. Create multimap and insert key-value pairs.
  • 403. 27 28 // insert five value_type objects in pairs 29 pairs.insert( mmid::value_type( 30, 111.11 ) ); 30 pairs.insert( mmid::value_type( 10, 22.22 ) ); 31 pairs.insert( mmid::value_type( 25, 33.333 ) ); 32 pairs.insert( mmid::value_type( 20, 9.345 ) ); 33 pairs.insert( mmid::value_type( 5, 77.54 ) ); 34 35 cout << "Multimap pairs contains:nKeytValuen"; 36 37 // use const_iterator to walk through elements of pairs 38 for ( mmid::const_iterator iter = pairs.begin(); 39 iter != pairs.end(); ++iter ) 40 cout << iter->first << 't' 41 << iter->second << 'n'; 42 43 cout << endl; 44 45 return 0; 46 47 } // end main Use iterator to print entire multimap.
  • 404. There are currently 0 pairs with key 15 in the multimap After inserts, there are 2 pairs with key 15 Multimap pairs contains: Key Value 5 77.54 10 22.22 15 2.7 15 99.3 20 9.345 25 33.333 30 111.11
  • 405. Map Associative Container  map  Header <map>  Like multimap, but only unique key/value pairs  One-to-one mapping (duplicates ignored)  Use [] to access values  Example: for map object m m[30] = 4000.21;  Sets the value of key 30 to 4000.21  If subscript not in map, creates new key/value pair  Type declaration std::map< int, double, std::less< int > >;
  • 406. 1 // Example 85 2 // Standard library class map test program. 3 #include <iostream> 4 5 using std::cout; 6 using std::endl; 7 8 #include <map> // map class-template definition 9 10 // define short name for map type used in this program 11 typedef std::map< int, double, std::less< int > > mid; 12 13 int main() 14 { 15 mid pairs; 16 17 // insert eight value_type objects in pairs 18 pairs.insert( mid::value_type( 15, 2.7 ) ); 19 pairs.insert( mid::value_type( 30, 111.11 ) ); 20 pairs.insert( mid::value_type( 5, 1010.1 ) ); 21 pairs.insert( mid::value_type( 10, 22.22 ) ); 22 pairs.insert( mid::value_type( 25, 33.333 ) ); 23 pairs.insert( mid::value_type( 5, 77.54 ) ); // dupe ignored 24 pairs.insert( mid::value_type( 20, 9.345 ) ); 25 pairs.insert( mid::value_type( 15, 99.3 ) ); // dupe ignored 26 Again, use typedefs to simplify declaration. Duplicate keys ignored.
  • 407. 27 cout << "pairs contains:nKeytValuen"; 28 29 // use const_iterator to walk through elements of pairs 30 for ( mid::const_iterator iter = pairs.begin(); 31 iter != pairs.end(); ++iter ) 32 cout << iter->first << 't' 33 << iter->second << 'n'; 34 35 // use subscript operator to change value for key 25 36 pairs[ 25 ] = 9999.99; 37 38 // use subscript operator insert value for key 40 39 pairs[ 40 ] = 8765.43; 40 41 cout << "nAfter subscript operations, pairs contains:" 42 << "nKeytValuen"; 43 44 for ( mid::const_iterator iter2 = pairs.begin(); 45 iter2 != pairs.end(); ++iter2 ) 46 cout << iter2->first << 't' 47 << iter2->second << 'n'; 48 49 cout << endl; 50 51 return 0; 52 53 } // end main Can use subscript operator to add or change key-value pairs.
  • 408. pairs contains: Key Value 5 1010.1 10 22.22 15 2.7 20 9.345 25 33.333 30 111.11 After subscript operations, pairs contains: Key Value 5 1010.1 10 22.22 15 2.7 20 9.345 25 9999.99 30 111.11 40 8765.43
  • 409. Container Adapters  Container adapters  stack, queue and priority_queue  Not first class containers  Do not support iterators  Do not provide actual data structure  Programmer can select implementation  Member functions push and pop  stack  Header <stack>  Insertions and deletions at one end  Last-in, first-out (LIFO) data structure  Can use vector, list, or deque (default)  Declarations stack<type, vector<type> > myStack; stack<type, list<type> > myOtherStack; stack<type> anotherStack; // default deque  vector, list Implementation of stack (default deque) Does not change behavior, just performance (deque and vector fastest)
  • 410. Algorithms  Before STL  Class libraries incompatible among vendors  Algorithms built into container classes  STL separates containers and algorithms  Easier to add new algorithms  More efficient, avoids virtual function calls  <algorithm>
  • 411. Basic Searching and Sorting Algorithms  find(iter1, iter2, value)  Returns iterator to first instance of value (in range)  find_if(iter1, iter2, function)  Like find  Returns iterator when function returns true  sort(iter1, iter2)  Sorts elements in ascending order  binary_search(iter1, iter2, value)  Searches ascending sorted list for value  Uses binary search
  • 412. Function Objects  Function objects (<functional>)  Contain functions invoked using operator() STL function objects Type divides< T > arithmetic equal_to< T > relational greater< T > relational greater_equal< T > relational less< T > relational less_equal< T > relational logical_and< T > logical logical_not< T > logical logical_or< T > logical minus< T > arithmetic modulus< T > arithmetic negate< T > arithmetic not_equal_to< T > relational plus< T > arithmetic multiplies< T > arithmetic
  • 413. 1 // Example 86 2 // Demonstrating function objects. 3 #include <iostream> 4 5 using std::cout; 6 using std::endl; 7 8 #include <vector> // vector class-template definition 9 #include <algorithm> // copy algorithm 10 #include <numeric> // accumulate algorithm 11 #include <functional> // binary_function definition 12 13 // binary function adds square of its second argument and 14 // running total in its first argument, then returns sum 15 int sumSquares( int total, int value ) 16 { 17 return total + value * value; 18 19 } // end function sumSquares 20 Create a function to be used with accumulate.
  • 414. 21 // binary function class template defines overloaded operator() 22 // that adds suare of its second argument and running total in 23 // its first argument, then returns sum 24 template< class T > 25 class SumSquaresClass : public std::binary_function< T, T, T > { 26 27 public: 28 29 // add square of value to total and return result 30 const T operator()( const T &total, const T &value ) 31 { 32 return total + value * value; 33 34 } // end function operator() 35 36 }; // end class SumSquaresClass 37 Create a function object (it can also encapsulate data). Overload operator().
  • 415. 38 int main() 39 { 40 const int SIZE = 10; 41 int array[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 }; 42 43 std::vector< int > integers( array, array + SIZE ); 44 45 std::ostream_iterator< int > output( cout, " " ); 46 47 int result = 0; 48 49 cout << "vector v contains:n"; 50 std::copy( integers.begin(), integers.end(), output ); 51 52 // calculate sum of squares of elements of vector integers 53 // using binary function sumSquares 54 result = std::accumulate( integers.begin(), integers.end(), 55 0, sumSquares ); 56 57 cout << "nnSum of squares of elements in integers using " 58 << "binarynfunction sumSquares: " << result; 59 accumulate initially passes 0 as the first argument, with the first element as the second. It then uses the return value as the first argument, and iterates through the other elements.
  • 416. 60 // calculate sum of squares of elements of vector integers 61 // using binary-function object 62 result = std::accumulate( integers.begin(), integers.end(), 63 0, SumSquaresClass< int >() ); 64 65 cout << "nnSum of squares of elements in integers using " 66 << "binarynfunction object of type " 67 << "SumSquaresClass< int >: " << result << endl; 68 69 return 0; 70 71 } // end main vector v contains: 1 2 3 4 5 6 7 8 9 10 Sum of squares of elements in integers using binary function sumSquares: 385 Sum of squares of elements in integers using binary function object of type SumSquaresClass< int >: 385 Use accumulate with a function object.
  • 417. Program Design and Software Tools Stack/Queue - File Processing Stack/Queue
  • 418. Introduction  Storage of data  Arrays, variables are temporary  Files are permanent  Magnetic disk, optical disk, tapes  In this chapter  Create, update, process files  Sequential and random access  Formatted and raw processing
  • 419. The Data Hierarchy  From smallest to largest  Bit (binary digit)  1 or 0  Character set Digits, letters, symbols used to represent data Every character represented by 1's and 0's  Byte: 8 bits: Can store a character (char)  From smallest to largest (continued)  Field: group of characters with some meaning  Your name  Record: group of related fields  struct or class in C++  In payroll system, could be name, SS#, address, wage  Each field associated with same employee  Record key: field used to uniquely identify record  File: group of related records  Payroll for entire company  Sequential file: records stored by key  Database: group of related files  Payroll, accounts-receivable, inventory…
  • 420. Files and Streams  C++ views file as sequence of bytes  Ends with end-of-file marker  When file opened  Object created, stream associated with it  cin, cout, etc. created when <iostream> included  Communication between program and file/device 0 31 2 4 5 8 9 ... ... n-1 end-of-file marker 6 7
  • 421. Files and Streams  To perform file processing  Include <iostream> and <fstream>  Class templates  basic_ifstream (input)  basic_ofstream (output)  basic_fstream (I/O)  typedefs for specializations that allow char I/O  ifstream (char input)  ofstream (char output)  fstream (char I/O)
  • 422. Files and Streams  Opening files  Create objects from template  Derive from stream classes  Can use stream methods : put, get, peek, etc. basic_fstream basic_ios basic_ifstream basic_ofstreambasic_iostream basic_istream basic_ostream
  • 423. Creating a Sequential-Access File  C++ imposes no structure on file  Concept of "record" must be implemented by programmer  To open file, create objects  Creates "line of communication" from object to file  Classes  ifstream (input only)  ofstream (output only)  fstream (I/O)  Constructors take file name and file-open mode ofstream outClientFile( "filename", fileOpenMode );  To attach a file later Ofstream outClientFile; outClientFile.open( "filename", fileOpenMode);
  • 424. Creating a Sequential-Access File  File-open modes  ofstream opened for output by default  ofstream outClientFile( "clients.dat", ios::out );  ofstream outClientFile( "clients.dat"); Mode Description ios::app Write all output to the end of the file. ios::ate Open a file for output and move to the end of the file (normally used to append data to a file). Data can be written anywhere in the file. ios::in Open a file for input. ios::out Open a file for output. ios::trunc Discard the file’s contents if it exists (this is also the default action for ios::out) ios::binary Open a file for binary (i.e., non-text) input or output.
  • 425. Creating a Sequential-Access File  Operations  Overloaded operator!  !outClientFile  Returns nonzero (true) if badbit or failbit set Opened non-existent file for reading, wrong permissions  Overloaded operator void*  Converts stream object to pointer  0 when failbit or badbit set, otherwise nonzero failbit set when EOF found  while ( cin >> myVariable ) Implicitly converts cin to pointer Loops until EOF  Writing to file (just like cout)  outClientFile << myVariable  Closing file  outClientFile.close()  Automatically closed when destructor called
  • 426. 1 // Example 87 2 // Create a sequential file. 3 #include <iostream> 4 5 using std::cout; 6 using std::cin; 7 using std::ios; 8 using std::cerr; 9 using std::endl; 10 11 #include <fstream> 12 13 using std::ofstream; 14 15 #include <cstdlib> // exit prototype 16 17 int main() 18 { 19 // ofstream constructor opens file 20 ofstream outClientFile( "clients.dat", ios::out ); 21 22 // exit program if unable to create file 23 if ( !outClientFile ) { // overloaded ! operator 24 cerr << "File could not be opened" << endl; 25 exit( 1 ); 26 27 } // end if Notice the the header files required for file I/O. ofstream object created and used to open file "clients.dat". If the file does not exist, it is created. ! operator used to test if the file opened properly.
  • 427. 28 29 cout << "Enter the account, name, and balance." << endl 30 << "Enter end-of-file to end input.n? "; 31 32 int account; 33 char name[ 30 ]; 34 double balance; 35 36 // read account, name and balance from cin, then place in file 37 while ( cin >> account >> name >> balance ) { 38 outClientFile << account << ' ' << name << ' ' << balance 39 << endl; 40 cout << "? "; 41 42 } // end while 43 44 return 0; // ofstream destructor closes file 45 46 } // end main cin is implicitly converted to a pointer. When EOF is encountered, it returns 0 and the loop stops. Write data to file like a regular stream. File closed when destructor called for object. Can be explicitly closed with close().
  • 428. Enter the account, name, and balance. Enter end-of-file to end input. ? 100 Jones 24.98 ? 200 Doe 345.67 ? 300 White 0.00 ? 400 Stone -42.16 ? 500 Rich 224.62 ? ^Z
  • 429. Reading Data from a Sequential- Access File  Reading files  ifstream inClientFile( "filename", ios::in );  Overloaded !  !inClientFile tests if file was opened properly  operator void* converts to pointer  while (inClientFile >> myVariable)  Stops when EOF found (gets value 0)
  • 430. 28 int main() 29 { 30 // ifstream constructor opens the file 31 ifstream inClientFile( "clients.dat", ios::in ); 32 33 // exit program if ifstream could not open file 34 if ( !inClientFile ) { 35 cerr << "File could not be opened" << endl; 36 exit( 1 ); 37 38 } // end if 39 40 int account; 41 char name[ 30 ]; 42 double balance; 43 44 cout << left << setw( 10 ) << "Account" << setw( 13 ) 45 << "Name" << "Balance" << endl << fixed << showpoint; 46 47 // display each record in file 48 while ( inClientFile >> account >> name >> balance ) 49 outputLine( account, name, balance ); 50 51 return 0; // ifstream destructor closes the file 52 53 } // end main Open and test file for input. Read from file until EOF found.
  • 431. 54 55 // display single record from file 56 void outputLine( int account, const char * const name, 57 double balance ) 58 { 59 cout << left << setw( 10 ) << account << setw( 13 ) << name 60 << setw( 7 ) << setprecision( 2 ) << right << balance 61 << endl; 62 63 } // end function outputLine Account Name Balance 100 Jones 24.98 200 Doe 345.67 300 White 0.00 400 Stone -42.16 500 Rich 224.62
  • 432. Reading Data from a Sequential- Access File  File position pointers  Number of next byte to read/write  Functions to reposition pointer  seekg (seek get for istream class)  seekp (seek put for ostream class)  Classes have "get" and "put" pointers  seekg and seekp take offset and direction  Offset: number of bytes relative to direction  Direction (ios::beg default) ios::beg - relative to beginning of stream ios::cur - relative to current position ios::end - relative to end
  • 433. Reading Data from a Sequential- Access File  Examples  fileObject.seekg(0)  Goes to front of file (location 0) because ios::beg is default  fileObject.seekg(n)  Goes to nth byte from beginning  fileObject.seekg(n, ios::cur)  Goes n bytes forward  fileObject.seekg(y, ios::end)  Goes y bytes back from end  fileObject.seekg(0, ios::cur)  Goes to last byte  seekp similar  To find pointer location  tellg and tellp  location = fileObject.tellg()
  • 434. Updating Sequential-Access Files  Updating sequential files  Risk overwriting other data  Example: change name "White" to "Worthington"  Old data 300 White 0.00 400 Jones 32.87  Insert new data  Formatted text different from internal representation  Problem can be avoided, but awkward 300 White 0.00 400 Jones 32.87 300 Worthington 0.00ones 32.87 300 Worthington 0.00 Data gets overwritten
  • 435. Random-Access Files  Instant access  Want to locate record quickly  Airline reservations, ATMs  Sequential files must search through each one  Random-access files are solution  Instant access  Insert record without destroying other data  Update/delete items without changing other data
  • 436. Random-Access Files  C++ imposes no structure on files  Programmer must create random-access files  Simplest way: fixed-length records  Calculate position in file from record size and key 0 200 300 400 500 byte offsets } } } } } } } 100 100 bytes 100 bytes 100 bytes 100 bytes 100 bytes 100 bytes
  • 437. Creating a Random-Access File  "1234567" (char *) vs 1234567 (int)  char * takes 8 bytes (1 for each character + null)  int takes fixed number of bytes (perhaps 4)  123 same size in bytes as 1234567  << operator and write()  outFile << number  Outputs number (int) as a char *  Variable number of bytes  outFile.write( const char *, size );  Outputs raw bytes  Takes pointer to memory location, number of bytes to write Copies data directly from memory into file Does not convert to char *
  • 438. Creating a Random-Access File  Example outFile.write( reinterpret_cast<const char *>(&number), sizeof( number ) );  &number is an int *  Convert to const char * with reinterpret_cast  sizeof(number)  Size of number (an int) in bytes  read function similar (more later)  Must use write/read between compatible machines  Only when using raw, unformatted data  Use ios::binary for raw writes/reads  Usually write entire struct or object to file
  • 439. Writing Data Randomly to a Random-Access File  Use seekp to write to exact location in file  Where does the first record begin?  Byte 0  The second record?  Byte 0 + sizeof(object)  Any record?  (Recordnum - 1) * sizeof(object)  read - similar to write  Reads raw bytes from file into memory  inFile.read( reinterpret_cast<char *>( &number ), sizeof( int ) );  &number: location to store data  sizeof(int): how many bytes to read  Do not use inFile >> number with raw bytes  >> expects char *
  • 440. Input/Output of Objects  I/O of objects  Chapter 8 (overloaded >>)  Only object's data transmitted  Member functions available internally  When objects stored in file, lose type info (class, etc.)  Program must know type of object when reading  One solution  When writing, output object type code before real object  When reading, read type code Call proper overloaded function (switch)
  • 441. Program Design and Software Tools Exception Handling Exception Handling
  • 442. Introduction  Exceptions  Indicates problem occurred in program  Not common  An "exception" to a program that usually works  Exception Handling  Resolve exceptions  Program may be able to continue  Controlled termination  Write fault-tolerant programs
  • 443. Exception-Handling Overview  Consider pseudocode Perform a task If the preceding task did not execute correctly Perform error processing Perform next task If the preceding task did not execute correctly Perform error processing  Mixing logic and error handling  Can make program difficult to read/debug  Exception handling removes error correction from "main line" of program
  • 444. Exception-Handling Overview  Exception handling  For synchronous errors (divide by zero, null pointer)  Cannot handle asynchronous errors (independent of program)  Disk I/O, mouse, keyboard, network messages  Easy to handle errors  Terminology  Function that has error throws an exception  Exception handler (if it exists) can deal with problem  Catches and handles exception  If no exception handler, uncaught exception  Could terminate program
  • 445. Exception-Handling Overview  C++ code try { code that may raise exception } catch (exceptionType){ code to handle exception }  try block encloses code that may raise exception  One or more catch blocks follow  Catch and handle exception, if appropriate  Take parameter; if named, can access exception object
  • 446. Exception-Handling Overview  Throw point  Location in try block where exception occurred  If exception handled  Program skips remainder of try block  Resumes after catch blocks  If not handled  Function terminates  Looks for enclosing catch block (stack unwinding)  If no exception  Program skips catch blocks
  • 447. Other Error-Handling Techniques  Ignore exception  Typical for personal (not commercial) software  Program may fail  Abort program  Usually appropriate  Not appropriate for mission-critical software  Set error indicators  Unfortunately, may not test for these when necessary  Test for error condition  Call exit (<cstdlib>) and pass error code
  • 448. Other Error-Handling Techniques  setjump and longjump  <csetjmp>  Jump from deeply nested function to call error handler  Can be dangerous  Dedicated error handling  new can have a special handler
  • 449. Simple Exception-Handling Example: Divide by Zero  Keyword throw  Throws an exception  Use when error occurs  Can throw almost anything (exception object, integer, etc.)  throw myObject;  throw 5;  Exception objects  Base class runtime_error ( <stdexcept> )  Constructor can take a string (to describe exception)  Member function what() returns that string
  • 450. Simple Exception-Handling Example: Divide by Zero  Upcoming example  Handle divide-by-zero errors  Define new exception class  DivideByZeroException  Inherit from runtime_error  In division function  Test denominator  If zero, throw exception (throw object)  In try block  Attempt to divide  Have enclosing catch block Catch DivideByZeroException objects
  • 451. 1 // Example 88 2 // A simple exception-handling example that checks for 3 // divide-by-zero exceptions. 4 #include <iostream> 5 6 using std::cout; 7 using std::cin; 8 using std::endl; 9 10 #include <exception> 11 12 using std::exception; 13 14 // DivideByZeroException objects should be thrown by functions 15 // upon detecting division-by-zero exceptions 16 class DivideByZeroException : public runtime_error { 17 18 public: 19 20 // constructor specifies default error message 21 DivideByZeroException::DivideByZeroException() 22 : exception( "attempted to divide by zero" ) {} 23 24 }; // end class DivideByZeroException 25 Define new exception class (inherit from runtime_error ). Pass a descriptive message to the constructor.
  • 452. 26 // perform division and throw DivideByZeroException object if 27 // divide-by-zero exception occurs 28 double quotient( int numerator, int denominator ) 29 { 30 // throw DivideByZeroException if trying to divide by zero 31 if ( denominator == 0 ) 32 throw DivideByZeroException(); // terminate function 33 34 // return division result 35 return static_cast< double >( numerator ) / denominator; 36 37 } // end function quotient 38 39 int main() 40 { 41 int number1; // user-specified numerator 42 int number2; // user-specified denominator 43 double result; // result of division 44 45 cout << "Enter two integers (end-of-file to end): "; 46 If the denominator is zero, throw a DivideByZeroException object.
  • 453. 47 // enable user to enter two integers to divide 48 while ( cin >> number1 >> number2 ) { 49 50 // try block contains code that might throw exception 51 // and code that should not execute if an exception occurs 52 try { 53 result = quotient( number1, number2 ); 54 cout << "The quotient is: " << result << endl; 55 56 } // end try 57 58 // exception handler handles a divide-by-zero exception 59 catch ( DivideByZeroException &divideByZeroException ) { 60 cout << "Exception occurred: " 61 << divideByZeroException.what() << endl; 62 63 } // end catch 64 65 cout << "nEnter two integers (end-of-file to end): "; 66 67 } // end while 68 69 cout << endl; 70 71 return 0; // terminate normally 72 73 } // end main Notice the structure of the try and catch blocks. The catch block can catch DivideByZeroException objects, and print an error message. If no exception occurs, the catch block is skipped. Member function what returns the string describing the exception.
  • 454. Enter two integers (end-of-file to end): 100 7 The quotient is: 14.2857 Enter two integers (end-of-file to end): 100 0 Exception occurred: attempted to divide by zero Enter two integers (end-of-file to end): ^Z
  • 455. Rethrowing an Exception  Rethrowing exceptions  Use when exception handler cannot process exception  Can still rethrow if handler did some processing  Can rethrow exception to another handler  Goes to next enclosing try block  Corresponding catch blocks try to handle  To rethrow  Use statement "throw;"  No arguments  Terminates function
  • 456. 1 // Example 89 2 // Demonstrating exception rethrowing. 3 #include <iostream> 4 5 using std::cout; 6 using std::endl; 7 8 #include <exception> 9 10 using std::exception; 11 12 // throw, catch and rethrow exception 13 void throwException() 14 { 15 // throw exception and catch it immediately 16 try { 17 cout << " Function throwException throws an exceptionn"; 18 throw exception(); // generate exception 19 20 } // end try 21 22 // handle exception 23 catch ( exception &caughtException ) { 24 cout << " Exception handled in function throwException" 25 << "n Function throwException rethrows exception"; 26 27 throw; // rethrow exception for further processing 28 29 } // end catch Exception handler generates a default exception (base class exception). It immediately catches and rethrows it (note use of throw;).
  • 457. 30 31 cout << "This also should not printn"; 32 33 } // end function throwException 34 35 int main() 36 { 37 // throw exception 38 try { 39 cout << "nmain invokes function throwExceptionn"; 40 throwException(); 41 cout << "This should not printn"; 42 43 } // end try 44 45 // handle exception 46 catch ( exception &caughtException ) { 47 cout << "nnException handled in mainn"; 48 49 } // end catch 50 51 cout << "Program control continues after catch in mainn"; 52 53 return 0; 54 55 } // end main This should never be reached, since the throw immediately exits the function. throwException rethrows an exception to main. It is caught and handled.
  • 458. main invokes function throwException Function throwException throws an exception Exception handled in function throwException Function throwException rethrows exception Exception handled in main Program control continues after catch in main
  • 459. Exception Specifications  List of exceptions function can throw  Also called throw list int someFunction( double value ) throw ( ExceptionA, ExceptionB, ExceptionC ) { // function body }  Can only throw ExceptionA, ExceptionB, and ExceptionC (and derived classes)  If throws other type, function unexpected called  By default, terminates program (more 13.7)  If no throw list, can throw any exception  If empty throw list, cannot throw any exceptions
  • 460. Processing Unexpected Exceptions  Function unexpected  Calls function registered with set_unexpected  <exception>  Calls terminate by default  set_terminate  Sets what function terminate calls  By default, calls abort If redefined, still calls abort after new function finishes  Arguments for set functions  Pass pointer to function  Function must take no arguments  Returns void
  • 461. Stack Unwinding  If exception thrown but not caught  Goes to enclosing try block  Terminates current function  Unwinds function call stack  Looks for try/catch that can handle exception  If none found, unwinds again  If exception never caught  Calls terminate
  • 462. 1 // Example 90 2 // Demonstrating stack unwinding. 3 #include <iostream> 4 5 using std::cout; 6 using std::endl; 7 8 #include <stdexcept> 9 10 using std::runtime_error; 11 12 // function3 throws run-time error 13 void function3() throw ( runtime_error ) 14 { 15 throw runtime_error( "runtime_error in function3" ); // fourth 16 } 17 18 // function2 invokes function3 19 void function2() throw ( runtime_error ) 20 { 21 function3(); // third 22 } 23 Note the use of the throw list. Throws a runtime error exception, defined in <stdexcept>.
  • 463. 24 // function1 invokes function2 25 void function1() throw ( runtime_error ) 26 { 27 function2(); // second 28 } 29 30 // demonstrate stack unwinding 31 int main() 32 { 33 // invoke function1 34 try { 35 function1(); // first 36 37 } // end try 38 39 // handle run-time error 40 catch ( runtime_error &error ) // fifth 41 { 42 cout << "Exception occurred: " << error.what() << endl; 43 44 } // end catch 45 46 return 0; 47 48 } // end main Exception occurred: runtime_error in function3 function1 calls function2 which calls function3. The exception occurs, and unwinds until an appropriate try/catch block can be found.
  • 464. Constructors, Destructors and Exception Handling  Error in constructor  new fails; cannot allocate memory  Cannot return a value - how to inform user?  Hope user examines object, notices errors  Set some global variable  Good alternative: throw an exception  Destructors automatically called for member objects  Called for automatic variables in try block  Can catch exceptions in destructor
  • 465. Exceptions and Inheritance  Exception classes  Can be derived from base classes  I.e., runtime_error; exception  If catch can handle base class, can handle derived classes  Polymorphic programming
  • 466. Processing new Failures  When new fails to get memory  Should throw bad_alloc exception  Defined in <new>  Some compilers have new return 0  Result depends on compiler
  • 467. 1 // Example 91 2 // Demonstrating pre-standard new returning 0 when memory 3 // is not allocated. 4 #include <iostream> 5 6 using std::cout; 7 8 int main() 9 { 10 double *ptr[ 50 ]; 11 12 // allocate memory for ptr 13 for ( int i = 0; i < 50; i++ ) { 14 ptr[ i ] = new double[ 5000000 ]; 15 16 // new returns 0 on failure to allocate memory 17 if ( ptr[ i ] == 0 ) { 18 cout << "Memory allocation failed for ptr[ " 19 << i << " ]n"; 20 21 break; 22 23 } // end if 24 Demonstrating new that returns 0 on allocation failure.
  • 468. 25 // successful memory allocation 26 else 27 cout << "Allocated 5000000 doubles in ptr[ " 28 << i << " ]n"; 29 30 } // end for 31 32 return 0; 33 34 } // end main Allocated 5000000 doubles in ptr[ 0 ] Allocated 5000000 doubles in ptr[ 1 ] Allocated 5000000 doubles in ptr[ 2 ] Allocated 5000000 doubles in ptr[ 3 ] Memory allocation failed for ptr[ 4 ]
  • 469. 1 // Example 92 2 // Demonstrating standard new throwing bad_alloc when memory 3 // cannot be allocated. 4 #include <iostream> 5 6 using std::cout; 7 using std::endl; 8 9 #include <new> // standard operator new 10 11 using std::bad_alloc; 12 13 int main() 14 { 15 double *ptr[ 50 ]; 16 17 // attempt to allocate memory 18 try { 19 20 // allocate memory for ptr[ i ]; new throws bad_alloc 21 // on failure 22 for ( int i = 0; i < 50; i++ ) { 23 ptr[ i ] = new double[ 5000000 ]; 24 cout << "Allocated 5000000 doubles in ptr[ " 25 << i << " ]n"; 26 } 27 28 } // end try Demonstrating new that throws an exception.
  • 470. 29 30 // handle bad_alloc exception 31 catch ( bad_alloc &memoryAllocationException ) { 32 cout << "Exception occurred: " 33 << memoryAllocationException.what() << endl; 34 35 } // end catch 36 37 return 0; 38 39 } // end main Allocated 5000000 doubles in ptr[ 0 ] Allocated 5000000 doubles in ptr[ 1 ] Allocated 5000000 doubles in ptr[ 2 ] Allocated 5000000 doubles in ptr[ 3 ] Exception occurred: Allocation Failure
  • 471. Processing new Failures  set_new_handler  Header <new>  Register function to call when new fails  Takes function pointer to function that  Takes no arguments  Returns void  Once registered, function called instead of throwing exception
  • 472. 1 // Example 93 2 // Demonstrating set_new_handler. 3 #include <iostream> 4 5 using std::cout; 6 using std::cerr; 7 8 #include <new> // standard operator new and set_new_handler 9 10 using std::set_new_handler; 11 12 #include <cstdlib> // abort function prototype 13 14 void customNewHandler() 15 { 16 cerr << "customNewHandler was called"; 17 abort(); 18 } 19 20 // using set_new_handler to handle failed memory allocation 21 int main() 22 { 23 double *ptr[ 50 ]; 24 The custom handler must take no arguments and return void.
  • 473. 25 // specify that customNewHandler should be called on failed 26 // memory allocation 27 set_new_handler( customNewHandler ); 28 29 // allocate memory for ptr[ i ]; customNewHandler will be 30 // called on failed memory allocation 31 for ( int i = 0; i < 50; i++ ) { 32 ptr[ i ] = new double[ 5000000 ]; 33 34 cout << "Allocated 5000000 doubles in ptr[ " 35 << i << " ]n"; 36 37 } // end for 38 39 return 0; 40 41 } // end main Allocated 5000000 doubles in ptr[ 0 ] Allocated 5000000 doubles in ptr[ 1 ] Allocated 5000000 doubles in ptr[ 2 ] Allocated 5000000 doubles in ptr[ 3 ] customNewHandler was called Note call to set_new_handler.
  • 474. Class auto_ptr and Dynamic Memory Allocation  Declare pointer, allocate memory with new  What if exception occurs before you can delete it?  Memory leak  Template class auto_ptr  Header <memory>  Like regular pointers (has * and ->)  When pointer goes out of scope, calls delete  Prevents memory leaks  Usage auto_ptr< MyClass > newPointer( new MyClass() );  newPointer points to dynamically allocated object
  • 475. 1 // Example 94 2 // Demonstrating auto_ptr. 3 #include <iostream> 4 5 using std::cout; 6 using std::endl; 7 8 #include <memory> 9 10 using std::auto_ptr; // auto_ptr class definition 11 12 class Integer { 13 14 public: 15 16 // Integer constructor 17 Integer( int i = 0 ) 18 : value( i ) 19 { 20 cout << "Constructor for Integer " << value << endl; 21 22 } // end Integer constructor 23
  • 476. 24 // Integer destructor 25 ~Integer() 26 { 27 cout << "Destructor for Integer " << value << endl; 28 29 } // end Integer destructor 30 31 // function to set Integer 32 void setInteger( int i ) 33 { 34 value = i; 35 36 } // end function setInteger 37 38 // function to return Integer 39 int getInteger() const 40 { 41 return value; 42 43 } // end function getInteger 44 45 private: 46 int value; 47 48 }; // end class Integer 49
  • 477. 50 // use auto_ptr to manipulate Integer object 51 int main() 52 { 53 cout << "Creating an auto_ptr object that points to an " 54 << "Integern"; 55 56 // "aim" auto_ptr at Integer object 57 auto_ptr< Integer > ptrToInteger( new Integer( 7 ) ); 58 59 cout << "nUsing the auto_ptr to manipulate the Integern"; 60 61 // use auto_ptr to set Integer value 62 ptrToInteger->setInteger( 99 ); 63 64 // use auto_ptr to get Integer value 65 cout << "Integer after setInteger: " 66 << ( *ptrToInteger ).getInteger() 67 << "nnTerminating program" << endl; 68 69 return 0; 70 71 } // end main Create an auto_ptr. It can be manipulated like a regular pointer. delete not explicitly called, but the auto_ptr will be destroyed once it leaves scope. Thus, the destructor for class Integer will be called.
  • 478. Creating an auto_ptr object that points to an Integer Constructor for Integer 7 Using the auto_ptr to manipulate the Integer Integer after setInteger: 99 Terminating program Destructor for Integer 99
  • 479. Standard Library Exception Hierarchy  Exception hierarchy  Base class exception (<exception>)  Virtual function what, overridden to provide error messages  Sample derived classes  runtime_error, logic_error  bad_alloc, bad_cast, bad_typeid Thrown by new, dynamic_cast and typeid  To catch all exceptions  catch(...)  catch( exception AnyException)  Will not catch user-defined exceptions
  • 480. Program Design and Software Tools Preprocessing Preprocessing
  • 481. Preprocessing  Preprocessing  Occurs before program compiled  Inclusion of external files  Definition of symbolic constants  Macros  Conditional compilation  Conditional execution pf preprocessing directive  All directives begin with #  Can only have whitespace before directives  Directives not C++ statements  Do not end with ;
  • 482. The #include Preprocessor Directive  #include directive  Puts copy of file in place of directive  Two forms  #include <filename> For standard library header files Searches pre-designated directories  #include "filename" Searches in current directory Normally used for programmer-defined files  Usage  Loading header files  #include <iostream>  Programs with multiple source files  Header file  Has common declarations and definitions  Classes, structures, enumerations, function prototypes  Extract commonality of multiple program files
  • 483. The #define Preprocessor Directive: Symbolic Constants  #define  Symbolic constants  Constants represented as symbols  When program compiled, all occurrences replaced  Format  #define identifier replacement-text  #define PI 3.14159  Everything to right of identifier replaces text  #define PI=3.14159  Replaces PI with "=3.14159"  Probably an error  Cannot redefine symbolic constants  Advantage: Takes no memory  Disadvantages  Name not seen by debugger (only replacement text)  Do not have specific data type  const variables preferred
  • 484. The #define Preprocessor Directive: Macros  Macro  Operation specified in #define  Macro without arguments  Treated like a symbolic constant  Macro with arguments  Arguments substituted for replacement text  Macro expanded  Performs a text substitution  No data type checking
  • 485. The #define Preprocessor Directive: Macros  Example #define CIRCLE_AREA( x ) ( PI * ( x ) * ( x ) ) area = CIRCLE_AREA( 4 ); becomes area = ( 3.14159 * ( 4 ) * ( 4 ) );  Use parentheses  Without them, #define CIRCLE_AREA( x ) PI * x * x area = CIRCLE_AREA( c + 2 ); becomes area = 3.14159 * c + 2 * c + 2; which evaluates incorrectly
  • 486. The #define Preprocessor Directive: Macros  Multiple arguments #define RECTANGLE_AREA( x, y ) ( ( x ) * ( y ) ) rectArea = RECTANGLE_AREA( a + 4, b + 7 ); becomes rectArea = ( ( a + 4 ) * ( b + 7 ) );  #undef  Undefines symbolic constant or macro  Can later be redefined
  • 487. Conditional Compilation  Control preprocessor directives and compilation  Cannot evaluate cast expressions, sizeof, enumeration constants  Structure similar to if #if !defined( NULL ) #define NULL 0 #endif  Determines if symbolic constant NULL defined  If NULL defined,  defined( NULL ) evaluates to 1  #define statement skipped  Otherwise  #define statement used  Every #if ends with #endif
  • 488. Conditional Compilation  Can use else  #else  #elif is "else if"  Abbreviations  #ifdef short for  #if defined(name)  #ifndef short for  #if !defined(name)  "Comment out" code  Cannot use /* ... */ with C-style comments  Cannot nest /* */  Instead, use #if 0 code commented out #endif  To enable code, change 0 to 1
  • 489. Conditional Compilation  Debugging #define DEBUG 1 #ifdef DEBUG cerr << "Variable x = " << x << endl; #endif  Defining DEBUG enables code  After code corrected  Remove #define statement  Debugging statements are now ignored
  • 490. The #error and #pragma Preprocessor Directives  #error tokens  Prints implementation-dependent message  Tokens are groups of characters separated by spaces  #error 1 - Out of range error has 6 tokens  Compilation may stop (depends on compiler)  #pragma tokens  Actions depend on compiler  May use compiler-specific options  Unrecognized #pragmas are ignored
  • 491. The # and ## Operators  # operator  Replacement text token converted to string with quotes #define HELLO( x ) cout << "Hello, " #x << endl;  HELLO( JOHN ) becomes  cout << "Hello, " "John" << endl;  Same as cout << "Hello, John" << endl;  ## operator  Concatenates two tokens #define TOKENCONCAT( x, y ) x ## y  TOKENCONCAT( O, K ) becomes  OK
  • 492. Line Numbers  #line  Renumbers subsequent code lines, starting with integer  #line 100  File name can be included  #line 100 "file1.cpp"  Next source code line is numbered 100  For error purposes, file name is "file1.cpp"  Can make syntax errors more meaningful  Line numbers do not appear in source file
  • 493. Predefined Symbolic Constants  Five predefined symbolic constants  Cannot be used in #define or #undef Symbolic constant Description __LINE__ The line number of the current source code line (an integer constant). __FILE__ The presumed name of the source file (a string). __DATE__ The date the source file is compiled (a string of the form "Mmm dd yyyy" such as "Jan 19 2001"). __TIME__ The time the source file is compiled (a string literal of the form "hh:mm:ss").
  • 494. Assertions  assert is a macro  Header <cassert>  Tests value of an expression  If 0 (false) prints error message, calls abort Terminates program, prints line number and file Good for checking for illegal values  If 1 (true), program continues as normal  assert( x <= 10 );  To remove assert statements  No need to delete them manually  #define NDEBUG  All subsequent assert statements ignored
  • 495. Program Design and Software Tools Unified Modeling Language Unified Modeling Language
  • 496. What is UML? The Unified Modelling Language is a standard notation to model [object oriented] systems. Syntax and semantics Model systems Visual documentations Collections of best practices Used to produce a set of artifacts that can be delivered Wide support Independent of programming languages Support high level concepts
  • 497. UML Diagram Types Use Case diagrams Static structure diagrams Class diagrams Object diagrams Interaction diagrams Sequence diagrams Collaboration diagrams Statechart diagrams Activity diagrams Component diagrams Deployment diagram
  • 498. Copyright © 1997 by Rational Software Corporation Actors  An actor is someone or some thing that must interact with the system under development Student Registrar Professor Billing System
  • 499. Use Cases  A use case is a pattern of behavior the system exhibits  Each use case is a sequence of related transactions performed by an actor and the system in a dialogue  Actors are examined to determine their needs  Registrar -- maintain the curriculum  Professor -- request roster  Student -- maintain schedule Maintain ScheduleMaintain Curriculum Request Course Roster
  • 500. Use Case Diagram  Use case diagrams are created to visualize the relationships between actors and use cases Student Registrar Professor Maintain Schedule Maintain Curriculum Request Course Roster Billing System
  • 501. Use Case Realizations  The use case diagram presents an outside view of the system  Interaction diagrams describe how use cases are realized as interactions among societies of objects  Two types of interaction diagrams  Sequence diagrams  Collaboration diagrams
  • 502. Class Diagram Class diagrams are the most commonly used diagrams in UML. Class diagrams are for visualizing, specifying and documenting the system from a static perspective. Class diagrams indicate which classes know about other classes and, if they do, what type of relationship exists. Class diagrams will have different levels of detail (abstraction) depending on where we are in the software development process.
  • 503. Class Diagrams Class diagrams describe types of objects in a system and their relationships. There are three types of relationships between classes: • Dependency (“uses”) • Aggregation (“has”) • Inheritance (“is”) Class diagrams also show the attributes and operations of a class.
  • 504. Class Diagrams Class diagrams consist of several classes connected with relationships Representation of a class:
  • 506. Convention Name of class is a word with initial upper case letter Capitalize first letter of every word in name Name of attributes is lower case letter Capitalize first letter of every word other than first Operations have same naming schemes as attributes Brackets include parameter operation works on
  • 507. Associations  “relationship between different objects of one or more classes”
  • 511. Class  Derived from the CRC Cards  Sections: name, attributes, operations Construct Description Syntax class a description of a set of objects that share the same attributes, operations, methods, relationships and semantics. Name Attributes Methods
  • 512. Association  It is more important to identify classes than to identify associations  Too many associations can be confusing  Classes may have association with themselves person manages 1* Construct Description Syntax association a relationship between two or more classifiers that involves connections among their instances.
  • 513. Generalization Generalization: identifying commonality among classes Construct Description Syntax generalization a taxonomic relationship between a more general and a more specific element.
  • 514. Aggregation A composite aggregation (filled diamond) means that the multiplicity at the composite end may be at most one. Shared aggregation (hollow diamond) means that the multiplicity at the composite end may be more than one. Construct Description Syntax aggregation A special form of association that specifies a whole-part relationship between the aggregate (whole) and the component part.
  • 515. Aggregation Guidelines There is an obvious physical or logical assembly The part and composite have the same lifetime Operations applied to the composite propagate to the parts e.g. destruction, movement, etc.
  • 517. Classifier A classifier is a mechanism that describes structural and behavioral features. Types of classifiers are … classes, interfaces, datatypes, signals, components, nodes, use cases and subsystems. Classes are the most important kind of classifier. Classes have a number of features beyond attributes and behaviors that allow you to model some of the more subtle/advanced features of a system.
  • 519. Abstract and Concrete Classes and Operations
  • 520. Template Icon  A parameterized element.  Represented in UML as a dashed box in the upper right- hand corner of the class icon, which lists the template parameters.
  • 521. State Transition Diagram Initialization Open entry: Register student exit: Increment count Closed Canceled do: Initialize course do: Finalize course do: Notify registered students Add Student / Set count = 0 Add student[ count < 10 ] [ count = 10 ] Cancel Cancel Cancel
  • 522. Sequence Diagram  A sequence diagram displays object interactions arranged in a time sequence : Student registration form registration manager math 101 1: fill in info 2: submit 3: add course(joe, math 01) 4: are you open? 5: are you open? 6: add (joe) 7: add (joe) math 101 section 1
  • 523. : Registrar course form : CourseForm theManager : CurriculumManager aCourse : Course 1: set course info 2: process 3: add course 4: new course Collaboration Diagram  A collaboration diagram displays object interactions organized around objects and their links to one another
  • 524. The Physical World  Component diagrams illustrate the organizations and dependencies among software components  A component may be  A source code component  A run time components or  An executable component
  • 526. Deploying the System  The deployment diagram shows the configuration of run-time processing elements and the software processes living on them  The deployment diagram visualizes the distribution of components across the enterprise.
  • 528. Review topics 1. Lvalue/rvalue 2. Reference variable + Calling functions by reference 3. Passing arrays to functions 4. Function pointers 5. Arrays of pointers to functions (e.g. menus) 6. Using member selection operators ('.' '->') 7. Returning a reference to a private data member 8. *this pointer 1. implicit & explicit use of *this pointer 2. *this pointer & cascaded function calls 9. When are destructors used, why not yet in the classes we're creating? 10. When is it appropriate to use 'new' and 'delete' from the <new> library? 11. Classes? 12. Polymorphism? 13. Multiple Inheritance?
  • 529. Confusing Equality (==) and Assignment (=) Operators  Lvalues  Expressions that can appear on left side of equation  Can be changed x = 4;  Rvalues  Only appear on right side of equation  Constants, such as numbers (i.e. cannot write 4 = x;)  Lvalues can be used as rvalues, but not vice versa
  • 530. References and Reference Parameters  Call by value  Copy of data passed to function  Changes to copy do not change original  Prevent unwanted side effects  Call by reference  Function can directly access data  Changes affect original  Reference parameter  Alias for argument in function call  Passes parameter by reference  Use & after data type in prototype  void myFunction( int &data )  Read “data is a reference to an int”  Function call format the same  However, original can now be changed
  • 531. References and Reference Parameters  Pointers  Another way to pass-by-refernce  References as aliases to other variables  Refer to same variable  Can be used within a function int count = 1; // declare integer variable count int &cRef = count; // create cRef as an alias for count ++cRef; // increment count (using its alias)  References must be initialized when declared  Otherwise, compiler error  Dangling reference  Reference to undefined variable
  • 532. Passing Arrays to Functions  Specify name without brackets  To pass array myArray to myFunction int myArray[ 24 ]; myFunction( myArray, 24 );  Array size usually passed, but not required  Useful to iterate over all elements  Arrays passed-by-reference  Functions can modify original array data  Value of name of array is address of first element  Function knows where the array is stored  Can change original memory locations
  • 533. Passing Arrays to Functions  Functions taking arrays  Function prototype  void modifyArray( int b[], int arraySize );  void modifyArray( int [], int ); Names optional in prototype  Both take an integer array and a single integer  No need for array size between brackets  Ignored by compiler  If declare array parameter as const  Cannot be modified (compiler error)  void doNotModify( const int [] );
  • 534. Using const with Pointers const qualifier Value of variable should not be modified const used when function does not need to change a variable Principle of least privilege const pointers Always point to same memory location Default for array name Must be initialized when declared Four ways to pass pointer to function Nonconstant pointer to nonconstant data  Highest amount of access Nonconstant pointer to constant data Constant pointer to nonconstant data Constant pointer to constant data  Least amount of access
  • 535. 1 // Example 95 2 // Attempting to modify a constant pointer to 3 // non-constant data. 4 5 int main() 6 { 7 int x, y; 8 9 // ptr is a constant pointer to an integer that can 10 // be modified through ptr, but ptr always points to the 11 // same memory location. 12 int * const ptr = &x; 13 14 *ptr = 7; // allowed: *ptr is not const 15 ptr = &y; // error: ptr is const; cannot assign new address 16 17 return 0; // indicates successful termination 18 19 } // end main ptr is constant pointer to integer.Can modify x (pointed to by ptr) since x not constant.Cannot modify ptr to point to new address since ptr is constant. Line 15 generates compiler error by attempting to assign new address to constant pointer. d:cpphtp4_examplesch05Fig05_13.cpp(15) : error C2166: l-value specifies const object
  • 536. 1 // Example 96 2 // Attempting to modify a constant pointer to constant data. 3 #include <iostream> 4 5 using std::cout; 6 using std::endl; 7 8 int main() 9 { 10 int x = 5, y; 11 12 // ptr is a constant pointer to a constant integer. 13 // ptr always points to the same location; the integer 14 // at that location cannot be modified. 15 const int *const ptr = &x; 16 17 cout << *ptr << endl; 18 19 *ptr = 7; // error: *ptr is const; cannot assign new value 20 ptr = &y; // error: ptr is const; cannot assign new address 21 22 return 0; // indicates successful termination 23 24 } // end main ptr is constant pointer to integer constant. Cannot modify x (pointed to by ptr) since *ptr declared constant. Cannot modify ptr to point to new address since ptr is constant.
  • 537. Relationship Between Pointers and Arrays  Arrays and pointers closely related  Array name like constant pointer  Pointers can do array subscripting operations  Accessing array elements with pointers  Element b[ n ] can be accessed by *( bPtr + n )  Called pointer/offset notation  Addresses  &b[ 3 ] same as bPtr + 3  Array name can be treated as pointer  b[ 3 ] same as *( b + 3 )  Pointers can be subscripted (pointer/subscript notation)  bPtr[ 3 ] same as b[ 3 ]
  • 538. Function Pointers  Calling functions using pointers  Assume parameter:  bool ( *compare ) ( int, int )  Execute function with either  ( *compare ) ( int1, int2 ) Dereference pointer to function to execute OR  compare( int1, int2 ) Could be confusing  User may think compare name of actual function in program
  • 539. 1 //Example 97 2 // Multipurpose sorting program using function pointers. 3 #include <iostream> 4 5 using std::cout; 6 using std::cin; 7 using std::endl; 8 9 #include <iomanip> 10 11 using std::setw; 12 13 // prototypes 14 void bubble( int [], const int, bool (*)( int, int ) ); 15 void swap( int * const, int * const ); 16 bool ascending( int, int ); 17 bool descending( int, int ); 18 19 int main() 20 { 21 const int arraySize = 10; 22 int order; 23 int counter; 24 int a[ arraySize ] = { 2, 6, 4, 8, 10, 12, 89, 68, 45, 37 }; 25 Parameter is pointer to function that receives two integer parameters and returns bool result.
  • 540. 26 cout << "Enter 1 to sort in ascending order,n" 27 << "Enter 2 to sort in descending order: "; 28 cin >> order; 29 cout << "nData items in original ordern"; 30 31 // output original array 32 for ( counter = 0; counter < arraySize; counter++ ) 33 cout << setw( 4 ) << a[ counter ]; 34 35 // sort array in ascending order; pass function ascending 36 // as an argument to specify ascending sorting order 37 if ( order == 1 ) { 38 bubble( a, arraySize, ascending ); 39 cout << "nData items in ascending ordern"; 40 } 41 42 // sort array in descending order; pass function descending 43 // as an agrument to specify descending sorting order 44 else { 45 bubble( a, arraySize, descending ); 46 cout << "nData items in descending ordern"; 47 } 48
  • 541. 49 // output sorted array 50 for ( counter = 0; counter < arraySize; counter++ ) 51 cout << setw( 4 ) << a[ counter ]; 52 53 cout << endl; 54 55 return 0; // indicates successful termination 56 57 } // end main 58 59 // multipurpose bubble sort; parameter compare is a pointer to 60 // the comparison function that determines sorting order 61 void bubble( int work[], const int size, 62 bool (*compare)( int, int ) ) 63 { 64 // loop to control passes 65 for ( int pass = 1; pass < size; pass++ ) 66 67 // loop to control number of comparisons per pass 68 for ( int count = 0; count < size - 1; count++ ) 69 70 // if adjacent elements are out of order, swap them 71 if ( (*compare)( work[ count ], work[ count + 1 ] ) ) 72 swap( &work[ count ], &work[ count + 1 ] ); compare is pointer to function that receives two integer parameters and returns bool result. Parentheses necessary to indicate pointer to function Call passed function compare; dereference pointer to execute function.
  • 542. 73 74 } // end function bubble 75 76 // swap values at memory locations to which 77 // element1Ptr and element2Ptr point 78 void swap( int * const element1Ptr, int * const element2Ptr ) 79 { 80 int hold = *element1Ptr; 81 *element1Ptr = *element2Ptr; 82 *element2Ptr = hold; 83 84 } // end function swap 85 86 // determine whether elements are out of order 87 // for an ascending order sort 88 bool ascending( int a, int b ) 89 { 90 return b < a; // swap if b is less than a 91 92 } // end function ascending 93
  • 543. 94 // determine whether elements are out of order 95 // for a descending order sort 96 bool descending( int a, int b ) 97 { 98 return b > a; // swap if b is greater than a 99 100 } // end function descending Enter 1 to sort in ascending order, Enter 2 to sort in descending order: 1 Data items in original order 2 6 4 8 10 12 89 68 45 37 Data items in ascending order 2 4 6 8 10 12 37 45 68 89 Enter 1 to sort in ascending order, Enter 2 to sort in descending order: 2 Data items in original order 2 6 4 8 10 12 89 68 45 37 Data items in descending order 89 68 45 37 12 10 8 6 4 2
  • 544. Function Pointers  Arrays of pointers to functions  Menu-driven systems  Pointers to each function stored in array of pointers to functions  All functions must have same return type and same parameter types  Menu choice  subscript into array of function pointers
  • 545. 1 // Example 98 2 // Demonstrating an array of pointers to functions. 3 #include <iostream> 4 5 using std::cout; 6 using std::cin; 7 using std::endl; 8 9 // function prototypes 10 void function1( int ); 11 void function2( int ); 12 void function3( int ); 13 14 int main() 15 { 16 // initialize array of 3 pointers to functions that each 17 // take an int argument and return void 18 void (*f[ 3 ])( int ) = { function1, function2, function3 }; 19 20 int choice; 21 22 cout << "Enter a number between 0 and 2, 3 to end: "; 23 cin >> choice; 24 Array initialized with names of three functions; function names are pointers.
  • 546. 25 // process user's choice 26 while ( choice >= 0 && choice < 3 ) { 27 28 // invoke function at location choice in array f 29 // and pass choice as an argument 30 (*f[ choice ])( choice ); 31 32 cout << "Enter a number between 0 and 2, 3 to end: "; 33 cin >> choice; 34 } 35 36 cout << "Program execution completed." << endl; 37 38 return 0; // indicates successful termination 39 40 } // end main 41 42 void function1( int a ) 43 { 44 cout << "You entered " << a 45 << " so function1 was callednn"; 46 47 } // end function1 48 Call chosen function by dereferencing corresponding element in array.
  • 547. 49 void function2( int b ) 50 { 51 cout << "You entered " << b 52 << " so function2 was callednn"; 53 54 } // end function2 55 56 void function3( int c ) 57 { 58 cout << "You entered " << c 59 << " so function3 was callednn"; 60 61 } // end function3 Enter a number between 0 and 2, 3 to end: 0 You entered 0 so function1 was called Enter a number between 0 and 2, 3 to end: 1 You entered 1 so function2 was called Enter a number between 0 and 2, 3 to end: 2 You entered 2 so function3 was called Enter a number between 0 and 2, 3 to end: 3 Program execution completed.
  • 548. Accessing Structure Members  Member access operators  Dot operator (.) for structure and class members  Arrow operator (->) for structure and class members via pointer to object  Print member hour of timeObject: cout << timeObject.hour; OR timePtr = &timeObject; cout << timePtr->hour;  timePtr->hour same as ( *timePtr ).hour  Parentheses required * lower precedence than .
  • 549. Subtle Trap: Returning a Reference to a private Data Member  Reference to object  &pRef = p;  Alias for name of object  Lvalue  Can receive value in assignment statement Changes original object  Returning references  public member functions can return non-const references to private data members  Client able to modify private data members
  • 550. 1 // Example 99 2 // Declaration of class Time. 3 // Member functions defined in time4.cpp 4 5 // prevent multiple inclusions of header file 6 #ifndef TIME4_H 7 #define TIME4_H 8 9 class Time { 10 11 public: 12 Time( int = 0, int = 0, int = 0 ); 13 void setTime( int, int, int ); 14 int getHour(); 15 16 int &badSetHour( int ); // DANGEROUS reference return 17 18 private: 19 int hour; 20 int minute; 21 int second; 22 23 }; // end class Time 24 25 #endif Function to demonstrate effects of returning reference to private data member.
  • 551. 25 // return hour value 26 int Time::getHour() 27 { 28 return hour; 29 30 } // end function getHour 31 32 // POOR PROGRAMMING PRACTICE: 33 // Returning a reference to a private data member. 34 int &Time::badSetHour( int hh ) 35 { 36 hour = ( hh >= 0 && hh < 24 ) ? hh : 0; 37 38 return hour; // DANGEROUS reference return 39 40 } // end function badSetHour Return reference to private data member hour.
  • 552. 1 // Example 100 2 // Demonstrating a public member function that 3 // returns a reference to a private data member. 4 #include <iostream> 5 6 using std::cout; 7 using std::endl; 8 9 // include definition of class Time from time4.h 10 #include "time4.h" 11 12 int main() 13 { 14 Time t; 15 16 // store in hourRef the reference returned by badSetHour 17 int &hourRef = t.badSetHour( 20 ); 18 19 cout << "Hour before modification: " << hourRef; 20 21 // use hourRef to set invalid value in Time object t 22 hourRef = 30; 23 24 cout << "nHour after modification: " << t.getHour(); 25 badSetHour returns reference to private data member hour. Reference allows setting of private data member hour.
  • 553. 26 // Dangerous: Function call that returns 27 // a reference can be used as an lvalue! 28 t.badSetHour( 12 ) = 74; 29 30 cout << "nn*********************************n" 31 << "POOR PROGRAMMING PRACTICE!!!!!!!!n" 32 << "badSetHour as an lvalue, Hour: " 33 << t.getHour() 34 << "n*********************************" << endl; 35 36 return 0; 37 38 } // end main Hour before modification: 20 Hour after modification: 30 ********************************* POOR PROGRAMMING PRACTICE!!!!!!!! badSetHour as an lvalue, Hour: 74 ********************************* Can use function call as lvalue to set invalid value. Returning reference allowed invalid setting of private data member hour.
  • 554. Default Memberwise Assignment  Assigning objects  Assignment operator (=)  Can assign one object to another of same type  Default: memberwise assignment Each right member assigned individually to left member  Passing, returning objects  Objects passed as function arguments  Objects returned from functions  Default: pass-by-value  Copy of object passed, returned Copy constructor  Copy original values into new object
  • 555. Dynamic Memory Management with Operators new and delete  Dynamic memory management  Control allocation and deallocation of memory  Operators new and delete  Include standard header <new>  new Time *timePtr; timePtr = new Time;  Creates object of proper size for type Time  Error if no space in memory for object  Calls default constructor for object  Returns pointer of specified type  Providing initializers double *ptr = new double( 3.14159 ); Time *timePtr = new Time( 12, 0, 0 );  Allocating arrays int *gradesArray = new int[ 10 ];
  • 556. Dynamic Memory Management with Operators new and delete  delete  Destroy dynamically allocated object and free space  Consider delete timePtr;  Operator delete  Calls destructor for object  Deallocates memory associated with object Memory can be reused to allocate other objects  Deallocating arrays delete [] gradesArray; Deallocates array to which gradesArray points  If pointer to array of objects  First calls destructor for each object in array  Then deallocates memory
  • 557. employee2.h (2 of 2) employee2.cpp (1 of 3) 1 // Example 102 2 // Member-function definitions for class Employee. 3 #include <iostream> 4 5 using std::cout; 6 using std::endl; 7 8 #include <new> // C++ standard new operator 9 #include <cstring> // strcpy and strlen prototypes 10 11 #include "employee2.h" // Employee class definition 12 13 // define and initialize static data member 14 int Employee::count = 0; 15 16 // define static member function that returns number of 17 // Employee objects instantiated 18 int Employee::getCount() 19 { 20 return count; 21 22 } // end static function getCount Initialize static data member exactly once at file scope. static member function accesses static data member count.
  • 558. static Class Members  static class variable  “Class-wide” data  Property of class, not specific object of class  Efficient when single copy of data is enough  Only the static variable has to be updated  May seem like global variables, but have class scope  Only accessible to objects of same class  Initialized exactly once at file scope  Exist even if no objects of class exist  Can be public, private or protected
  • 559. static Class Members  Accessing static class variables  Accessible through any object of class  public static variables  Can also be accessed using binary scope resolution operator(::) Employee::count  private static variables  When no class member objects exist: Can only be accessed via public static member function Employee::getCount()  static member functions  Cannot access non-static data or functions  No this pointer for static functions  static data members and static member functions exist independent of objects
  • 560. 1 // Example 101 2 // Employee class definition. 3 #ifndef EMPLOYEE2_H 4 #define EMPLOYEE2_H 5 6 class Employee { 7 8 public: 9 Employee( const char *, const char * ); // constructor 10 ~Employee(); // destructor 11 const char *getFirstName() const; // return first name 12 const char *getLastName() const; // return last name 13 14 // static member function 15 static int getCount(); // return # objects instantiated 16 17 private: 18 char *firstName; 19 char *lastName; 20 21 // static data member 22 static int count; // number of objects instantiated 23 24 }; // end class Employee 25 static member function can only access static data members and member functions. static data member is class-wide data.
  • 561. 23 24 // constructor dynamically allocates space for 25 // first and last name and uses strcpy to copy 26 // first and last names into the object 27 Employee::Employee( const char *first, const char *last ) 28 { 29 firstName = new char[ strlen( first ) + 1 ]; 30 strcpy( firstName, first ); 31 32 lastName = new char[ strlen( last ) + 1 ]; 33 strcpy( lastName, last ); 34 35 ++count; // increment static count of employees 36 37 cout << "Employee constructor for " << firstName 38 << ' ' << lastName << " called." << endl; 39 40 } // end Employee constructor 41 42 // destructor deallocates dynamically allocated memory 43 Employee::~Employee() 44 { 45 cout << "~Employee() called for " << firstName 46 << ' ' << lastName << endl; 47 new operator dynamically allocates space. Use static data member to store total count of employees.
  • 562. 48 delete [] firstName; // recapture memory 49 delete [] lastName; // recapture memory 50 51 --count; // decrement static count of employees 52 53 } // end destructor ~Employee 54 55 // return first name of employee 56 const char *Employee::getFirstName() const 57 { 58 // const before return type prevents client from modifying 59 // private data; client should copy returned string before 60 // destructor deletes storage to prevent undefined pointer 61 return firstName; 62 63 } // end function getFirstName 64 65 // return last name of employee 66 const char *Employee::getLastName() const 67 { 68 // const before return type prevents client from modifying 69 // private data; client should copy returned string before 70 // destructor deletes storage to prevent undefined pointer 71 return lastName; 72 73 } // end function getLastName Operator delete deallocates memory. Use static data member to store total count of employees.
  • 563. Operator Functions As Class Members Vs. As Friend Functions  Operator functions  Member functions  Use this keyword to implicitly get argument  Gets left operand for binary operators (like +)  Leftmost object must be of same class as operator  Non member functions  Need parameters for both operands  Can have object of different class than operator  Must be a friend to access private or protected data  Example Overloaded << operator  Left operand of type ostream &  Such as cout object in cout << classObject  Similarly, overloaded >> needs istream &  Thus, both must be non-member functions
  • 564. Operator Functions As Class Members Vs. As Friend Functions  Commutative operators  May want + to be commutative  So both “a + b” and “b + a” work  Suppose we have two different classes  Overloaded operator can only be member function when its class is on left  HugeIntClass + Long int  Can be member function  When other way, need a non-member overload function  Long int + HugeIntClass
  • 565. Overloading Stream-Insertion and Stream-Extraction Operators  << and >>  Already overloaded to process each built-in type  Can also process a user-defined class  Example program  Class PhoneNumber  Holds a telephone number  Print out formatted number automatically  (123) 456-7890
  • 566. 1 // Example 103 2 // Overloading the stream-insertion and 3 // stream-extraction operators. 4 #include <iostream> 5 6 using std::cout; 7 using std::cin; 8 using std::endl; 9 using std::ostream; 10 using std::istream; 11 12 #include <iomanip> 13 14 using std::setw; 15 16 // PhoneNumber class definition 17 class PhoneNumber { 18 friend ostream &operator<<( ostream&, const PhoneNumber & ); 19 friend istream &operator>>( istream&, PhoneNumber & ); 20 21 private: 22 char areaCode[ 4 ]; // 3-digit area code and null 23 char exchange[ 4 ]; // 3-digit exchange and null 24 char line[ 5 ]; // 4-digit line and null 25 26 }; // end class PhoneNumber Notice function prototypes for overloaded operators >> and << They must be non-member friend functions, since the object of class Phonenumber appears on the right of the operator. cin << object cout >> object
  • 567. 27 28 // overloaded stream-insertion operator; cannot be 29 // a member function if we would like to invoke it with 30 // cout << somePhoneNumber; 31 ostream &operator<<( ostream &output, const PhoneNumber &num ) 32 { 33 output << "(" << num.areaCode << ") " 34 << num.exchange << "-" << num.line; 35 36 return output; // enables cout << a << b << c; 37 38 } // end function operator<< 39 40 // overloaded stream-extraction operator; cannot be 41 // a member function if we would like to invoke it with 42 // cin >> somePhoneNumber; 43 istream &operator>>( istream &input, PhoneNumber &num ) 44 { 45 input.ignore(); // skip ( 46 input >> setw( 4 ) >> num.areaCode; // input area code 47 input.ignore( 2 ); // skip ) and space 48 input >> setw( 4 ) >> num.exchange; // input exchange 49 input.ignore(); // skip dash (-) 50 input >> setw( 5 ) >> num.line; // input line 51 52 return input; // enables cin >> a >> b >> c; The expression: cout << phone; is interpreted as the function call: operator<<(cout, phone); output is an alias for cout. This allows objects to be cascaded. cout << phone1 << phone2; first calls operator<<(cout, phone1), and returns cout. Next, cout << phone2 executes. Stream manipulator setw restricts number of characters read. setw(4) allows 3 characters to be read, leaving room for the null character.
  • 568. 53 54 } // end function operator>> 55 56 int main() 57 { 58 PhoneNumber phone; // create object phone 59 60 cout << "Enter phone number in the form (123) 456-7890:n"; 61 62 // cin >> phone invokes operator>> by implicitly issuing 63 // the non-member function call operator>>( cin, phone ) 64 cin >> phone; 65 66 cout << "The phone number entered was: " ; 67 68 // cout << phone invokes operator<< by implicitly issuing 69 // the non-member function call operator<<( cout, phone ) 70 cout << phone << endl; 71 72 return 0; 73 74 } // end main Enter phone number in the form (123) 456-7890: (800) 555-1212 The phone number entered was: (800) 555-1212