Presentation is loading. Please wait.

Presentation is loading. Please wait.

IS Program Design and Software Tools Introduction to C++ Programming

Similar presentations


Presentation on theme: "IS Program Design and Software Tools Introduction to C++ Programming"— Presentation transcript:

1 IS 0020 Program Design and Software Tools Introduction to C++ Programming
Lecture 1 Jan 6, 2004

2 Course Information Lecture: Pre-requisite Textbook James B D Joshi
Tuesdays: 6: PM One (two) 15 (10) minutes break(s) Office Hours: Wed 3:00-5:00PM/Appointment Pre-requisite IS 0015 Data Structures and Programming Techniques Textbook C++ How to Program- Fourth Edition,  by H. M. Deitel, P. J. Deitel, Prentice Hall, New Jersey, 2003, ISBN:  

3 Course Information 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.

4 Grading Quiz 10% (in the beginning of the class; on previous lecture) Homework/Programming Assignments 40% (typically every week) Midterm 25% Comprehensive Final 25%

5 Course Policy Your work MUST be your own Homework
Zero tolerance for cheating You get an F for the course if you cheat in anything however small – NO DISCUSSION Homework There will be penalty for late assignments (15% each day) Ensure clarity in your answers – no credit will be given for vague answers Homework is primarily the GSA’s responsibility Check webpage for everything! You are responsible for checking the webpage for updates

6 Course Policy Your work MUST be your own Homework
Zero tolerance for cheating You get an F for the course if you cheat in anything however small – NO DISCUSSION Homework There will be penalty for late assignments (15% each day) Ensure clarity in your answers – no credit will be given for vague answers Homework is primarily the GSA’s responsibility Solutions/theory will be posted on the web Check webpage for everything! You are responsible for checking the webpage for updates

7 Computer Languages Machine language
Only language computer directly understands Defined by hardware design Machine-dependent Generally consist of strings of numbers Ultimately 0s and 1s Instruct computers to perform elementary operations One at a time Cumbersome for humans Example:

8 Computer Languages Assembly language
English-like abbreviations representing elementary computer operations Clearer to humans Incomprehensible to computers Translator programs (assemblers) Convert to machine language Example: LOAD BASEPAY ADD OVERPAY STORE GROSSPAY

9 Computer Languages High-level languages
Similar to everyday English, use common mathematical notations Single statements accomplish substantial tasks Assembly language requires many instructions to accomplish simple tasks Translator programs (compilers) Convert to machine language Interpreter programs Directly execute high-level language programs Example: grossPay = basePay + overTimePay

10 History of C and C++ History of C
Evolved from two other programming languages BCPL and B “Typeless” languages Dennis Ritchie (Bell Laboratories) Added data typing, other features Development language of UNIX Hardware independent Portable programs 1989: ANSI standard 1990: ANSI and ISO standard published ANSI/ISO 9899: 1990

11 History of C and C++ History of C++ Extension of C
Early 1980s: Bjarne Stroustrup (Bell Laboratories) Provides capabilities for object-oriented programming Objects: reusable software components Model items in real world Object-oriented programs Easy to understand, correct and modify Hybrid language C-like style Object-oriented style Both

12 “Building block approach” to creating programs
C++ Standard Library C++ programs Built from pieces called classes and functions C++ standard library Rich collections of existing classes and functions “Building block approach” to creating programs “Software reuse”

13 Java Java 1991: Sun Microsystems 1995: Sun Microsystems
Green project 1995: Sun Microsystems Formally announced Java at trade show Web pages with dynamic and interactive content Develop large-scale enterprise applications Enhance functionality of web servers Provide applications for consumer devices Cell phones, pagers, personal digital assistants, …

14 Structured Programming
Structured programming (1960s) Disciplined approach to writing programs Clear, easy to test and debug, and easy to modify Pascal 1971: Niklaus Wirth Ada 1970s - early 1980s: US Department of Defense (DoD) Multitasking Programmer can specify many activities to run in parallel

15 The Key Software Trend: Object Technology
Objects Reusable software components that model real world items Meaningful software units Date objects, time objects, paycheck objects, invoice objects, audio objects, video objects, file objects, record objects, etc. Any noun can be represented as an object More understandable, better organized and easier to maintain than procedural programming Favor modularity Software reuse Libraries MFC (Microsoft Foundation Classes) Rogue Wave

16 Basics of a Typical C++ Environment
C++ systems Program-development environment Language C++ Standard Library C++ program names extensions .cpp .cxx .cc .C

17 Basics of a Typical C++ Environment
Phases of C++ Programs: Edit Preprocess Compile Link Load 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 . Disk

18 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

19 A Simple Program: Printing a Line of Text
Before writing the programs Comments Document programs Improve program readability Ignored by compiler Single-line comment Use C’s comment /* .. */ OR Begin with // or Preprocessor directives Processed by preprocessor before compiling Begin with #

20 fig01_02.cpp (1 of 1) fig01_02.cpp output (1 of 1)
// Fig. 1.2: fig01_02.cpp // A first program in C++. #include <iostream> 4 // function main begins program execution int main() { std::cout << "Welcome to C++!\n"; 9 return 0; // indicate that program ended successfully 11 12 } // end function main Single-line comments. Function main returns an integer value. Preprocessor directive to include input/output stream header file <iostream>. Left brace { begins function body. fig01_02.cpp (1 of 1) fig01_02.cpp output (1 of 1) Function main appears exactly once in every C++ program.. Statements end with a semicolon ;. Corresponding right brace } ends function body. Name cout belongs to namespace std. Stream insertion operator. Keyword return is one of several means to exit function; value 0 indicates program terminated successfully. Welcome to C++!

21 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 using name that belongs to “namespace” std std:: removed through use of using statements Escape characters \ Indicates “special” character output

22 A Simple Program: Printing a Line of Text

23 Another Simple Program: Adding Two Integers
Variables Location in memory where value can be stored Common data types int - integer numbers char - characters double - floating point numbers Declare variables with name and data type before use int integer1; int integer2; int sum; Can declare several variables of same type in one declaration Comma-separated list int integer1, integer2, sum;

24 Another Simple Program: Adding Two Integers
Input stream object >> (stream extraction operator) Used with std::cin Waits for user to input value, then press Enter (Return) key Stores value in variable to right of operator Converts value to variable data type = (assignment operator) Assigns value to variable Binary operator (two operands) Example: sum = variable1 + variable2;

25 Declare integer variables.
// Fig. 1.6: fig01_06.cpp // Addition program. #include <iostream> 4 // function main begins program execution int main() { int integer1; // first number to be input by user int integer2; // second number to be input by user int sum; // variable in which sum will be stored 11 std::cout << "Enter first integer\n"; // prompt std::cin >> integer1; // read an integer 14 std::cout << "Enter second integer\n"; // prompt std::cin >> integer2; // read an integer 17 sum = integer1 + integer2; // assign result to sum 19 std::cout << "Sum is " << sum << std::endl; // print sum 21 return 0; // indicate that program ended successfully 23 24 } // end function main fig01_06.cpp (1 of 1) Declare integer variables. Use stream extraction operator with standard input stream to obtain user input. Calculations can be performed in output statements: alternative for lines 18 and 20: std::cout << "Sum is " << integer1 + integer2 << std::endl; Stream manipulator std::endl outputs a newline, then “flushes output buffer.” Concatenating, chaining or cascading stream insertion operations.

26 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

27 Arithmetic calculations
* : Multiplication / : Division Integer division truncates remainder 7 / 5 evaluates to 1 % : Modulus operator returns remainder 7 % 5 evaluates to 2

28 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 Associate left to right using statements Eliminate use of std:: prefix Write cout instead of std::cout

29 Decision Making: Equality and Relational Operators

30 using statements eliminate need for std:: prefix.
// Fig. 1.14: fig01_14.cpp // Using if statements, relational // operators, and equality operators. #include <iostream> 5 using std::cout; // program uses cout using std::cin; // program uses cin using std::endl; // program uses endl 9 10 // function main begins program execution 11 int main() 12 { int num1; // first number to be read from user int num2; // second number to be read from user 15 cout << "Enter two integers, and I will tell you\n" << "the relationships they satisfy: "; cin >> num1 >> num2; // read two integers 19 if ( num1 == num2 ) cout << num1 << " is equal to " << num2 << endl; 22 if ( num1 != num2 ) cout << num1 << " is not equal to " << num2 << endl; 25 fig01_14.cpp (1 of 2) using statements eliminate need for std:: prefix. Declare variables. Can write cout and cin without std:: prefix. if structure compares values of num1 and num2 to test for equality. If condition is true (i.e., values are equal), execute this statement. if structure compares values of num1 and num2 to test for inequality. If condition is true (i.e., values are not equal), execute this statement.

31 fig01_14.cpp (2 of 2) fig01_14.cpp output (1 of 2)
if ( num1 < num2 ) cout << num1 << " is less than " << num2 << endl; 28 if ( num1 > num2 ) cout << num1 << " is greater than " << num2 << endl; 31 if ( num1 <= num2 ) cout << num1 << " is less than or equal to " << num2 << endl; 35 if ( num1 >= num2 ) cout << num1 << " is greater than or equal to " << num2 << endl; 39 return 0; // indicate that program ended successfully 41 42 } // end function main fig01_14.cpp (2 of 2) fig01_14.cpp output (1 of 2) Statements may be split over several lines. Enter two integers, and I will tell you the relationships they satisfy: 22 12 22 is not equal to 12 22 is greater than 12 22 is greater than or equal to 12

32 Algorithm a procedure determining
Algorithms 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

33 Not executed on computers
Pseudocode Pseudocode Artificial, informal language used to develop algorithms Similar to everyday English Not executed on computers Used to think out program before coding Easy to convert into C++ program Only executable statements No need to declare variables

34 3 control structures to build any program
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

35 Keywords C++ keywords Cannot be used as identifiers or variable names

36 Single-entry/single-exit 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) Single-entry/single-exit control structures Connect exit point of one to entry point of the next Control structure stacking

37 if Selection Structure
Choose among alternative courses of action Pseudocode example: If student’s grade is greater than or equal to 60 Print “Passed” If the condition is true Print statement executed, program continues to next statement If the condition is false Print statement ignored, program continues Indenting makes programs easier to read C++ ignores whitespace characters (tabs, spaces, etc.)

38 if Selection Structure
Translation into C++ If student’s grade is greater than or equal to 60 Print “Passed” if ( grade >= 60 ) cout << "Passed"; Diamond symbol (decision symbol) Indicates decision is to be made Contains an expression that can be true or false Test condition, follow path if structure Single-entry/single-exit

39 if Selection Structure
Flowchart of pseudocode statement true false grade >= 60 print “Passed” A decision can be made on any expression. zero - false nonzero - true Example: 3 - 4 is true

40 if/else Selection Structure
Performs action if condition true if/else Different actions if conditions true or false Pseudocode if student’s grade is greater than or equal to 60 print “Passed” else print “Failed” C++ code if ( grade >= 60 ) cout << "Passed"; else cout << "Failed";

41 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” ); Condition Value if true Value if false true false print “Failed” print “Passed” grade >= 60

42 if/else Selection Structure
Nested if/else structures One inside another, test for multiple cases Once condition met, other statements skipped if student’s grade is greater than or equal to Print “A” else if student’s grade is greater than or equal to Print “B” else if student’s grade is greater than or equal to Print “C” else if student’s grade is greater than or equal to Print “D” else Print “F”

43 if/else Selection Structure
Example if ( grade >= 90 ) // 90 and above cout << "A"; else if ( grade >= 80 ) // cout << "B"; else if ( grade >= 70 ) // cout << "C"; else if ( grade >= 60 ) // cout << "D"; else // less than cout << "F";

44 if/else Selection Structure
Compound statement Set of statements within a pair of braces if ( grade >= 60 ) cout << "Passed.\n"; else { cout << "Failed.\n"; cout << "You must take this course again.\n"; } Without braces, cout << "You must take this course again.\n"; always executed Block Set of statements within braces

45 while Repetition Structure
Action repeated while some condition remains true Psuedocode while there are more items on my shopping list Purchase next item and cross it off my list while loop repeated until condition becomes false Example int product = 2; while ( product <= 1000 ) product = 2 * product;

46 while Repetition Structure
Flowchart of while loop product <= 1000 product = 2 * product true false

47 Counter-Controlled Repetition
Loop repeated until counter reaches certain value Definite repetition Number of repetitions known Example A class of ten students took a quiz. The grades (integers in the range 0 to 100) for this quiz are available to you. Determine the class average on the quiz.

48 fig02_07.cpp (1 of 2) 1 // Fig. 2.7: fig02_07.cpp
// Class average program with counter-controlled repetition. #include <iostream> 4 using std::cout; using std::cin; using std::endl; 8 // function main begins program execution 10 int main() 11 { int total; // sum of grades input by user int gradeCounter; // number of grade to be entered next int grade; // grade value int average; // average of grades 16 // initialization phase total = 0; // initialize total gradeCounter = 1; // initialize loop counter 20 fig02_07.cpp (1 of 2)

49 fig02_07.cpp (2 of 2) fig02_07.cpp output (1 of 1)
// processing phase while ( gradeCounter <= 10 ) { // loop 10 times cout << "Enter grade: "; // prompt for input cin >> grade; // read grade from user total = total + grade; // add grade to total gradeCounter = gradeCounter + 1; // increment counter } 28 // termination phase average = total / 10; // integer division 31 // display result cout << "Class average is " << average << endl; 34 return 0; // indicate program ended successfully 36 37 } // end function main fig02_07.cpp (2 of 2) fig02_07.cpp output (1 of 1) The counter gets incremented each time the loop executes. Eventually, the counter causes the loop to end. Enter grade: 98 Enter grade: 76 Enter grade: 71 Enter grade: 87 Enter grade: 83 Enter grade: 90 Enter grade: 57 Enter grade: 79 Enter grade: 82 Enter grade: 94 Class average is 81

50 Sentinel-Controlled Repetition
Suppose problem becomes: Develop a class-averaging program that will process an arbitrary number of grades each time the program is run Unknown number of students How will program know when to end? Sentinel value Indicates “end of data entry” Loop ends when sentinel input Sentinel chosen so it cannot be confused with regular input -1 in this case

51 // Fig. 2.9: fig02_09.cpp // Class average program with sentinel-controlled repetition. #include <iostream> 4 using std::cout; using std::cin; using std::endl; using std::fixed; 9 10 #include <iomanip> // parameterized stream manipulators 11 12 using std::setprecision; // sets numeric output precision 13 14 // function main begins program execution 15 int main() 16 { int total; // sum of grades int gradeCounter; // number of grades entered int grade; // grade value 20 double average; // number with decimal point for average 22 // initialization phase total = 0; // initialize total gradeCounter = 0; // initialize loop counter fig02_09.cpp (1 of 3) Data type double used to represent decimal numbers.

52 Required because dividing two integers truncates the remainder.
26 // processing phase // get first grade from user cout << "Enter grade, -1 to end: "; // prompt for input cin >> grade; // read grade from user 31 // loop until sentinel value read from user while ( grade != -1 ) { total = total + grade; // add grade to total gradeCounter = gradeCounter + 1; // increment counter 36 cout << "Enter grade, -1 to end: "; // prompt for input cin >> grade; // read next grade 39 } // end while 41 // termination phase // if user entered at least one grade ... if ( gradeCounter != 0 ) { 45 // calculate average of all grades entered average = static_cast< double >( total ) / gradeCounter; 48 fig02_09.cpp (2 of 3) static_cast<double>() treats total as a double temporarily (casting). Required because dividing two integers truncates the remainder. gradeCounter is an int, but it gets promoted to double.

53 fig02_09.cpp (3 of 3) fig02_09.cpp output (1 of 1)
// display average with two digits of precision cout << "Class average is " << setprecision( 2 ) << fixed << average << endl; 52 } // end if part of if/else 54 else // if no grades were entered, output appropriate message cout << "No grades were entered" << endl; 57 return 0; // indicate program ended successfully 59 60 } // end function main setprecision(2)prints two digits past decimal point (rounded to fit precision). Programs that use this must include <iomanip> fixed forces output to print in fixed point format (not scientific notation). Also, forces trailing zeros and decimal point to print. Include <iostream> fig02_09.cpp (3 of 3) fig02_09.cpp output (1 of 1) Enter grade, -1 to end: 75 Enter grade, -1 to end: 94 Enter grade, -1 to end: 97 Enter grade, -1 to end: 88 Enter grade, -1 to end: 70 Enter grade, -1 to end: 64 Enter grade, -1 to end: 83 Enter grade, -1 to end: 89 Enter grade, -1 to end: -1 Class average is 82.50

54 switch Multiple-Selection Structure
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 break; default: // taken if none matches statements break; }

55 switch Multiple-Selection Structure
true false . case a case a action(s) break case b case b action(s) case z case z action(s) default action(s)

56 switch Multiple-Selection Structure
Example upcoming Program to read grades (A-F) Display number of each grade entered Details about characters Single characters typically stored in a char data type char a 1-byte integer, so chars can be stored as ints Can treat character as int or char 97 is the numerical representation of lowercase ‘a’ (ASCII) Use single quotes to get numerical representation of character cout << "The character (" << 'a' << ") has the value " << static_cast< int > ( 'a' ) << endl; Prints The character (a) has the value 97

57 fig02_22.cpp (1 of 4) 1 // Fig. 2.22: fig02_22.cpp
// Counting letter grades. #include <iostream> 4 using std::cout; using std::cin; using std::endl; 8 // function main begins program execution 10 int main() 11 { int grade; // one grade int aCount = 0; // number of As int bCount = 0; // number of Bs int cCount = 0; // number of Cs int dCount = 0; // number of Ds int fCount = 0; // number of Fs 18 cout << "Enter the letter grades." << endl << "Enter the EOF character to end input." << endl; 21 fig02_22.cpp (1 of 4)

58 This can also be used to initialize multiple variables: a = b = c = 0;
// loop until user types end-of-file key sequence while ( ( grade = cin.get() ) != EOF ) { 24 // determine which grade was input switch ( grade ) { // switch structure nested in while 27 case 'A': // grade was uppercase A case 'a': // or lowercase a aCount; // increment aCount break; // necessary to exit switch 32 case 'B': // grade was uppercase B case 'b': // or lowercase b bCount; // increment bCount break; // exit switch 37 case 'C': // grade was uppercase C case 'c': // or lowercase c cCount; // increment cCount break; // exit switch 42 break causes switch to end and the program continues with the first statement after the switch structure. Assignment statements have a value, which is the same as the variable on the left of the =. The value of this statement is the same as the value returned by cin.get(). This can also be used to initialize multiple variables: a = b = c = 0; cin.get() uses dot notation (explained chapter 6). This function gets 1 character from the keyboard (after Enter pressed), and it is assigned to grade. cin.get() returns EOF (end-of-file) after the EOF character is input, to indicate the end of data. EOF may be ctrl-d or ctrl-z, depending on your OS. fig02_22.cpp (2 of 4) Compares grade (an int) to the numerical representations of A and a.

59 Notice the default statement, which catches all other cases.
case 'D': // grade was uppercase D case 'd': // or lowercase d dCount; // increment dCount break; // exit switch 47 case 'F': // grade was uppercase F case 'f': // or lowercase f fCount; // increment fCount break; // exit switch 52 case '\n': // ignore newlines, case '\t': // tabs, case ' ': // and spaces in input break; // exit switch 57 default: // catch all other characters cout << "Incorrect letter grade entered." << " Enter a new grade." << endl; break; // optional; will exit switch anyway 62 } // end switch 64 } // end while 66 fig02_22.cpp (3 of 4) This test is necessary because Enter is pressed after each letter grade is input. This adds a newline character that must be removed. Likewise, we want to ignore any whitespace. Notice the default statement, which catches all other cases.

60 fig02_22.cpp (4 of 4) 67 // output summary of results
cout << "\n\nTotals for each letter grade are:" << "\nA: " << aCount // display number of A grades << "\nB: " << bCount // display number of B grades << "\nC: " << cCount // display number of C grades << "\nD: " << dCount // display number of D grades << "\nF: " << fCount // display number of F grades << endl; 75 return 0; // indicate successful termination 77 78 } // end function main fig02_22.cpp (4 of 4)

61 do/while Repetition Structure
Similar to while structure Makes loop continuation test at end, not beginning Loop body executes at least once Format do { statement } while ( condition ); true false action(s) condition

62 fig02_24.cpp (1 of 1) fig02_24.cpp output (1 of 1)
// Fig. 2.24: fig02_24.cpp // Using the do/while repetition structure. #include <iostream> 4 using std::cout; using std::endl; 7 // function main begins program execution int main() 10 { int counter = 1; // initialize counter 12 do { cout << counter << " "; // display counter } while ( ++counter <= 10 ); // end do/while 16 cout << endl; 18 return 0; // indicate successful termination 20 21 } // end function main fig02_24.cpp (1 of 1) fig02_24.cpp output (1 of 1) Notice the preincrement in loop-continuation test.

63 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

64 Exits for structure when break executed.
// Fig. 2.26: fig02_26.cpp // Using the break statement in a for structure. #include <iostream> 4 using std::cout; using std::endl; 7 // function main begins program execution int main() 10 { 11 int x; // x declared here so it can be used after the loop 13 // loop 10 times for ( x = 1; x <= 10; x++ ) { 16 // if x is 5, terminate loop if ( x == 5 ) break; // break loop only if x is 5 20 cout << x << " "; // display value of x 22 } // end for 24 cout << "\nBroke out of loop when x became " << x << endl; fig02_26.cpp (1 of 2) Exits for structure when break executed.

65 Used as conditions in loops, if statements && (logical AND)
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;

66 ! (logical NOT, logical negation)
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;

67 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)

68 Confusing Equality (==) and Assignment (=) Operators
Example if ( payCode == 4 ) cout << "You get a bonus!" << endl; If paycode is 4, bonus given If == was replaced with = if ( payCode = 4 ) cout << "You get a bonus!" << endl; Paycode set to 4 (no matter what it was before) Statement is true (since 4 is non-zero) Bonus given in every case

69 Confusing Equality (==) and Assignment (=) Operators
Lvalues Expressions that can appear on left side of equation Can be changed (I.e., variables) 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

70 Structured-Programming Summary
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

71 Structured-Programming Summary
Representation of Rule 3 (replacing any rectangle with a control structure) Rule 3

72 Structured-Programming Summary
All programs broken down into Sequence Selection if, if/else, or switch Any selection can be rewritten as an if statement Repetition while, do/while or for Any repetition structure can be rewritten as a while statement

73 Lecture 2 Functions and Arrays Jan 13, 2004
IS Program Design and Software Tools Introduction to C++ Programming Lecture 2 Functions and Arrays Jan 13, 2004

74 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

75 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( ); sqrt (square root) function The preceding statement would print 30 All functions in math library return a double

76 Math Library Functions
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.

77 Functions Functions Local variables Parameters 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

78 Function Definitions Function prototype Calling/invoking a function
Tells compiler argument type and return type of function int square( int ); Function takes an int and returns an 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 double maximum( double, double, double ); Definition double maximum( double x, double y, double z ) { }

79 Functions cannot be defined inside other functions
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

80 Function Prototypes Function signature Argument Coercion
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) int * double Function signature

81 Function Prototypes

82 Header files ending with .h
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>

83 Enumeration: enum Enumeration Example 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

84 Variables have attributes
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 (see Ch. 6), which files can use it

85 Automatic storage class
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;

86 Storage Classes Static storage class auto and register keyword
Variables exist for entire program For functions, name exists for entire program May not be accessible, scope rules still apply (more later) auto and register keyword Created and active in a block 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

87 Scope Rules Scope File scope Function 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:)

88 Function-prototype scope
Scope Rules Block scope Begins at declaration, ends at right brace } Can only be referenced in this range Local variables, function parameters 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

89 Declared outside of function; global variable with file scope.
// Fig. 3.12: fig03_12.cpp // A scoping example. #include <iostream> 4 using std::cout; using std::endl; 7 void useLocal( void ); // function prototype void useStaticLocal( void ); // function prototype 10 void useGlobal( void ); // function prototype 11 12 int x = 1; // global variable 13 14 int main() 15 { int x = 5; // local variable to main 17 cout << "local x in main's outer scope is " << x << endl; 19 { // start new scope 21 int x = 7; 23 cout << "local x in main's inner scope is " << x << endl; 25 } // end new scope fig03_12.cpp (1 of 5) Declared outside of function; global variable with file scope. Local variable with function scope. Create a new block, giving x block scope. When the block ends, this x is destroyed.

90 27 cout << "local x in main's outer scope is " << x << endl; 29 useLocal(); // useLocal has local x useStaticLocal(); // useStaticLocal has static local x useGlobal(); // useGlobal uses global x useLocal(); // useLocal reinitializes its local x useStaticLocal(); // static local x retains its prior value useGlobal(); // global x also retains its value 36 cout << "\nlocal x in main is " << x << endl; 38 return 0; // indicates successful termination 40 41 } // end main 42 fig03_12.cpp (2 of 5)

91 43 // useLocal reinitializes local variable x during each call
44 void useLocal( void ) 45 { int x = 25; // initialized each time useLocal is called 47 cout << endl << "local x is " << x << " on entering useLocal" << endl; x; cout << "local x is " << x << " on exiting useLocal" << endl; 53 54 } // end function useLocal 55 fig03_12.cpp (3 of 5) Automatic variable (local variable of function). This is destroyed when the function exits, and reinitialized when the function begins.

92 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 { // initialized only first time useStaticLocal is called static int x = 50; 63 cout << endl << "local static x is " << x << " on entering useStaticLocal" << endl; x; cout << "local static x is " << x << " on exiting useStaticLocal" << endl; 69 70 } // end function useStaticLocal 71 fig03_12.cpp (4 of 5) Static local variable of function; it is initialized only once, and retains its value between function calls.

93 fig03_12.cpp (5 of 5) fig03_12.cpp output (1 of 2)
72 // useGlobal modifies global variable x during each call 73 void useGlobal( void ) 74 { cout << endl << "global x is " << x << " on entering useGlobal" << endl; x *= 10; cout << "global x is " << x << " on exiting useGlobal" << endl; 80 81 } // end function useGlobal This function does not declare any variables. It uses the global x declared in the beginning of the program. fig03_12.cpp (5 of 5) fig03_12.cpp output (1 of 2) local x in main's outer scope is 5 local x in main's inner scope is 7 local x is 25 on entering useLocal local x is 26 on exiting useLocal local static x is 50 on entering useStaticLocal local static x is 51 on exiting useStaticLocal global x is 1 on entering useGlobal global x is 10 on exiting useGlobal

94 Recursion Recursive functions If not base case
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

95 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)

96 Data type unsigned long can hold an integer from 0 to 4 billion.
// Fig. 3.14: fig03_14.cpp // Recursive factorial function. #include <iostream> 4 using std::cout; using std::endl; 7 #include <iomanip> 9 10 using std::setw; 11 12 unsigned long factorial( unsigned long ); // function prototype 13 14 int main() 15 { // Loop 10 times. During each iteration, calculate // factorial( i ) and display result. for ( int i = 0; i <= 10; i++ ) cout << setw( 2 ) << i << "! = " << factorial( i ) << endl; 21 return 0; // indicates successful termination 23 24 } // end main fig03_14.cpp (1 of 2) Data type unsigned long can hold an integer from 0 to 4 billion.

97 fig03_14.cpp (2 of 2) fig03_14.cpp output (1 of 1)
25 26 // recursive definition of function factorial 27 unsigned long factorial( unsigned long number ) 28 { // base case if ( number <= 1 ) return 1; 32 // recursive step else return number * factorial( number - 1 ); 36 37 } // end function factorial The base case occurs when we have 0! or 1!. All other cases must be split up (recursive step). fig03_14.cpp (2 of 2) fig03_14.cpp output (1 of 1) 0! = 1 1! = 1 2! = 2 3! = 6 4! = 24 5! = 120 6! = 720 7! = 5040 8! = 40320 9! = 10! =

98 Example Using Recursion: Fibonacci Series
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 ( n == 0 || n == 1 ) // base case return n; else return fibonacci( n - 1 ) + fibonacci( n – 2 ); }

99 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( 0 ) return 1 return 0 return +

100 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)

101 Inline Functions Inline functions Example
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

102 fig03_19.cpp (1 of 2) 1 // Fig. 3.19: fig03_19.cpp
// Using an inline function to calculate. // the volume of a cube. #include <iostream> 5 using std::cout; using std::cin; using std::endl; 9 10 // Definition of inline function cube. Definition of function 11 // appears before function is called, so a function prototype 12 // is not required. First line of function definition acts as 13 // the prototype. 14 inline double cube( const double side ) 15 { return side * side * side; // calculate cube 17 18 } // end function cube 19 fig03_19.cpp (1 of 2)

103 fig03_19.cpp (2 of 2) fig03_19.cpp output (1 of 1)
20 int main() 21 { cout << "Enter the side length of your cube: "; 23 double sideValue; 25 cin >> sideValue; 27 // calculate cube of sideValue and display result cout << "Volume of cube with side " << sideValue << " is " << cube( sideValue ) << endl; 31 return 0; // indicates successful termination 33 34 } // end main fig03_19.cpp (2 of 2) fig03_19.cpp output (1 of 1) Enter the side length of your cube: 3.5 Volume of cube with side 3.5 is

104 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

105 Notice the & operator, indicating pass-by-reference.
// Fig. 3.20: fig03_20.cpp // Comparing pass-by-value and pass-by-reference // with references. #include <iostream> 5 using std::cout; using std::endl; 8 int squareByValue( int ); // function prototype 10 void squareByReference( int & ); // function prototype 11 12 int main() 13 { int x = 2; int z = 4; 16 // demonstrate squareByValue cout << "x = " << x << " before squareByValue\n"; cout << "Value returned by squareByValue: " << squareByValue( x ) << endl; cout << "x = " << x << " after squareByValue\n" << endl; 22 fig03_20.cpp (1 of 2) Notice the & operator, indicating pass-by-reference.

106 Changes number, but original parameter (x) is not modified.
// demonstrate squareByReference cout << "z = " << z << " before squareByReference" << endl; squareByReference( z ); cout << "z = " << z << " after squareByReference" << endl; 27 return 0; // indicates successful termination 29 } // end main 30 31 // squareByValue multiplies number by itself, stores the 32 // result in number and returns the new value of number 33 int squareByValue( int number ) 34 { return number *= number; // caller's argument not modified 36 37 } // end function squareByValue 38 39 // squareByReference multiplies numberRef by itself and 40 // stores the result in the variable to which numberRef 41 // refers in function main 42 void squareByReference( int &numberRef ) 43 { numberRef *= numberRef; // caller's argument modified 45 46 } // end function squareByReference fig03_20.cpp (2 of 2) Changes number, but original parameter (x) is not modified. Changes numberRef, an alias for the original parameter. Thus, z is changed.

107 fig03_20.cpp output (1 of 1) x = 2 before squareByValue
Value returned by squareByValue: 4 x = 2 after squareByValue z = 4 before squareByReference z = 16 after squareByReference fig03_20.cpp output (1 of 1)

108 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

109 fig03_21.cpp (1 of 1) fig03_21.cpp output (1 of 1)
// Fig. 3.21: fig03_21.cpp // References must be initialized. #include <iostream> 4 using std::cout; using std::endl; 7 int main() { int x = 3; 11 // y refers to (is an alias for) x int &y = x; 14 cout << "x = " << x << endl << "y = " << y << endl; y = 7; cout << "x = " << x << endl << "y = " << y << endl; 18 return 0; // indicates successful termination 20 21 } // end main fig03_21.cpp (1 of 1) fig03_21.cpp output (1 of 1) y declared as a reference to x. x = 3 y = 3 x = 7 y = 7

110 fig03_22.cpp (1 of 1) fig03_22.cpp output (1 of 1)
// Fig. 3.22: fig03_22.cpp // References must be initialized. #include <iostream> 4 using std::cout; using std::endl; 7 int main() { int x = 3; int &y; // Error: y must be initialized 12 cout << "x = " << x << endl << "y = " << y << endl; y = 7; cout << "x = " << x << endl << "y = " << y << endl; 16 return 0; // indicates successful termination 18 19 } // end main fig03_22.cpp (1 of 1) fig03_22.cpp output (1 of 1) Uninitialized reference – compiler error. Borland C++ command-line compiler error message:  Error E2304 Fig03_22.cpp 11: Reference variable 'y' must be initialized­ in function main() Microsoft Visual C++ compiler error message:  D:\cpphtp4_examples\ch03\Fig03_22.cpp(11) : error C2530: 'y' : references must be initialized

111 Function call with omitted parameters
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

112 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

113 Overloaded functions distinguished by signature
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 Encodes function identifier with parameters Type-safe linkage Ensures proper overloaded function called

114 Compact way to make overloaded functions Format
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

115 Function Templates Example T is a formal type, used as parameter type
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);

116 maximum expects all parameters to be of the same type.
// Fig. 3.27: fig03_27.cpp // Using a function template. #include <iostream> 4 using std::cout; using std::cin; using std::endl; 8 // definition of function template maximum 10 template < class T > // or template < typename T > 11 T maximum( T value1, T value2, T value3 ) 12 { T max = value1; 14 if ( value2 > max ) max = value2; 17 if ( value3 > max ) max = value3; 20 return max; 22 23 } // end function template maximum 24 fig03_27.cpp (1 of 3) Formal type parameter T placeholder for type of data to be tested by maximum. maximum expects all parameters to be of the same type.

117 maximum called with various data types.
25 int main() 26 { // demonstrate maximum with int values int int1, int2, int3; 29 cout << "Input three integer values: "; cin >> int1 >> int2 >> int3; 32 // invoke int version of maximum cout << "The maximum integer value is: " << maximum( int1, int2, int3 ); 36 // demonstrate maximum with double values double double1, double2, double3; 39 cout << "\n\nInput three double values: "; cin >> double1 >> double2 >> double3; 42 // invoke double version of maximum cout << "The maximum double value is: " << maximum( double1, double2, double3 ); 46 fig03_27.cpp (2 of 3) maximum called with various data types.

118 fig03_27.cpp (3 of 3) fig03_27.cpp output (1 of 1)
// demonstrate maximum with char values char char1, char2, char3; 49 cout << "\n\nInput three characters: "; cin >> char1 >> char2 >> char3; 52 // invoke char version of maximum cout << "The maximum character value is: " << maximum( char1, char2, char3 ) << endl; 57 return 0; // indicates successful termination 59 60 } // end main fig03_27.cpp (3 of 3) fig03_27.cpp output (1 of 1) Input three integer values: 1 2 3 The maximum integer value is: 3 Input three double values: The maximum double value is: 3.3 Input three characters: A C B The maximum character value is: C

119 Arrays Array To refer to an element N-element array c
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

120 Array elements like other variables
Arrays Array elements like other variables Assignment, printing for an integer array c c[ 0 ] = 3; cout << c[ 0 ]; Can perform operations inside subscript c[ 5 – 2 ] same as c[3]

121 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 ];

122 Examples Using Arrays Initializing arrays For loop Initializer list
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 same value int n[ 5 ] = { 0 }; If array size omitted, initializers determine size int n[] = { 1, 2, 3, 4, 5 }; 5 initializers, therefore 5 element array

123 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'

124 Examples Using Arrays Input from keyboard Printing strings
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

125 Examples Using Arrays Recall static storage If not static
If static, local variables save values between function calls Visible only in function body Can declare local arrays to be static Initialized to zero static int array[3]; If not static Created (and destroyed) in every function call

126 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

127 Passing Arrays to Functions
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 Individual array elements passed-by-value Like regular variables square( myArray[3] );

128 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 [] );

129 Syntax for accepting an array in parameter list.
// Fig. 4.14: fig04_14.cpp // Passing arrays and individual array elements to functions. #include <iostream> 4 using std::cout; using std::endl; 7 #include <iomanip> 9 10 using std::setw; 11 12 void modifyArray( int [], int ); // appears strange 13 void modifyElement( int ); 14 15 int main() 16 { const int arraySize = 5; // size of array a int a[ arraySize ] = { 0, 1, 2, 3, 4 }; // initialize a 19 cout << "Effects of passing entire array by reference:" << "\n\nThe values of the original array are:\n"; 22 // output original array for ( int i = 0; i < arraySize; i++ ) cout << setw( 3 ) << a[ i ]; fig04_14.cpp (1 of 3) Syntax for accepting an array in parameter list.

130 Pass a single array element by value; the original cannot be modified.
26 cout << endl; 28 // pass array a to modifyArray by reference modifyArray( a, arraySize ); 31 cout << "The values of the modified array are:\n"; 33 // output modified array for ( int j = 0; j < arraySize; j++ ) cout << setw( 3 ) << a[ j ]; 37 // output value of a[ 3 ] cout << "\n\n\n" << "Effects of passing array element by value:" << "\n\nThe value of a[3] is " << a[ 3 ] << '\n'; 42 // pass array element a[ 3 ] by value modifyElement( a[ 3 ] ); 45 // output value of a[ 3 ] cout << "The value of a[3] is " << a[ 3 ] << endl; 48 return 0; // indicates successful termination 50 51 } // end main Pass array name (a) and size to function. Arrays are passed-by-reference. fig04_14.cpp (2 of 3) Pass a single array element by value; the original cannot be modified.

131 52 53 // in function modifyArray, "b" points to 54 // the original array "a" in memory 55 void modifyArray( int b[], int sizeOfArray ) 56 { // multiply each array element by 2 for ( int k = 0; k < sizeOfArray; k++ ) b[ k ] *= 2; 60 61 } // end function modifyArray 62 63 // in function modifyElement, "e" is a local copy of 64 // array element a[ 3 ] passed from main 65 void modifyElement( int e ) 66 { // multiply parameter by 2 cout << "Value in modifyElement is " << ( e *= 2 ) << endl; 70 71 } // end function modifyElement Although named b, the array points to the original array a. It can modify a’s data. fig04_14.cpp (3 of 3) Individual array elements are passed by value, and the originals cannot be changed.

132 Effects of passing entire array by reference:
The values of the original array are: The values of the modified array are: Effects of passing array element by value: The value of a[3] is 6 Value in modifyElement is 12 fig04_14.cpp output (1 of 1)

133 // Fig. 4.15: fig04_15.cpp // Demonstrating the const type qualifier. #include <iostream> 4 using std::cout; using std::endl; 7 void tryToModifyArray( const int [] ); // function prototype 9 10 int main() 11 { int a[] = { 10, 20, 30 }; 13 tryToModifyArray( a ); 15 cout << a[ 0 ] << ' ' << a[ 1 ] << ' ' << a[ 2 ] << '\n'; 17 return 0; // indicates successful termination 19 20 } // end main 21 Array parameter declared as const. Array cannot be modified, even though it is passed by reference. fig04_15.cpp (1 of 2)

134 fig04_15.cpp (2 of 2) fig04_15.cpp output (1 of 1)
22 // In function tryToModifyArray, "b" cannot be used 23 // to modify the original array "a" in main. 24 void tryToModifyArray( const int b[] ) 25 { b[ 0 ] /= 2; // error b[ 1 ] /= 2; // error b[ 2 ] /= 2; // error 29 30 } // end function tryToModifyArray fig04_15.cpp (2 of 2) fig04_15.cpp output (1 of 1) d:\cpphtp4_examples\ch04\Fig04_15.cpp(26) : error C2166: l-value specifies const object d:\cpphtp4_examples\ch04\Fig04_15.cpp(27) : error C2166: l-value specifies const object d:\cpphtp4_examples\ch04\Fig04_15.cpp(28) : error C2166: l-value specifies const object

135 Sorting Arrays Example: Swap function?
Go left to right, and exchange elements as necessary One pass for each element Original: Pass 1: (elements exchanged) Pass 2: Pass 3: (no changes needed) Pass 4: Pass 5: Small elements "bubble" to the top (like 2 in this example) Swap function?

136 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 ] Column subscript Array name Row subscript

137 Multiple-Subscripted Arrays
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 } }; 1 2 3 4 Row 0 Row 1 1 0 3 4

138 Can declare pointers to any data type Pointer initialization
Powerful, but difficult to master Simulate pass-by-reference Close relationship with arrays and strings Can declare pointers to any data type Pointer initialization Initialized to 0, NULL, or address 0 or NULL points to nothing

139 Pointer Variable Declarations and Initialization
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 count 7 countPtr

140 Pointer Operators & (address operator)
Returns memory address of its operand Example int y = 5; int *yPtr; yPtr = &y; // yPtr gets address of y yPtr “points to” y yPtr y 5 yptr 500000 600000 address of y is value of yptr

141 * (indirection/dereferencing operator)
Pointer Operators * (indirection/dereferencing operator) Returns synonym for object its pointer operand points to *yPtr returns y (because yPtr points to y). dereferenced pointer is lvalue *yptr = 9; // assigns 9 to y * and & are inverses of each other

142 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 return can return one value from function Arguments passed to function using reference arguments Modify original values of arguments More than one value “returned”

143 Calling Functions by Reference
Pass-by-reference with pointer arguments Simulate pass-by-reference Use pointers and indirection operator Pass address of argument using & operator Arrays not passed with & because array name already pointer * operator used as alias/nickname for variable inside of function

144 Prototype indicates parameter is pointer to int
// Fig. 5.7: fig05_07.cpp // Cube a variable using pass-by-reference // with a pointer argument. #include <iostream> 5 using std::cout; using std::endl; 8 void cubeByReference( int * ); // prototype 10 11 int main() 12 { int number = 5; 14 cout << "The original value of number is " << number; 16 // pass address of number to cubeByReference cubeByReference( &number ); 19 cout << "\nThe new value of number is " << number << endl; 21 return 0; // indicates successful termination 23 24 } // end main 25 fig05_07.cpp (1 of 2) Prototype indicates parameter is pointer to int Apply address operator & to pass address of number to cubeByReference cubeByReference modified variable number

145 fig05_07.cpp (2 of 2) fig05_07.cpp output (1 of 1)
26 // calculate cube of *nPtr; modifies variable number in main 27 void cubeByReference( int *nPtr ) 28 { *nPtr = *nPtr * *nPtr * *nPtr; // cube *nPtr 30 31 } // end function cubeByReference cubeByReference receives address of int variable, i.e., pointer to an int fig05_07.cpp (2 of 2) fig05_07.cpp output (1 of 1) Modify and access int variable using indirection operator * The original value of number is 5 The new value of number is 125

146 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 Award function enough access to accomplish task, but no more 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

147 Using const with Pointers
const pointers Always point to same memory location Default for array name Must be initialized when declared

148 fig05_13.cpp (1 of 1) fig05_13.cpp output (1 of 1)
// Fig. 5.13: fig05_13.cpp // Attempting to modify a constant pointer to // non-constant data. 4 int main() { int x, y; 8 // ptr is a constant pointer to an integer that can // be modified through ptr, but ptr always points to the // same memory location. int * const ptr = &x; 13 *ptr = 7; // allowed: *ptr is not const ptr = &y; // error: ptr is const; cannot assign new address 16 return 0; // indicates successful termination 18 19 } // end main fig05_13.cpp (1 of 1) fig05_13.cpp output (1 of 1) 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_examples\ch05\Fig05_13.cpp(15) : error C2166: l-value specifies const object

149 ptr is constant pointer to integer constant.
// Fig. 5.14: fig05_14.cpp // Attempting to modify a constant pointer to constant data. #include <iostream> 4 using std::cout; using std::endl; 7 int main() { int x = 5, y; 11 // ptr is a constant pointer to a constant integer. // ptr always points to the same location; the integer // at that location cannot be modified. const int *const ptr = &x; 16 cout << *ptr << endl; 18 *ptr = 7; // error: *ptr is const; cannot assign new value ptr = &y; // error: ptr is const; cannot assign new address 21 return 0; // indicates successful termination 23 24 } // end main fig05_14.cpp (1 of 1) 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.

150 d:\cpphtp4_examples\ch05\Fig05_14
d:\cpphtp4_examples\ch05\Fig05_14.cpp(19) : error C2166: l-value specifies const object d:\cpphtp4_examples\ch05\Fig05_14.cpp(20) : error C2166: l-value specifies const object Line 19 generates compiler error by attempting to modify constant object. Line 20 generates compiler error by attempting to assign new address to constant pointer. fig05_14.cpp output (1 of 1)

151 Pointer Expressions and 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

152 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

153 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)

154 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 ]

155 Arrays can contain pointers
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’ ’m’ ’o’ ’n’ ’d’ ’C’ ’l’ ’u’ ’b’ ’S’ ’p’

156 Calling functions using pointers
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

157 // Fig. 5.25: fig05_25.cpp // Multipurpose sorting program using function pointers. #include <iostream> 4 using std::cout; using std::cin; using std::endl; 8 #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 { const int arraySize = 10; int order; int counter; int a[ arraySize ] = { 2, 6, 4, 8, 10, 12, 89, 68, 45, 37 }; 25 fig05_25.cpp (1 of 5) Parameter is pointer to function that receives two integer parameters and returns bool result.

158 26 cout << "Enter 1 to sort in ascending order,\n"
<< "Enter 2 to sort in descending order: "; cin >> order; cout << "\nData items in original order\n"; 30 // output original array for ( counter = 0; counter < arraySize; counter++ ) cout << setw( 4 ) << a[ counter ]; 34 // sort array in ascending order; pass function ascending // as an argument to specify ascending sorting order if ( order == 1 ) { bubble( a, arraySize, ascending ); cout << "\nData items in ascending order\n"; } 41 // sort array in descending order; pass function descending // as an agrument to specify descending sorting order else { bubble( a, arraySize, descending ); cout << "\nData items in descending order\n"; } 48 fig05_25.cpp (2 of 5)

159 Parentheses necessary to indicate pointer to function
// output sorted array for ( counter = 0; counter < arraySize; counter++ ) cout << setw( 4 ) << a[ counter ]; 52 cout << endl; 54 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, bool (*compare)( int, int ) ) 63 { // loop to control passes for ( int pass = 1; pass < size; pass++ ) 66 // loop to control number of comparisons per pass for ( int count = 0; count < size - 1; count++ ) 69 // if adjacent elements are out of order, swap them if ( (*compare)( work[ count ], work[ count + 1 ] ) ) swap( &work[ count ], &work[ count + 1 ] ); fig05_25.cpp (3 of 5) 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.

160 fig05_25.cpp (4 of 5) 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 { int hold = *element1Ptr; *element1Ptr = *element2Ptr; *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 { return b < a; // swap if b is less than a 91 92 } // end function ascending 93 fig05_25.cpp (4 of 5)

161 fig05_25.cpp (5 of 5) fig05_25.cpp output (1 of 1)
94 // determine whether elements are out of order 95 // for a descending order sort 96 bool descending( int a, int b ) 97 { return b > a; // swap if b is greater than a 99 100 } // end function descending fig05_25.cpp (5 of 5) fig05_25.cpp output (1 of 1) Enter 1 to sort in ascending order, Enter 2 to sort in descending order: 1 Data items in original order Data items in ascending order Enter 1 to sort in ascending order, Enter 2 to sort in descending order: 2 Data items in original order Data items in descending order

162 Arrays of pointers to functions
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

163 // Fig. 5.26: fig05_26.cpp // Demonstrating an array of pointers to functions. #include <iostream> 4 using std::cout; using std::cin; using std::endl; 8 // function prototypes 10 void function1( int ); 11 void function2( int ); 12 void function3( int ); 13 14 int main() 15 { // initialize array of 3 pointers to functions that each // take an int argument and return void void (*f[ 3 ])( int ) = { function1, function2, function3 }; 19 int choice; 21 cout << "Enter a number between 0 and 2, 3 to end: "; cin >> choice; 24 fig05_26.cpp (1 of 3) Array initialized with names of three functions; function names are pointers.

164 Call chosen function by dereferencing corresponding element in array.
// process user's choice while ( choice >= 0 && choice < 3 ) { 27 // invoke function at location choice in array f // and pass choice as an argument (*f[ choice ])( choice ); 31 cout << "Enter a number between 0 and 2, 3 to end: "; cin >> choice; } 35 cout << "Program execution completed." << endl; 37 return 0; // indicates successful termination 39 40 } // end main 41 42 void function1( int a ) 43 { cout << "You entered " << a << " so function1 was called\n\n"; 46 47 } // end function1 48 fig05_26.cpp (2 of 3) Call chosen function by dereferencing corresponding element in array.

165 fig05_26.cpp (3 of 3) fig05_26.cpp output (1 of 1)
49 void function2( int b ) 50 { cout << "You entered " << b << " so function2 was called\n\n"; 53 54 } // end function2 55 56 void function3( int c ) 57 { cout << "You entered " << c << " so function3 was called\n\n"; 60 61 } // end function3 fig05_26.cpp (3 of 3) fig05_26.cpp output (1 of 1) 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.

166 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

167 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’ };

168 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')

169 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' );

170 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)

171 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.

172 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 to­ken 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.

173 IS 0020 Program Design and Software Tools Introduction to C++ Programming
Lecture 3 Jan 20, 2004

174 Quiz 1 Average: about 3.8 More than half obtained: 4 + Highest is 8 Need more work/practice!

175 Quiz 1 Question 1 int i; for ( i= 2; i < 20; i = i + i ){
printf(“%d, ”, i); i = i + 1; } Answer: 2, 6, 14

176 Quiz 1 Question 2 int sum = 0; int i = 1, j = 1; while (i = 5){
sum = sum + i; if (sum == 20) break; j++; } printf( “%d, %d”, i, j); Answer: 5, 4

177 Question 3 Quiz 1 x = 0; y = 5; do { switch (x) { case “2”: case “3”:
y += 3 * x; break; default: y += x; } } while (++x < 5); Answer: x = 5, y = 25

178 Question 3 Quiz 1 Answer 1: for x = 5 and any value of y
Consider the condition shown below. For what values of x and y will the values of z be as follows (state your answer in the back of the paper): z = 10 z = 20 Condition: ((x == 5 || 7 < y && (100 – 2*50))?z = 10: z = 20) Answer 1: for x = 5 and any value of y Answer 2: for x ≠ 5 and any value of y

179 Arrays of pointers to functions
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

180 // Fig. 5.26: fig05_26.cpp // Demonstrating an array of pointers to functions. #include <iostream> 4 using std::cout; using std::cin; using std::endl; 8 // function prototypes 10 void function1( int ); 11 void function2( int ); 12 void function3( int ); 13 14 int main() 15 { // initialize array of 3 pointers to functions that each // take an int argument and return void void (*f[ 3 ])( int ) = { function1, function2, function3 }; 19 int choice; 21 cout << "Enter a number between 0 and 2, 3 to end: "; cin >> choice; 24 fig05_26.cpp (1 of 3) Array initialized with names of three functions; function names are pointers.

181 Call chosen function by dereferencing corresponding element in array.
// process user's choice while ( choice >= 0 && choice < 3 ) { 27 // invoke function at location choice in array f // and pass choice as an argument (*f[ choice ])( choice ); 31 cout << "Enter a number between 0 and 2, 3 to end: "; cin >> choice; } 35 cout << "Program execution completed." << endl; 37 return 0; // indicates successful termination 39 40 } // end main 41 42 void function1( int a ) 43 { cout << "You entered " << a << " so function1 was called\n\n"; 46 47 } // end function1 48 fig05_26.cpp (2 of 3) Call chosen function by dereferencing corresponding element in array.

182 fig05_26.cpp (3 of 3) fig05_26.cpp output (1 of 1)
49 void function2( int b ) 50 { cout << "You entered " << b << " so function2 was called\n\n"; 53 54 } // end function2 55 56 void function3( int c ) 57 { cout << "You entered " << c << " so function3 was called\n\n"; 60 61 } // end function3 fig05_26.cpp (3 of 3) fig05_26.cpp output (1 of 1) 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.

183 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

184 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’ };

185 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')

186 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' ); cin.get() Read character and returns that character char c; c = cin.get(); Could use a Condition like ((c = cin.get())!= ‘\n’);

187 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)

188 Classes

189 Object-oriented programming (OOP)
Introduction Object-oriented programming (OOP) Encapsulates data (attributes) and functions (behavior) into packages called classes Information hiding Class objects communicate across well-defined interfaces Implementation details hidden within classes themselves User-defined (programmer-defined) types: classes Data (data members) Functions (member functions or methods) Similar to blueprints – reusable Class instance: object

190 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

191 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;

192 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 .

193 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

194 Define structure type Time with three integer members.
// Fig. 6.1: fig06_01.cpp // Create a structure, set its members, and print it. #include <iostream> 4 using std::cout; using std::endl; 7 #include <iomanip> 9 10 using std::setfill; 11 using std::setw; 12 13 // structure definition 14 struct Time { int hour; // 0-23 (24-hour clock format) int minute; // 0-59 int second; // 0-59 18 19 }; // end struct Time 20 21 void printUniversal( const Time & ); // prototype 22 void printStandard( const Time & ); // prototype 23 fig06_01.cpp (1 of 3) Define structure type Time with three integer members. Pass references to constant Time objects to eliminate copying overhead.

195 Use dot operator to initialize structure members.
24 int main() 25 { Time dinnerTime; // variable of new type Time 27 dinnerTime.hour = 18; // set hour member of dinnerTime dinnerTime.minute = 30; // set minute member of dinnerTime dinnerTime.second = 0; // set second member of dinnerTime 31 cout << "Dinner will be held at "; printUniversal( dinnerTime ); cout << " universal time,\nwhich is "; printStandard( dinnerTime ); cout << " standard time.\n"; 37 dinnerTime.hour = 29; // set hour to invalid value dinnerTime.minute = 73; // set minute to invalid value 40 cout << "\nTime with invalid values: "; printUniversal( dinnerTime ); cout << endl; 44 return 0; 46 47 } // end main 48 Use dot operator to initialize structure members. fig06_01.cpp (2 of 3) Direct access to data allows assignment of bad values.

196 fig06_01.cpp (3 of 3) fig06_01.cpp output (1 of 1)
49 // print time in universal-time format 50 void printUniversal( const Time &t ) 51 { cout << setfill( '0' ) << setw( 2 ) << t.hour << ":" << setw( 2 ) << t.minute << ":" << setw( 2 ) << t.second; 55 56 } // end function printUniversal 57 58 // print time in standard-time format 59 void printStandard( const Time &t ) 60 { cout << ( ( t.hour == 0 || t.hour == 12 ) ? : t.hour % 12 ) << ":" << setfill( '0' ) << setw( 2 ) << t.minute << ":" << setw( 2 ) << t.second << ( t.hour < 12 ? " AM" : " PM" ); 66 67 } // end function printStandard fig06_01.cpp (3 of 3) fig06_01.cpp output (1 of 1) Use parameterized stream manipulator setfill. Use dot operator to access data members. Dinner will be held at 18:30:00 universal time, which is 6:30:00 PM standard time. Time with invalid values: 29:73:00

197 Implementing a Time Abstract Data Type with a class
Classes Model objects Attributes (data members) Behaviors (member functions) Defined using keyword class Member functions Methods Invoked in response to messages Member access specifiers public: Accessible wherever object of class in scope private: Accessible only to member functions of class protected:

198 Implementing a Time Abstract Data Type with a class
Constructor function Special member function Initializes data members Same name as class Called when object instantiated Several constructors Function overloading No return type

199 Class Time definition (1 of 1)
2 public: Time(); // constructor void setTime( int, int, int ); // set hour, minute, second void printUniversal(); // print universal-time format void printStandard(); // print standard-time format 8 private: int hour; // (24-hour clock format) int minute; // int second; // 13 14 }; // end class Time Definition of class begins with keyword class. Class body starts with left brace. Function prototypes for public member functions. Member access specifiers. Class Time definition (1 of 1) Constructor has same name as class, Time, and no return type. private data members accessible only to member functions. Class body ends with right brace. Definition terminates with semicolon.

200 Implementing a Time Abstract Data Type with a class
Objects of class After class definition Class name new type specifier C++ extensible language Object, array, pointer and reference declarations Example: Class name becomes new type specifier. 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

201 Implementing a Time Abstract Data Type with a class
Member functions defined outside class Binary scope resolution operator (::) “Ties” member name to class name Uniquely identify functions of particular class Different classes can have member functions with same name Format for defining member functions ReturnType ClassName::MemberFunctionName( ){ } Does not change whether function public or private Member functions defined inside class Do not need scope resolution operator, class name Compiler attempts inline Outside class, inline explicitly with keyword inline

202 fig06_03.cpp (1 of 5) Define class Time. 1 // Fig. 6.3: fig06_03.cpp
// Time class. #include <iostream> 4 using std::cout; using std::endl; 7 #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: Time(); // constructor void setTime( int, int, int ); // set hour, minute, second void printUniversal(); // print universal-time format void printStandard(); // print standard-time format 21 fig06_03.cpp (1 of 5) Define class Time.

203 Constructor initializes private data members to 0.
int hour; // (24-hour clock format) int minute; // int second; // 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 { 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 { hour = ( h >= 0 && h < 24 ) ? h : 0; minute = ( m >= 0 && m < 60 ) ? m : 0; second = ( s >= 0 && s < 60 ) ? s : 0; 44 45 } // end function setTime 46 fig06_03.cpp (2 of 5) Constructor initializes private data members to 0. public member function checks parameter values for validity before setting private data members.

204 Declare variable t to be object of class Time.
47 // print Time in universal format 48 void Time::printUniversal() 49 { cout << setfill( '0' ) << setw( 2 ) << hour << ":" << setw( 2 ) << minute << ":" << setw( 2 ) << second; 53 54 } // end function printUniversal 55 56 // print Time in standard format 57 void Time::printStandard() 58 { cout << ( ( hour == 0 || hour == 12 ) ? 12 : hour % 12 ) << ":" << setfill( '0' ) << setw( 2 ) << minute << ":" << setw( 2 ) << second << ( hour < 12 ? " AM" : " PM" ); 63 64 } // end function printStandard 65 66 int main() 67 { Time t; // instantiate object t of class Time 69 No arguments (implicitly “know” purpose is to print data members); member function calls more concise. fig06_03.cpp (3 of 5) Declare variable t to be object of class Time.

205 Invoke public member functions to print time. fig06_03.cpp (4 of 5)
// output Time object t's initial values cout << "The initial universal time is "; t.printUniversal(); // 00:00:00 73 cout << "\nThe initial standard time is "; t.printStandard(); // 12:00:00 AM 76 t.setTime( 13, 27, 6 ); // change time 78 // output Time object t's new values cout << "\n\nUniversal time after setTime is "; t.printUniversal(); // 13:27:06 82 cout << "\nStandard time after setTime is "; t.printStandard(); // 1:27:06 PM 85 t.setTime( 99, 99, 99 ); // attempt invalid settings 87 // output t's values after specifying invalid values cout << "\n\nAfter attempting invalid settings:" << "\nUniversal time: "; t.printUniversal(); // 00:00:00 92 Invoke public member functions to print time. fig06_03.cpp (4 of 5) Set data members using public member function. Attempt to set data members to invalid values using public member function.

206 fig06_03.cpp (5 of 5) fig06_03.cpp output (1 of 1)
cout << "\nStandard time: "; t.printStandard(); // 12:00:00 AM cout << endl; 96 return 0; 98 99 } // end main fig06_03.cpp (5 of 5) fig06_03.cpp output (1 of 1) 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.

207 Implementing a Time Abstract Data Type with a class
Destructors Same name as class Preceded with tilde (~) No arguments Cannot be overloaded Performs “termination housekeeping”

208 Implementing a Time Abstract Data Type with a class
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

209 Class Scope and Accessing Class Members
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

210 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

211 Class Scope and Accessing Class Members
Operators to access class members Identical to those for structs Dot member selection operator (.) Object Reference to object Arrow member selection operator (->) Pointers

212 // Fig. 6.4: fig06_04.cpp // Demonstrating the class member access operators . and -> // // CAUTION: IN FUTURE EXAMPLES WE AVOID PUBLIC DATA! #include <iostream> 6 using std::cout; using std::endl; 9 10 // class Count definition 11 class Count { 12 13 public: int x; 15 void print() { cout << x << endl; } 20 21 }; // end class Count 22 fig06_04.cpp (1 of 2) Data member x public to illustrate class member access operators; typically data members private.

213 fig06_04.cpp (2 of 2) fig06_04.cpp output (1 of 1)
23 int main() 24 { Count counter; // create counter object Count *counterPtr = &counter; // create pointer to counter Count &counterRef = counter; // create reference to counter 28 cout << "Assign 1 to x and print using the object's name: "; counter.x = 1; // assign 1 to data member x counter.print(); // call member function print 32 cout << "Assign 2 to x and print using a reference: "; counterRef.x = 2; // assign 2 to data member x counterRef.print(); // call member function print 36 cout << "Assign 3 to x and print using a pointer: "; counterPtr->x = 3; // assign 3 to data member x counterPtr->print(); // call member function print 40 return 0; 42 43 } // end main fig06_04.cpp (2 of 2) fig06_04.cpp output (1 of 1) Use dot member selection operator for counter object. Use dot member selection operator for counterRef reference to object. Use arrow member selection operator for counterPtr pointer to object. Assign 1 to x and print using the object's name: 1 Assign 2 to x and print using a reference: 2 Assign 3 to x and print using a pointer: 3

214 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

215 Separating Interface from Implementation
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

216 Preprocessor code to prevent multiple inclusions.
// Fig. 6.5: time1.h // Declaration of class Time. // Member functions are defined in time1.cpp 4 // prevent multiple inclusions of header file #ifndef TIME1_H #define TIME1_H 8 // Time abstract data type definition 10 class Time { 11 12 public: Time(); // constructor void setTime( int, int, int ); // set hour, minute, second void printUniversal(); // print universal-time format void printStandard(); // print standard-time format 17 18 private: int hour; // (24-hour clock format) int minute; // int second; // 22 23 }; // end class Time 24 25 #endif Preprocessor code to prevent multiple inclusions. time1.h (1 of 1) Code between these directives not included if name TIME1_H already defined. “If not defined” Preprocessor directive defines name TIME1_H. Naming convention: header file name with underscore replacing period.

217 Include header file time1.h.
// Fig. 6.6: time1.cpp // Member-function definitions for class Time. #include <iostream> 4 using std::cout; 6 #include <iomanip> 8 using std::setfill; 10 using std::setw; 11 12 // include definition of class Time from time1.h 13 #include "time1.h" 14 15 // Time constructor initializes each data member to zero. 16 // Ensures all Time objects start in a consistent state. 17 Time::Time() 18 { hour = minute = second = 0; 20 21 } // end Time constructor 22 time1.cpp (1 of 3) Include header file time1.h. Name of header file enclosed in quotes; angle brackets cause preprocessor to assume header part of C++ Standard Library.

218 23 // Set new Time value using universal time. Perform validity
24 // checks on the data values. Set invalid values to zero. 25 void Time::setTime( int h, int m, int s ) 26 { hour = ( h >= 0 && h < 24 ) ? h : 0; minute = ( m >= 0 && m < 60 ) ? m : 0; second = ( s >= 0 && s < 60 ) ? s : 0; 30 31 } // end function setTime 32 33 // print Time in universal format 34 void Time::printUniversal() 35 { cout << setfill( '0' ) << setw( 2 ) << hour << ":" << setw( 2 ) << minute << ":" << setw( 2 ) << second; 39 40 } // end function printUniversal 41 time1.cpp (2 of 3)

219 time1.cpp (3 of 3) 42 // print Time in standard format
43 void Time::printStandard() 44 { cout << ( ( hour == 0 || hour == 12 ) ? 12 : hour % 12 ) << ":" << setfill( '0' ) << setw( 2 ) << minute << ":" << setw( 2 ) << second << ( hour < 12 ? " AM" : " PM" ); 49 50 } // end function printStandard time1.cpp (3 of 3)

220 // Fig. 6.7: fig06_07.cpp // Program to test class Time. // NOTE: This file must be compiled with time1.cpp. #include <iostream> 5 using std::cout; using std::endl; 8 // include definition of class Time from time1.h 10 #include "time1.h" 11 12 int main() 13 { Time t; // instantiate object t of class Time 15 // output Time object t's initial values cout << "The initial universal time is "; t.printUniversal(); // 00:00:00 cout << "\nThe initial standard time is "; t.printStandard(); // 12:00:00 AM 21 t.setTime( 13, 27, 6 ); // change time 23 fig06_07.cpp (1 of 2) Include header file time1.h to ensure correct creation/manipulation and determine size of Time class object.

221 fig06_07.cpp (2 of 2) fig06_07.cpp output (1 of 1)
// output Time object t's new values cout << "\n\nUniversal time after setTime is "; t.printUniversal(); // 13:27:06 cout << "\nStandard time after setTime is "; t.printStandard(); // 1:27:06 PM 29 t.setTime( 99, 99, 99 ); // attempt invalid settings 31 // output t's values after specifying invalid values cout << "\n\nAfter attempting invalid settings:" << "\nUniversal time: "; t.printUniversal(); // 00:00:00 cout << "\nStandard time: "; t.printStandard(); // 12:00:00 AM cout << endl; 39 return 0; 41 42 } // end main fig06_07.cpp (2 of 2) fig06_07.cpp output (1 of 1) 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

222 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

223 // Fig. 6.8: fig06_08.cpp // Demonstrate errors resulting from attempts // to access private class members. #include <iostream> 5 using std::cout; 7 // include definition of class Time from time1.h #include "time1.h" 10 11 int main() 12 { Time t; // create Time object 14 15 t.hour = 7; // error: 'Time::hour' is not accessible 17 // error: 'Time::minute' is not accessible cout << "minute = " << t.minute; 20 return 0; 22 23 } // end main fig06_08.cpp (1 of 1) Recall data member hour is private; attempts to access private members results in error. Data member minute also private; attempts to access private members produces error.

224 Controlling Access to Members
Class member access Default private Explicitly set to private, public, protected struct member access Default public Access to class’s private data Controlled with access functions (accessor methods) Get function Read private data Set function Modify private data

225 Access Functions and Utility 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

226 Set access function performs validity checks.
// Fig. 6.9: salesp.h // SalesPerson class definition. // Member functions defined in salesp.cpp. #ifndef SALESP_H #define SALESP_H 6 class SalesPerson { 8 public: SalesPerson(); // constructor void getSalesFromUser(); // input sales from keyboard void setSales( int, double ); // set sales for a month void printAnnualSales(); // summarize and print sales 14 15 private: double totalAnnualSales(); // utility function double sales[ 12 ]; // 12 monthly sales figures 18 19 }; // end class SalesPerson 20 21 #endif salesp.h (1 of 1) Set access function performs validity checks. private utility function.

227 salesp.cpp (1 of 3) 1 // Fig. 6.10: salesp.cpp
// Member functions for class SalesPerson. #include <iostream> 4 using std::cout; using std::cin; using std::endl; using std::fixed; 9 10 #include <iomanip> 11 12 using std::setprecision; 13 14 // include SalesPerson class definition from salesp.h 15 #include "salesp.h" 16 17 // initialize elements of array sales to 0.0 18 SalesPerson::SalesPerson() 19 { for ( int i = 0; i < 12; i++ ) sales[ i ] = 0.0; 22 23 } // end SalesPerson constructor 24 salesp.cpp (1 of 3)

228 Set access function performs validity checks.
25 // get 12 sales figures from the user at the keyboard 26 void SalesPerson::getSalesFromUser() 27 { double salesFigure; 29 for ( int i = 1; i <= 12; i++ ) { cout << "Enter sales amount for month " << i << ": "; cin >> salesFigure; setSales( i, salesFigure ); 34 } // 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 { // test for valid month and amount values if ( month >= 1 && month <= 12 && amount > 0 ) sales[ month - 1 ] = amount; // adjust for subscripts 0-11 46 else // invalid month or amount value cout << "Invalid month or sales figure" << endl; salesp.cpp (2 of 3) Set access function performs validity checks.

229 49 50 } // end function setSales 51 52 // print total annual sales (with help of utility function) 53 void SalesPerson::printAnnualSales() 54 { cout << setprecision( 2 ) << fixed << "\nThe total annual sales are: $" << totalAnnualSales() << endl; // call utility function 58 59 } // end function printAnnualSales 60 61 // private utility function to total annual sales 62 double SalesPerson::totalAnnualSales() 63 { double total = 0.0; // initialize total 65 for ( int i = 0; i < 12; i++ ) // summarize sales results total += sales[ i ]; 68 return total; 70 71 } // end function totalAnnualSales salesp.cpp (3 of 3) private utility function to help function printAnnualSales; encapsulates logic of manipulating sales array.

230 // Fig. 6.11: fig06_11.cpp // Demonstrating a utility function. // Compile this program with salesp.cpp 4 // include SalesPerson class definition from salesp.h #include "salesp.h" 7 int main() { SalesPerson s; // create SalesPerson object s 11 s.getSalesFromUser(); // note simple sequential code; no s.printAnnualSales(); // control structures in main 14 return 0; 16 17 } // end main fig06_11.cpp (1 of 1) Simple sequence of member function calls; logic encapsulated in member functions.

231 fig06_11.cpp output (1 of 1) Enter sales amount for month 1: 5314.76
The total annual sales are: $ fig06_11.cpp output (1 of 1)

232 Initializing Class Objects: Constructors
Initialize data members Or can set later Same name as class No return type Initializers Passed as arguments to constructor In parentheses to right of class name before semicolon Class-type ObjectName( value1,value2,…);

233 Using Default Arguments with Constructors
Can specify default arguments Default constructors Defaults all arguments OR Explicitly requires no arguments Can be invoked with no arguments Only one per class

234 Default constructor specifying all arguments.
// Fig. 6.12: time2.h // Declaration of class Time. // Member functions defined in time2.cpp. 4 // prevent multiple inclusions of header file #ifndef TIME2_H #define TIME2_H 8 // Time abstract data type definition 10 class Time { 11 12 public: Time( int = 0, int = 0, int = 0); // default constructor void setTime( int, int, int ); // set hour, minute, second void printUniversal(); // print universal-time format void printStandard(); // print standard-time format 17 18 private: int hour; // (24-hour clock format) int minute; // int second; // 22 23 }; // end class Time 24 25 #endif time2.h (1 of 1) Default constructor specifying all arguments.

235 Constructor calls setTime to validate passed (or default) values.
// Fig. 6.13: time2.cpp // Member-function definitions for class Time. #include <iostream> 4 using std::cout; 6 #include <iomanip> 8 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 { setTime( hr, min, sec ); // validate and set time 20 21 } // end Time constructor 22 time2.cpp (1 of 3) Constructor calls setTime to validate passed (or default) values.

236 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 { hour = ( h >= 0 && h < 24 ) ? h : 0; minute = ( m >= 0 && m < 60 ) ? m : 0; second = ( s >= 0 && s < 60 ) ? s : 0; 30 31 } // end function setTime 32 33 // print Time in universal format 34 void Time::printUniversal() 35 { cout << setfill( '0' ) << setw( 2 ) << hour << ":" << setw( 2 ) << minute << ":" << setw( 2 ) << second; 39 40 } // end function printUniversal 41 time2.cpp (2 of 3)

237 Initialize Time objects using default arguments.
// Fig. 6.14: fig06_14.cpp // Demonstrating a default constructor for class Time. #include <iostream> 4 using std::cout; using std::endl; 7 // include definition of class Time from time2.h #include "time2.h" 10 11 int main() 12 { Time t1; // all arguments defaulted Time t2( 2 ); // minute and second defaulted Time t3( 21, 34 ); // second defaulted Time t4( 12, 25, 42 ); // all values specified Time t5( 27, 74, 99 ); // all bad values specified 18 cout << "Constructed with:\n\n" << "all default arguments:\n "; t1.printUniversal(); // 00:00:00 cout << "\n "; t1.printStandard(); // 12:00:00 AM 24 fig06_14.cpp (1 of 2) Initialize Time objects using default arguments. Initialize Time object with invalid values; validity checking will set values to 0.

238 t5 constructed with invalid arguments; values set to 0.
cout << "\n\nhour specified; default minute and second:\n "; t2.printUniversal(); // 02:00:00 cout << "\n "; t2.printStandard(); // 2:00:00 AM 29 cout << "\n\nhour and minute specified; default second:\n "; t3.printUniversal(); // 21:34:00 cout << "\n "; t3.printStandard(); // 9:34:00 PM 34 cout << "\n\nhour, minute, and second specified:\n "; t4.printUniversal(); // 12:25:42 cout << "\n "; t4.printStandard(); // 12:25:42 PM 39 cout << "\n\nall invalid values specified:\n "; t5.printUniversal(); // 00:00:00 cout << "\n "; t5.printStandard(); // 12:00:00 AM cout << endl; 45 return 0; 47 48 } // end main fig06_14.cpp (2 of 2) t5 constructed with invalid arguments; values set to 0.

239 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”

240 When Constructors and Destructors Are Called
Called implicitly by compiler Order of function calls Depends on order of execution When execution enters and exits scope of objects Generally, destructor calls reverse order of constructor calls

241 When Constructors and Destructors Are Called
Order of constructor, destructor function calls 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 When objects defined Each time execution enters scope When objects leave scope Execution exits block in which object defined Not called if program ends with exit or abort

242 When Constructors and Destructors Are Called
Order of constructor, destructor function calls 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

243 Constructor and destructor member functions.
// Fig. 6.15: create.h // Definition of class CreateAndDestroy. // Member functions defined in create.cpp. #ifndef CREATE_H #define CREATE_H 6 class CreateAndDestroy { 8 public: CreateAndDestroy( int, char * ); // constructor ~CreateAndDestroy(); // destructor 12 13 private: int objectID; char *message; 16 17 }; // end class CreateAndDestroy 18 19 #endif create.h (1 of 1) Constructor and destructor member functions. private members to show order of constructor, destructor function calls.

244 Output message to demonstrate timing of constructor function calls.
// Fig. 6.16: create.cpp // Member-function definitions for class CreateAndDestroy #include <iostream> 4 using std::cout; using std::endl; 7 // include CreateAndDestroy class definition from create.h #include "create.h" 10 11 // constructor 12 CreateAndDestroy::CreateAndDestroy( int objectNumber, char *messagePtr ) 14 { objectID = objectNumber; message = messagePtr; 17 cout << "Object " << objectID << " constructor runs " << message << endl; 20 21 } // end CreateAndDestroy constructor 22 create.cpp (1 of 2) Output message to demonstrate timing of constructor function calls.

245 Output message to demonstrate timing of destructor function calls.
24 CreateAndDestroy::~CreateAndDestroy() 25 { // the following line is for pedagogic purposes only cout << ( objectID == 1 || objectID == 6 ? "\n" : "" ); 28 cout << "Object " << objectID << " destructor runs " << message << endl; 31 32 } // end ~CreateAndDestroy destructor Output message to demonstrate timing of destructor function calls. create.cpp (2 of 2)

246 Create variable with global scope.
// Fig. 6.17: fig06_17.cpp // Demonstrating the order in which constructors and // destructors are called. #include <iostream> 5 using std::cout; using std::endl; 8 // 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 { cout << "\nMAIN FUNCTION: EXECUTION BEGINS" << endl; 20 CreateAndDestroy second( 2, "(local automatic in main)" ); 22 static CreateAndDestroy third( , "(local static in main)" ); 25 fig06_17.cpp (1 of 3) Create variable with global scope. Create local automatic object. Create static local object.

247 Create local automatic objects. fig06_17.cpp (2 of 3)
create(); // call function to create objects 27 cout << "\nMAIN FUNCTION: EXECUTION RESUMES" << endl; 29 CreateAndDestroy fourth( 4, "(local automatic in main)" ); 31 cout << "\nMAIN FUNCTION: EXECUTION ENDS" << endl; 33 return 0; 35 36 } // end main 37 38 // function to create objects 39 void create( void ) 40 { cout << "\nCREATE FUNCTION: EXECUTION BEGINS" << endl; 42 CreateAndDestroy fifth( 5, "(local automatic in create)" ); 44 static CreateAndDestroy sixth( , "(local static in create)" ); 47 CreateAndDestroy seventh( , "(local automatic in create)" ); 50 Create local automatic objects. fig06_17.cpp (2 of 3) Create local automatic object. Create local automatic object in function. Create static local object in function. Create local automatic object in function.

248 51 cout << "\nCREATE FUNCTION: EXECUTION ENDS\" << endl;
52 53 } // end function create fig06_17.cpp (3 of 3)

249 Global object constructed before main execution and destroyed last.
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) Global object constructed before main execution and destroyed last. fig06_17.cpp output (1 of 1) Destructors for local automatic objects in main called in reverse order of constructors. Local static object exists until program termination. 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.

250 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

251 time3.h (1 of 2) Set functions. Get functions. 1 // Fig. 6.18: time3.h
// Declaration of class Time. // Member functions defined in time3.cpp 4 // prevent multiple inclusions of header file #ifndef TIME3_H #define TIME3_H 8 class Time { 10 11 public: Time( int = 0, int = 0, int = 0 ); // default constructor 13 // set functions void setTime( int, int, int ); // set hour, minute, second void setHour( int ); // set hour void setMinute( int ); // set minute void setSecond( int ); // set second 19 // get functions int getHour(); // return hour int getMinute(); // return minute int getSecond(); // return second 24 time3.h (1 of 2) Set functions. Get functions.

252 25 void printUniversal(); // output universal-time format
void printStandard(); // output standard-time format 27 28 private: int hour; // (24-hour clock format) int minute; // int second; // 32 33 }; // end clas Time 34 35 #endif time3.h (2 of 2)

253 time3.cpp (1 of 4) 1 // Fig. 6.19: time3.cpp
// Member-function definitions for Time class. #include <iostream> 4 using std::cout; 6 #include <iomanip> 8 using std::setfill; 10 using std::setw; 11 12 // include definition of class Time from time3.h 13 #include "time3.h" 14 15 // constructor function to initialize private data; 16 // calls member function setTime to set variables; 17 // default values are 0 (see class definition) 18 Time::Time( int hr, int min, int sec ) 19 { setTime( hr, min, sec ); 21 22 } // end Time constructor 23 time3.cpp (1 of 4)

254 Call set functions to perform validity checking.
24 // set hour, minute and second values 25 void Time::setTime( int h, int m, int s ) 26 { setHour( h ); setMinute( m ); setSecond( s ); 30 31 } // end function setTime 32 33 // set hour value 34 void Time::setHour( int h ) 35 { hour = ( h >= 0 && h < 24 ) ? h : 0; 37 38 } // end function setHour 39 40 // set minute value 41 void Time::setMinute( int m ) 42 { minute = ( m >= 0 && m < 60 ) ? m : 0; 44 45 } // end function setMinute 46 time3.cpp (2 of 4) Call set functions to perform validity checking. Set functions perform validity checks before modifying data.

255 Set function performs validity checks before modifying data.
47 // set second value 48 void Time::setSecond( int s ) 49 { second = ( s >= 0 && s < 60 ) ? s : 0; 51 52 } // end function setSecond 53 54 // return hour value 55 int Time::getHour() 56 { return hour; 58 59 } // end function getHour 60 61 // return minute value 62 int Time::getMinute() 63 { return minute; 65 66 } // end function getMinute 67 Set function performs validity checks before modifying data. time3.cpp (3 of 4) Get functions allow client to read data.

256 Get function allows client to read data. time3.cpp (4 of 4)
68 // return second value 69 int Time::getSecond() 70 { return second; 72 73 } // end function getSecond 74 75 // print Time in universal format 76 void Time::printUniversal() 77 { cout << setfill( '0' ) << setw( 2 ) << hour << ":" << setw( 2 ) << minute << ":" << setw( 2 ) << second; 81 82 } // end function printUniversal 83 84 // print Time in standard format 85 void Time::printStandard() 86 { cout << ( ( hour == 0 || hour == 12 ) ? 12 : hour % 12 ) << ":" << setfill( '0' ) << setw( 2 ) << minute << ":" << setw( 2 ) << second << ( hour < 12 ? " AM" : " PM" ); 91 92 } // end function printStandard Get function allows client to read data. time3.cpp (4 of 4)

257 Invoke set functions to set valid values.
// Fig. 6.20: fig06_20.cpp // Demonstrating the Time class set and get functions #include <iostream> 4 using std::cout; using std::endl; 7 // include definition of class Time from time3.h #include "time3.h" 10 11 void incrementMinutes( Time &, const int ); // prototype 12 13 int main() 14 { Time t; // create Time object 16 // set time using individual set functions t.setHour( 17 ); // set hour to valid value t.setMinute( 34 ); // set minute to valid value t.setSecond( 25 ); // set second to valid value 21 fig06_20.cpp (1 of 3) Invoke set functions to set valid values.

258 Attempt to set invalid values using set functions.
// use get functions to obtain hour, minute and second cout << "Result of setting all valid values:\n" << " Hour: " << t.getHour() << " Minute: " << t.getMinute() << " Second: " << t.getSecond(); 27 // set time using individual set functions t.setHour( 234 ); // invalid hour set to 0 t.setMinute( 43 ); // set minute to valid value t.setSecond( 6373 ); // invalid second set to 0 32 // display hour, minute and second after setting // invalid hour and second values cout << "\n\nResult of attempting to set invalid hour and" << " second:\n Hour: " << t.getHour() << " Minute: " << t.getMinute() << " Second: " << t.getSecond() << "\n\n"; 39 t.setTime( 11, 58, 0 ); // set time incrementMinutes( t, 3 ); // increment t's minute by 3 42 return 0; 44 45 } // end main 46 Attempt to set invalid values using set functions. fig06_20.cpp (2 of 3) Invalid values result in setting data members to 0. Modify data members using function setTime.

259 Using get functions to read data and set functions to modify data.
47 // add specified number of minutes to a Time object 48 void incrementMinutes( Time &tt, const int count ) 49 { cout << "Incrementing minute " << count << " times:\nStart time: "; tt.printStandard(); 53 for ( int i = 0; i < count; i++ ) { tt.setMinute( ( tt.getMinute() + 1 ) % 60 ); 56 if ( tt.getMinute() == 0 ) tt.setHour( ( tt.getHour() + 1 ) % 24); 59 cout << "\nminute + 1: "; tt.printStandard(); 62 } // end for 64 cout << endl; 66 67 } // end function incrementMinutes fig06_20.cpp (3 of 3) Using get functions to read data and set functions to modify data.

260 Result of setting all valid values:
Hour: 17 Minute: 34 Second: 25 Result of attempting to set invalid hour and second: Hour: 0 Minute: 43 Second: 0 Incrementing minute 3 times: Start time: 11:58:00 AM minute + 1: 11:59:00 AM minute + 1: 12:00:00 PM minute + 1: 12:01:00 PM fig06_20.cpp output (1 of 1) Attempting to set data members with invalid values results in error message and members set to 0.

261 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

262 // Fig. 6.21: time4.h // Declaration of class Time. // Member functions defined in time4.cpp 4 // prevent multiple inclusions of header file #ifndef TIME4_H #define TIME4_H 8 class Time { 10 11 public: Time( int = 0, int = 0, int = 0 ); void setTime( int, int, int ); int getHour(); 15 int &badSetHour( int ); // DANGEROUS reference return 17 18 private: int hour; int minute; int second; 22 23 }; // end class Time 24 25 #endif time4.h (1 of 1) Function to demonstrate effects of returning reference to private data member.

263 time4.cpp (1 of 2) 1 // Fig. 6.22: time4.cpp
// Member-function definitions for Time class. 3 // include definition of class Time from time4.h #include "time4.h" 6 // constructor function to initialize private data; // calls member function setTime to set variables; // default values are 0 (see class definition) 10 Time::Time( int hr, int min, int sec ) 11 { setTime( hr, min, sec ); 13 14 } // end Time constructor 15 16 // set values of hour, minute and second 17 void Time::setTime( int h, int m, int s ) 18 { hour = ( h >= 0 && h < 24 ) ? h : 0; minute = ( m >= 0 && m < 60 ) ? m : 0; second = ( s >= 0 && s < 60 ) ? s : 0; 22 23 } // end function setTime 24 time4.cpp (1 of 2)

264 Return reference to private data member hour.
25 // return hour value 26 int Time::getHour() 27 { 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 { hour = ( hh >= 0 && hh < 24 ) ? hh : 0; 37 return hour; // DANGEROUS reference return 39 40 } // end function badSetHour time4.cpp (2 of 2) Return reference to private data member hour.

265 badSetHour returns reference to private data member hour.
// Fig. 6.23: fig06_23.cpp // Demonstrating a public member function that // returns a reference to a private data member. #include <iostream> 5 using std::cout; using std::endl; 8 // include definition of class Time from time4.h 10 #include "time4.h" 11 12 int main() 13 { Time t; 15 // store in hourRef the reference returned by badSetHour int &hourRef = t.badSetHour( 20 ); 18 cout << "Hour before modification: " << hourRef; 20 // use hourRef to set invalid value in Time object t hourRef = 30; 23 cout << "\nHour after modification: " << t.getHour(); 25 fig06_23.cpp (1 of 2) badSetHour returns reference to private data member hour. Reference allows setting of private data member hour.

266 fig06_23.cpp (2 of 2) fig06_23.cpp output (1 of 1)
// Dangerous: Function call that returns // a reference can be used as an lvalue! t.badSetHour( 12 ) = 74; 29 cout << "\n\n*********************************\n" << "POOR PROGRAMMING PRACTICE!!!!!!!!\n" << "badSetHour as an lvalue, Hour: " << t.getHour() << "\n*********************************" << endl; 35 return 0; 37 38 } // end main Can use function call as lvalue to set invalid value. fig06_23.cpp (2 of 2) fig06_23.cpp output (1 of 1) Hour before modification: 20 Hour after modification: 30 ********************************* POOR PROGRAMMING PRACTICE!!!!!!!! badSetHour as an lvalue, Hour: 74 Returning reference allowed invalid setting of private data member hour.

267 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

268 fig06_24.cpp (1 of 3) 1 // Fig. 6.24: fig06_24.cpp
// Demonstrating that class objects can be assigned // to each other using default memberwise assignment. #include <iostream> 5 using std::cout; using std::endl; 8 // class Date definition 10 class Date { 11 12 public: Date( int = 1, int = 1, int = 1990 ); // default constructor void print(); 15 16 private: int month; int day; int year; 20 21 }; // end class Date 22 fig06_24.cpp (1 of 3)

269 fig06_24.cpp (2 of 3) 23 // Date constructor with no range checking
24 Date::Date( int m, int d, int y ) 25 { month = m; day = d; year = y; 29 30 } // end Date constructor 31 32 // print Date in the format mm-dd-yyyy 33 void Date::print() 34 { cout << month << '-' << day << '-' << year; 36 37 } // end function print 38 39 int main() 40 { Date date1( 7, 4, 2002 ); Date date2; // date2 defaults to 1/1/1990 43 fig06_24.cpp (2 of 3)

270 fig06_24.cpp (3 of 3) fig06_24.cpp output (1 of 1)
cout << "date1 = "; date1.print(); cout << "\ndate2 = "; date2.print(); 48 date2 = date1; // default memberwise assignment 50 cout << "\n\nAfter default memberwise assignment, date2 = "; date2.print(); cout << endl; 54 return 0; 56 57 } // end main Default memberwise assignment assigns each member of date1 individually to each member of date2. fig06_24.cpp (3 of 3) fig06_24.cpp output (1 of 1) date1 = date2 = After default memberwise assignment, date2 =

271 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

272 const (Constant) Objects and const Member Functions
Principle of least privilege Only allow modification of necessary objects 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

273 const (Constant) Objects and 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

274 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

275 Declare const get functions.
// Fig. 7.1: time5.h // Definition of class Time. // Member functions defined in time5.cpp. #ifndef TIME5_H #define TIME5_H 6 class Time { 8 public: Time( int = 0, int = 0, int = 0 ); // default constructor 11 // set functions void setTime( int, int, int ); // set time void setHour( int ); // set hour void setMinute( int ); // set minute void setSecond( int ); // set second 17 // get functions (normally declared const) int getHour() const; // return hour int getMinute() const; // return minute int getSecond() const; // return second 22 // print functions (normally declared const) void printUniversal() const; // print universal time void printStandard(); // print standard time time5.h (1 of 2) Declare const get functions. Declare const function printUniversal.

276 26 27 private: int hour; // (24-hour clock format) int minute; // int second; // 31 32 }; // end class Time 33 34 #endif time5.h (2 of 2)

277 time5.cpp (1 of 4) 1 // Fig. 7.2: time5.cpp
// Member-function definitions for class Time. #include <iostream> 4 using std::cout; 6 #include <iomanip> 8 using std::setfill; 10 using std::setw; 11 12 // include definition of class Time from time5.h 13 #include "time5.h" 14 15 // constructor function to initialize private data; 16 // calls member function setTime to set variables; 17 // default values are 0 (see class definition) 18 Time::Time( int hour, int minute, int second ) 19 { setTime( hour, minute, second ); 21 22 } // end Time constructor 23 time5.cpp (1 of 4)

278 time5.cpp (2 of 4) 24 // set hour, minute and second values
25 void Time::setTime( int hour, int minute, int second ) 26 { setHour( hour ); setMinute( minute ); setSecond( second ); 30 31 } // end function setTime 32 33 // set hour value 34 void Time::setHour( int h ) 35 { hour = ( h >= 0 && h < 24 ) ? h : 0; 37 38 } // end function setHour 39 40 // set minute value 41 void Time::setMinute( int m ) 42 { minute = ( m >= 0 && m < 60 ) ? m : 0; 44 45 } // end function setMinute 46 time5.cpp (2 of 4)

279 const functions do not modify objects.
47 // set second value 48 void Time::setSecond( int s ) 49 { second = ( s >= 0 && s < 60 ) ? s : 0; 51 52 } // end function setSecond 53 54 // return hour value 55 int Time::getHour() const 56 { return hour; 58 59 } // end function getHour 60 61 // return minute value 62 int Time::getMinute() const 63 { return minute; 65 66 } // end function getMinute 67 time5.cpp (3 of 4) const functions do not modify objects.

280 const functions do not modify objects. time5.cpp (4 of 4)
68 // return second value 69 int Time::getSecond() const 70 { return second; 72 73 } // end function getSecond 74 75 // print Time in universal format 76 void Time::printUniversal() const 77 { cout << setfill( '0' ) << setw( 2 ) << hour << ":" << setw( 2 ) << minute << ":" << setw( 2 ) << second; 81 82 } // end function printUniversal 83 84 // print Time in standard format 85 void Time::printStandard() // note lack of const declaration 86 { cout << ( ( hour == 0 || hour == 12 ) ? 12 : hour % 12 ) << ":" << setfill( '0' ) << setw( 2 ) << minute << ":" << setw( 2 ) << second << ( hour < 12 ? " AM" : " PM" ); 91 92 } // end function printStandard const functions do not modify objects. time5.cpp (4 of 4)

281 Declare noon a const object.
// Fig. 7.3: fig07_03.cpp // Attempting to access a const object with // non-const member functions. 4 // include Time class definition from time5.h #include "time5.h" 7 int main() { Time wakeUp( 6, 45, 0 ); // non-constant object const Time noon( 12, 0, 0 ); // constant object 12 fig07_03.cpp (1 of 2) Declare noon a const object. Note that non-const constructor can initialize const object.

282 const (Constant) Objects and const Member Functions
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

283 fig07_04.cpp (1 of 3) 1 // Fig. 7.4: fig07_04.cpp
// Using a member initializer to initialize a // constant of a built-in data type. #include <iostream> 5 using std::cout; using std::endl; 8 class Increment { 10 11 public: Increment( int c = 0, int i = 1 ); // default constructor 13 void addIncrement() { count += increment; 17 } // end function addIncrement 19 void print() const; // prints count and increment 21 fig07_04.cpp (1 of 3)

284 Declare increment as const data member. fig07_04.cpp (2 of 3)
22 private: int count; const int increment; // const data member 25 26 }; // end class Increment 27 28 // constructor 29 Increment::Increment( int c, int i ) : count( c ), // initializer for non-const member increment( i ) // required initializer for const member 32 { // empty body 34 35 } // end Increment constructor 36 37 // print count and increment values 38 void Increment::print() const 39 { cout << "count = " << count << ", increment = " << increment << endl; 42 43 } // end function print 44 Declare increment as const data member. fig07_04.cpp (2 of 3) 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).

285 fig07_04.cpp (3 of 3) fig07_04.cpp output (1 of 1)
45 int main() 46 { Increment value( 10, 5 ); 48 cout << "Before incrementing: "; value.print(); 51 for ( int j = 0; j < 3; j++ ) { value.addIncrement(); cout << "After increment " << j + 1 << ": "; value.print(); } 57 return 0; 59 60 } // end main fig07_04.cpp (3 of 3) fig07_04.cpp output (1 of 1) Before incrementing: count = 10, increment = 5 After increment 1: count = 15, increment = 5 After increment 2: count = 20, increment = 5 After increment 3: count = 25, increment = 5

286 Composition: Objects as Members of Classes
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)

287 // Fig. 7.6: date1.h // Date class definition. // Member functions defined in date1.cpp #ifndef DATE1_H #define DATE1_H 6 class Date { 8 public: Date( int = 1, int = 1, int = 1900 ); // default constructor void print() const; // print date in month/day/year format ~Date(); // provided to confirm destruction order 13 14 private: int month; // 1-12 (January-December) int day; // 1-31 based on month int year; // any year 18 // utility function to test proper day for month and year int checkDay( int ) const; 21 22 }; // end class Date 23 24 #endif date1.h (1 of 1) Note no constructor with parameter of type Date. Recall compiler provides default copy constructor.

288 date1.cpp (1 of 3) 1 // Fig. 7.7: date1.cpp
// Member-function definitions for class Date. #include <iostream> 4 using std::cout; using std::endl; 7 // include Date class definition from date1.h #include "date1.h" 10 11 // constructor confirms proper value for month; calls 12 // utility function checkDay to confirm proper value for day 13 Date::Date( int mn, int dy, int yr ) 14 { if ( mn > 0 && mn <= 12 ) // validate the month month = mn; 17 else { // invalid month set to 1 month = 1; cout << "Month " << mn << " invalid. Set to month 1.\n"; } 22 year = yr; // should validate yr day = checkDay( dy ); // validate the day 25 date1.cpp (1 of 3)

289 // Fig. 7.8: employee1.h // Employee class definition. // Member functions defined in employee1.cpp. #ifndef EMPLOYEE1_H #define EMPLOYEE1_H 6 // include Date class definition from date1.h #include "date1.h" 9 10 class Employee { 11 12 public: Employee( const char *, const char *, const Date &, const Date & ); 15 void print() const; ~Employee(); // provided to confirm destruction order 18 19 private: char firstName[ 25 ]; char lastName[ 25 ]; const Date birthDate; // composition: member object const Date hireDate; // composition: member object 24 25 }; // end class Employee employee1.h (1 of 2) Using composition; Employee object contains Date objects as data members.

290 employee1.h (2 of 2) employee1.cpp (1 of 3)
26 27 #endif employee1.h (2 of 2) employee1.cpp (1 of 3) // Fig. 7.9: employee1.cpp // Member-function definitions for class Employee. #include <iostream> 4 using std::cout; using std::endl; 7 #include <cstring> // strcpy and strlen prototypes 9 10 #include "employee1.h" // Employee class definition 11 #include "date1.h" // Date class definition 12

291 Output to show timing of constructors.
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, const Date &dateOfBirth, const Date &dateOfHire ) : birthDate( dateOfBirth ), // initialize birthDate hireDate( dateOfHire ) // initialize hireDate 21 { // copy first into firstName and be sure that it fits int length = strlen( first ); length = ( length < 25 ? length : 24 ); strncpy( firstName, first, length ); firstName[ length ] = '\0'; 27 // copy last into lastName and be sure that it fits length = strlen( last ); length = ( length < 25 ? length : 24 ); strncpy( lastName, last, length ); lastName[ length ] = '\0'; 33 // output Employee object to show when constructor is called cout << "Employee object constructor: " << firstName << ' ' << lastName << endl; 37 employee1.cpp (2 of 3) Member initializer syntax to initialize Date data members birthDate and hireDate; compiler uses default copy constructor. Output to show timing of constructors.

292 Output to show timing of destructors.
38 } // end Employee constructor 39 40 // print Employee object 41 void Employee::print() const 42 { cout << lastName << ", " << firstName << "\nHired: "; hireDate.print(); cout << " Birth date: "; birthDate.print(); cout << endl; 48 49 } // end function print 50 51 // output Employee object to show when its destructor is called 52 Employee::~Employee() 53 { cout << "Employee object destructor: " << lastName << ", " << firstName << endl; 56 57 } // end destructor ~Employee employee1.cpp (3 of 3) Output to show timing of destructors.

293 Create Date objects to pass to Employee constructor.
// Fig. 7.10: fig07_10.cpp // Demonstrating composition--an object with member objects. #include <iostream> 4 using std::cout; using std::endl; 7 #include "employee1.h" // Employee class definition 9 10 int main() 11 { Date birth( 7, 24, 1949 ); Date hire( 3, 12, 1988 ); Employee manager( "Bob", "Jones", birth, hire ); 15 cout << '\n'; manager.print(); 18 cout << "\nTest Date constructor with invalid values:\n"; Date lastDayOff( 14, 35, 1994 ); // invalid month and day cout << endl; 22 return 0; 24 25 } // end main fig07_10.cpp (1 of 1) Create Date objects to pass to Employee constructor.

294 Destructor for Employee’s member object hireDate.
Date object constructor for date 7/24/1949 Date object constructor for date 3/12/1988 Employee object constructor: Bob Jones Jones, Bob Hired: 3/12/1988 Birth date: 7/24/1949 Test Date constructor with invalid values: Month 14 invalid. Set to month 1. Day 35 invalid. Set to day 1. Date object constructor for date 1/1/1994 Date object destructor for date 1/1/1994 Employee object destructor: Jones, Bob Date object destructor for date 3/12/1988 Date object destructor for date 7/24/1949 Note two additional Date objects constructed; no output since default copy constructor used. fig07_10.cpp output (1 of 1) Destructor for host object manager runs before destructors for member objects hireDate and birthDate. Destructor for Employee’s member object hireDate. Destructor for Employee‘s member object birthDate. Destructor for Date object hire. Destructor for Date object birth.

295 IS 0020 Program Design and Software Tools Introduction to C++ Programming
Lecture 4 - Classes Jan 27, 2004

296 friend Functions and friend Classes
Defined outside class’s scope Right to access non-public members Declaring friends Function Precede function prototype with keyword friend All member functions of class ClassTwo as friends of class ClassOne Place declaration of form friend class ClassTwo; in ClassOne definition

297 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 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

298 Precede function prototype with keyword friend.
// Fig. 7.11: fig07_11.cpp // Friends can access private members of a class. #include <iostream> 4 using std::cout; using std::endl; 7 // Count class definition class Count { friend void setX( Count &, int ); // friend declaration 11 12 public: 13 // constructor Count() : x( 0 ) // initialize x to 0 { // empty body 19 } // end Count constructor 21 fig07_11.cpp (1 of 3) Precede function prototype with keyword friend.

299 Pass Count object since C-style, standalone function.
// output x void print() const { cout << x << endl; 26 } // end function print 28 29 private: 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 { c.x = val; // legal: setX is a friend of Count 39 40 } // end function setX 41 fig07_11.cpp (2 of 3) Pass Count object since C-style, standalone function. Since setX friend of Count, can access and modify private data member x.

300 fig07_11.cpp (3 of 3) fig07_11.cpp output (1 of 1)
42 int main() 43 { Count counter; // create Count object 45 cout << "counter.x after instantiation: "; counter.print(); 48 setX( counter, 8 ); // set x with a friend 50 cout << "counter.x after call to setX friend function: "; counter.print(); 53 return 0; 55 56 } // end main fig07_11.cpp (3 of 3) fig07_11.cpp output (1 of 1) Use friend function to access and modify private data member x. counter.x after instantiation: 0 counter.x after call to setX friend function: 8

301 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

302 fig07_13.cpp (1 of 3) 1 // Fig. 7.13: fig07_13.cpp
// Using the this pointer to refer to object members. #include <iostream> 4 using std::cout; using std::endl; 7 class Test { 9 10 public: Test( int = 0 ); // default constructor void print() const; 13 14 private: int x; 16 17 }; // end class Test 18 19 // constructor 20 Test::Test( int value ) : x( value ) // initialize x to value 22 { // empty body 24 25 } // end Test constructor fig07_13.cpp (1 of 3)

303 Implicitly use this pointer; only specify name of data member (x).
26 27 // print x using implicit and explicit this pointers; 28 // parentheses around *this required 29 void Test::print() const 30 { // implicitly use this pointer to access member x cout << " x = " << x; 33 // explicitly use this pointer to access member x cout << "\n this->x = " << this->x; 36 // explicitly use dereferenced this pointer and // the dot operator to access member x cout << "\n(*this).x = " << ( *this ).x << endl; 40 41 } // end function print 42 43 int main() 44 { Test testObject( 12 ); 46 testObject.print(); 48 return 0; 50 Implicitly use this pointer; only specify name of data member (x). fig07_13.cpp (2 of 3) Explicitly use this pointer with arrow operator. Explicitly use this pointer; dereference this pointer first, then use dot operator.

304 fig07_13.cpp (3 of 3) fig07_13.cpp output (1 of 1)
51 } // end main x = 12 this->x = 12 (*this).x = 12 fig07_13.cpp (3 of 3) fig07_13.cpp output (1 of 1)

305 Cascaded member function calls
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

306 // Fig. 7.14: time6.h // Cascading member function calls. 3 // Time class definition. // Member functions defined in time6.cpp. #ifndef TIME6_H #define TIME6_H 8 class Time { 10 11 public: Time( int = 0, int = 0, int = 0 ); // default constructor 13 // set functions Time &setTime( int, int, int ); // set hour, minute, second Time &setHour( int ); // set hour Time &setMinute( int ); // set minute Time &setSecond( int ); // set second 19 // get functions (normally declared const) int getHour() const; // return hour int getMinute() const; // return minute int getSecond() const; // return second 24 time6.h (1 of 2) Set functions return reference to Time object to enable cascaded member function calls.

307 time6.h (2 of 2) 25 // print functions (normally declared const)
void printUniversal() const; // print universal time void printStandard() const; // print standard time 28 29 private: int hour; // (24-hour clock format) int minute; // int second; // 33 34 }; // end class Time 35 36 #endif time6.h (2 of 2)

308 time6.cpp (1 of 5) 1 // Fig. 7.15: time6.cpp
// Member-function definitions for Time class. #include <iostream> 4 using std::cout; 6 #include <iomanip> 8 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 { setTime( hr, min, sec ); 20 21 } // end Time constructor 22 time6.cpp (1 of 5)

309 Return *this as reference to enable cascaded member function calls.
23 // set values of hour, minute, and second 24 Time &Time::setTime( int h, int m, int s ) 25 { setHour( h ); setMinute( m ); setSecond( s ); 29 return *this; // enables cascading 31 32 } // end function setTime 33 34 // set hour value 35 Time &Time::setHour( int h ) 36 { hour = ( h >= 0 && h < 24 ) ? h : 0; 38 return *this; // enables cascading 40 41 } // end function setHour 42 time6.cpp (2 of 5) Return *this as reference to enable cascaded member function calls. Return *this as reference to enable cascaded member function calls.

310 Return *this as reference to enable cascaded member function calls.
43 // set minute value 44 Time &Time::setMinute( int m ) 45 { minute = ( m >= 0 && m < 60 ) ? m : 0; 47 return *this; // enables cascading 49 50 } // end function setMinute 51 52 // set second value 53 Time &Time::setSecond( int s ) 54 { second = ( s >= 0 && s < 60 ) ? s : 0; 56 return *this; // enables cascading 58 59 } // end function setSecond 60 61 // get hour value 62 int Time::getHour() const 63 { return hour; 65 66 } // end function getHour 67 Return *this as reference to enable cascaded member function calls. time6.cpp (3 of 5) Return *this as reference to enable cascaded member function calls.

311 time6.cpp (4 of 5) 68 // get minute value
69 int Time::getMinute() const 70 { return minute; 72 73 } // end function getMinute 74 75 // get second value 76 int Time::getSecond() const 77 { return second; 79 80 } // end function getSecond 81 82 // print Time in universal format 83 void Time::printUniversal() const 84 { cout << setfill( '0' ) << setw( 2 ) << hour << ":" << setw( 2 ) << minute << ":" << setw( 2 ) << second; 88 89 } // end function printUniversal 90 time6.cpp (4 of 5)

312 time6.cpp (5 of 5) 91 // print Time in standard format
92 void Time::printStandard() const 93 { cout << ( ( hour == 0 || hour == 12 ) ? 12 : hour % 12 ) << ":" << setfill( '0' ) << setw( 2 ) << minute << ":" << setw( 2 ) << second << ( hour < 12 ? " AM" : " PM" ); 98 99 } // end function printStandard time6.cpp (5 of 5)

313 // Fig. 7.16: fig07_16.cpp // Cascading member function calls with the this pointer. #include <iostream> 4 using std::cout; using std::endl; 7 #include "time6.h" // Time class definition 9 10 int main() 11 { Time t; 13 // cascaded function calls t.setHour( 18 ).setMinute( 30 ).setSecond( 22 ); 16 // output time in universal and standard formats cout << "Universal time: "; t.printUniversal(); 20 cout << "\nStandard time: "; t.printStandard(); 23 cout << "\n\nNew standard time: "; 25 fig07_16.cpp (1 of 2) Cascade member function calls; recall dot operator associates from left to right.

314 fig07_16.cpp (2 of 2) fig07_16.cpp output (1 of 1)
// cascaded function calls t.setTime( 20, 20, 20 ).printStandard(); 28 cout << endl; 30 return 0; 32 33 } // end main Function call to printStandard must appear last; printStandard does not return reference to t. fig07_16.cpp (2 of 2) fig07_16.cpp output (1 of 1) Universal time: 18:30:22 Standard time: 6:30:22 PM New standard time: 8:20:20 PM

315 Dynamic Memory Management with Operators new and delete
Control allocation and deallocation of memory Operators new and delete Include standard header <new> Access to standard version of new

316 Dynamic Memory Management with Operators new and delete
Consider Time *timePtr; timePtr = new Time; new operator 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( ); Time *timePtr = new Time( 12, 0, 0 ); Allocating arrays int *gradesArray = new int[ 10 ];

317 Dynamic Memory Management with Operators new and 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

318 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

319 Accessing static class variables
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 To call public static member function combine class name, binary scope resolution operator (::) and function name Employee::getCount()

320 static member functions
static Class Members 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

321 static data member is class-wide data.
// Fig. 7.17: employee2.h // Employee class definition. #ifndef EMPLOYEE2_H #define EMPLOYEE2_H 5 class Employee { 7 public: Employee( const char *, const char * ); // constructor ~Employee(); // destructor const char *getFirstName() const; // return first name const char *getLastName() const; // return last name 13 // static member function static int getCount(); // return # objects instantiated 16 17 private: char *firstName; char *lastName; 20 // static data member static int count; // number of objects instantiated 23 24 }; // end class Employee 25 employee2.h (1 of 2) static member function can only access static data members and member functions. static data member is class-wide data.

322 employee2.h (2 of 2) employee2.cpp (1 of 3)
26 #endif // Fig. 7.18: employee2.cpp // Member-function definitions for class Employee. #include <iostream> 4 using std::cout; using std::endl; 7 #include <new> // C++ standard new operator #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 { return count; 21 22 } // end static function getCount employee2.h (2 of 2) employee2.cpp (1 of 3) Initialize static data member exactly once at file scope. static member function accesses static data member count.

323 new operator dynamically allocates space.
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 { firstName = new char[ strlen( first ) + 1 ]; strcpy( firstName, first ); 31 lastName = new char[ strlen( last ) + 1 ]; strcpy( lastName, last ); 34 count; // increment static count of employees 36 cout << "Employee constructor for " << firstName << ' ' << lastName << " called." << endl; 39 40 } // end Employee constructor 41 42 // destructor deallocates dynamically allocated memory 43 Employee::~Employee() 44 { cout << "~Employee() called for " << firstName << ' ' << lastName << endl; 47 employee2.cpp (2 of 3) new operator dynamically allocates space. Use static data member to store total count of employees.

324 Operator delete deallocates memory. employee2.cpp (3 of 3)
delete [] firstName; // recapture memory delete [] lastName; // recapture memory 50 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 { // const before return type prevents client from modifying // private data; client should copy returned string before // destructor deletes storage to prevent undefined pointer return firstName; 62 63 } // end function getFirstName 64 65 // return last name of employee 66 const char *Employee::getLastName() const 67 { // const before return type prevents client from modifying // private data; client should copy returned string before // destructor deletes storage to prevent undefined pointer return lastName; 72 73 } // end function getLastName Operator delete deallocates memory. employee2.cpp (3 of 3) Use static data member to store total count of employees.

325 new operator dynamically allocates space.
// Fig. 7.19: fig07_19.cpp // Driver to test class Employee. #include <iostream> 4 using std::cout; using std::endl; 7 #include <new> // C++ standard new operator 9 10 #include "employee2.h" // Employee class definition 11 12 int main() 13 { cout << "Number of employees before instantiation is " << Employee::getCount() << endl; // use class name 16 Employee *e1Ptr = new Employee( "Susan", "Baker" ); Employee *e2Ptr = new Employee( "Robert", "Jones" ); 19 cout << "Number of employees after instantiation is " << e1Ptr->getCount(); 22 fig07_19.cpp (1 of 2) new operator dynamically allocates space. static member function can be invoked on any object of class.

326 Operator delete deallocates memory.
cout << "\n\nEmployee 1: " << e1Ptr->getFirstName() << " " << e1Ptr->getLastName() << "\nEmployee 2: " << e2Ptr->getFirstName() << " " << e2Ptr->getLastName() << "\n\n"; 29 delete e1Ptr; // recapture memory e1Ptr = 0; // disconnect pointer from free-store space delete e2Ptr; // recapture memory e2Ptr = 0; // disconnect pointer from free-store space 34 cout << "Number of employees after deletion is " << Employee::getCount() << endl; 37 return 0; 39 40 } // end main fig07_19.cpp (2 of 2) Operator delete deallocates memory. static member function invoked using binary scope resolution operator (no existing class objects).

327 Number of employees before instantiation is 0
Employee constructor for Susan Baker called. Employee constructor for Robert Jones called. Number of employees after instantiation is 2 Employee 1: Susan Baker Employee 2: Robert Jones ~Employee() called for Susan Baker ~Employee() called for Robert Jones Number of employees after deletion is 0 fig07_19.cpp output (1 of 1)

328 Data Abstraction and 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

329 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

330 Example: Array Abstract Data Type
ADT array Could include Subscript range checking Arbitrary range of subscripts Instead of having to start with 0 Array assignment Array comparison Array input/output Arrays that know their sizes Arrays that expand dynamically to accommodate more elements

331 Example: String Abstract Data Type
Strings in C++ C++ does not provide built-in string data type Maximizes performance Provides mechanisms for creating and implementing string abstract data type String ADT (Chapter 8) ANSI/ISO standard string class (Chapter 19)

332 Example: Queue Abstract Data Type
FIFO First in, first out Enqueue Put items in queue one at a time Dequeue Remove items from queue one at a time Queue ADT Implementation hidden from clients Clients may not manipulate data structure directly Only queue member functions can access internal data Queue ADT (Chapter 15) Standard library queue class (Chapter 20)

333 Container Classes and Iterators
Container classes (collection classes) Designed to hold collections of objects Common services Insertion, deletion, searching, sorting, or testing an item Examples Arrays, stacks, queues, trees and linked lists Iterator objects (iterators) Returns next item of collection Or performs some action on next item Can have several iterators per container Book with multiple bookmarks Each iterator maintains own “position” Discussed further in Chapter 20

334 Forward class declaration
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;

335 public member function.
// Fig. 7.20: implementation.h // Header file for class Implementation 3 class Implementation { 5 public: 7 // constructor Implementation( int v ) : value( v ) // initialize value with v { // empty body 13 } // end Implementation constructor 15 // set value to v void setValue( int v ) { value = v; // should validate v 20 } // end function setValue 22 implementation.h (1 of 2) public member function.

336 public member function. implementation.h (2 of 2)
// return value int getValue() const { return value; 27 } // end function getValue 29 30 private: int value; 32 33 }; // end class Implementation public member function. implementation.h (2 of 2)

337 Pointer to Implementation object requires forward class declaration.
// Fig. 7.21: interface.h // Header file for interface.cpp 3 class Implementation; // forward class declaration 5 class Interface { 7 public: Interface( int ); void setValue( int ); // same public interface as int getValue() const; // class Implementation ~Interface(); 13 14 private: 15 // requires previous forward declaration (line 4) Implementation *ptr; 18 19 }; // end class Interface interface.h (1 of 1) Pointer to Implementation object requires forward class declaration. Provide same public interface as class Implementation; recall setValue and getValue only public member functions.

338 Maintain pointer to underlying Implementation object.
// Fig. 7.22: interface.cpp // Definition of class Interface #include "interface.h" // Interface class definition #include "implementation.h" // Implementation class definition 5 // constructor Interface::Interface( int v ) : ptr ( new Implementation( v ) ) // initialize ptr { // empty body 11 12 } // end Interface constructor 13 14 // call Implementation's setValue function 15 void Interface::setValue( int v ) 16 { ptr->setValue( v ); 18 19 } // end function setValue 20 Maintain pointer to underlying Implementation object. interface.cpp (1 of 2) Proxy class Interface includes header file for class Implementation. Invoke corresponding function on underlying Implementation object.

339 Invoke corresponding function on underlying Implementation object.
21 // call Implementation's getValue function 22 int Interface::getValue() const 23 { return ptr->getValue(); 25 26 } // end function getValue 27 28 // destructor 29 Interface::~Interface() 30 { delete ptr; 32 33 } // end destructor ~Interface Invoke corresponding function on underlying Implementation object. interface.cpp (2 of 2) Deallocate underlying Implementation object.

340 fig07_23.cpp (1 of 1) fig07_23.cpp output (1 of 1)
// Fig. 7.23: fig07_23.cpp // Hiding a class’s private data with a proxy class. #include <iostream> 4 using std::cout; using std::endl; 7 #include "interface.h" // Interface class definition 9 10 int main() 11 { Interface i( 5 ); 13 cout << "Interface contains: " << i.getValue() << " before setValue" << endl; 16 i.setValue( 10 ); 18 cout << "Interface contains: " << i.getValue() << " after setValue" << endl; 21 return 0; 23 24 } // end main fig07_23.cpp (1 of 1) fig07_23.cpp output (1 of 1) 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. Interface contains: 5 before setValue Interface contains: 10 after setValue

341 Operator Overloading Lecture 6 Feb 10, 2004
IS Program Design and Software Tools Introduction to C++ Programming Operator Overloading Lecture 6 Feb 10, 2004

342 Use operators with objects (operator overloading)
Introduction Use operators with objects (operator overloading) Clearer than function calls for certain classes Operator sensitive to context Examples << Stream insertion, bitwise left-shift + Performs arithmetic on multiple types (integers, floats, etc.) when to use operator overloading?

343 Fundamentals of Operator Overloading
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 +

344 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 Overloading provides concise notation object2 = object1.add(object2); object2 = object2 + object1;

345 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 +=

346 Restrictions on Operator Overloading

347 Operator Functions As Class Members Vs. As Friend 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 Operator member function called when Left operand of binary operator of same class Single operand of unitary operator of same class

348 Operator Functions As Class Members Vs. As Friend Functions
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

349 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

350 Overloading Stream-Insertion and Stream-Extraction Operators
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)

351 cin << object cout >> object
// Fig. 8.3: fig08_03.cpp // Overloading the stream-insertion and // stream-extraction operators. #include <iostream> 5 using std::cout; using std::cin; using std::endl; using std::ostream; 10 using std::istream; 11 12 #include <iomanip> 13 14 using std::setw; 15 16 // PhoneNumber class definition 17 class PhoneNumber { friend ostream &operator<<( ostream&, const PhoneNumber & ); friend istream &operator>>( istream&, PhoneNumber & ); 20 21 private: char areaCode[ 4 ]; // 3-digit area code and null char exchange[ 4 ]; // 3-digit exchange and null char line[ 5 ]; // 4-digit line and null 25 26 }; // end class PhoneNumber fig08_03.cpp (1 of 3) 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

352 output is an alias for cout.
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 { output << "(" << num.areaCode << ") " << num.exchange << "-" << num.line; 35 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 { input.ignore(); // skip ( input >> setw( 4 ) >> num.areaCode; // input area code input.ignore( 2 ); // skip ) and space input >> setw( 4 ) >> num.exchange; // input exchange input.ignore(); // skip dash (-) input >> setw( 5 ) >> num.line; // input line 51 return input; // enables cin >> a >> b >> c; fig08_03.cpp (2 of 3) 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. ignore() skips specified number of characters from input (1 by default). Stream manipulator setw restricts number of characters read. setw(4) allows 3 characters to be read, leaving room for the null character.

353 fig08_03.cpp (3 of 3) fig08_03.cpp output (1 of 1)
53 54 } // end function operator>> 55 56 int main() 57 { PhoneNumber phone; // create object phone 59 cout << "Enter phone number in the form (123) :\n"; 61 // cin >> phone invokes operator>> by implicitly issuing // the non-member function call operator>>( cin, phone ) cin >> phone; 65 cout << "The phone number entered was: " ; 67 // cout << phone invokes operator<< by implicitly issuing // the non-member function call operator<<( cout, phone ) cout << phone << endl; 71 return 0; 73 74 } // end main fig08_03.cpp (3 of 3) fig08_03.cpp output (1 of 1) Enter phone number in the form (123) : (800) The phone number entered was: (800)

354 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

355 Overloading Unary Operators
Upcoming example (8.10) Overload ! to test for empty string If non-static member function, needs no arguments !s becomes s.operator!() class String { public: bool operator!() const; }; If non-member function, needs one argument s! becomes operator!(s) class String { friend bool operator!( const String & ) }

356 Overloading Binary Operators
Non-static member function, one argument Non-member function, two arguments One argument must be class object or reference Upcoming example If non-static member function, needs one argument class String { public: const String &operator+=( const String & ); ... }; y += z equivalent to y.operator+=( z )

357 Overloading Binary Operators
Upcoming example If non-member function, needs two arguments Example: class String { friend const String &operator+=( String &, const String & ); ... }; y += z equivalent to operator+=( y, z )

358 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 One element at a time 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 !=

359 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

360 Prototype for copy constructor.
// Fig. 8.4: array1.h // Array class for storing arrays of integers. #ifndef ARRAY1_H #define ARRAY1_H 5 #include <iostream> 7 using std::ostream; using std::istream; 10 11 class Array { friend ostream &operator<<( ostream &, const Array & ); friend istream &operator>>( istream &, Array & ); 14 15 public: Array( int = 10 ); // default constructor Array( const Array & ); // copy constructor ~Array(); // destructor int getSize() const; // return size 20 // assignment operator const Array &operator=( const Array & ); 23 // equality operator bool operator==( const Array & ) const; 26 array1.h (1 of 2) Most operators overloaded as member functions (except << and >>, which must be non-member functions). Prototype for copy constructor.

361 27 // inequality operator; returns opposite of == operator
bool operator!=( const Array &right ) const { return ! ( *this == right ); // invokes Array::operator== 31 } // end function operator!= 33 // subscript operator for non-const objects returns lvalue int &operator[]( int ); 36 // subscript operator for const objects returns rvalue const int &operator[]( int ) const; 39 40 private: int size; // array size int *ptr; // pointer to first element of array 43 44 }; // end class Array 45 46 #endif array1.h (2 of 2) != operator simply returns opposite of == operator. Thus, only need to define the == operator.

362 array1.cpp (1 of 7) 1 // Fig 8.5: array1.cpp
// Member function definitions for class Array #include <iostream> 4 using std::cout; using std::cin; using std::endl; 8 #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 { // validate arraySize size = ( arraySize > 0 ? arraySize : 10 ); 24 ptr = new int[ size ]; // create space for array 26 array1.cpp (1 of 7)

363 27 for ( int i = 0; i < size; i++ )
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 ) : size( arrayToCopy.size ) 36 { ptr = new int[ size ]; // create space for array 38 for ( int i = 0; i < size; i++ ) ptr[ i ] = arrayToCopy.ptr[ i ]; // copy into object 41 42 } // end Array copy constructor 43 44 // destructor for class Array 45 Array::~Array() 46 { delete [] ptr; // reclaim array space 48 49 } // end destructor 50 array1.cpp (2 of 7) We must declare a new integer array so the objects do not point to the same memory.

364 Want to avoid self-assignment.
51 // return size of array 52 int Array::getSize() const 53 { 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 { if ( &right != this ) { // check for self-assignment 63 // for arrays of different sizes, deallocate original // left-side array, then allocate new left-side array if ( size != right.size ) { delete [] ptr; // reclaim space size = right.size; // resize this object ptr = new int[ size ]; // create space for array copy 70 } // end inner if 72 for ( int i = 0; i < size; i++ ) ptr[ i ] = right.ptr[ i ]; // copy array into object 75 } // end outer if array1.cpp (3 of 7) Want to avoid self-assignment.

365 77 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 { if ( size != right.size ) return false; // arrays of different sizes 88 for ( int i = 0; i < size; i++ ) 90 if ( ptr[ i ] != right.ptr[ i ] ) return false; // arrays are not equal 93 return true; // arrays are equal 95 96 } // end function operator== 97 array1.cpp (4 of 7)

366 integers1[5] calls integers1.operator[]( 5 ) array1.cpp (5 of 7)
98 // overloaded subscript operator for non-const Arrays 99 // reference return creates an lvalue 100 int &Array::operator[]( int subscript ) 101 { // check for subscript out of range error if ( subscript < 0 || subscript >= size ) { cout << "\nError: Subscript " << subscript << " out of range" << endl; 106 exit( 1 ); // terminate program; subscript out of range 108 } // end if 110 return ptr[ subscript ]; // reference return 112 113 } // end function operator[] 114 integers1[5] calls integers1.operator[]( 5 ) array1.cpp (5 of 7) exit() (header <cstdlib>) ends the program.

367 115 // overloaded subscript operator for const Arrays
116 // const reference return creates an rvalue 117 const int &Array::operator[]( int subscript ) const 118 { // check for subscript out of range error if ( subscript < 0 || subscript >= size ) { cout << "\nError: Subscript " << subscript << " out of range" << endl; 123 exit( 1 ); // terminate program; subscript out of range 125 } // end if 127 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 { for ( int i = 0; i < a.size; i++ ) input >> a.ptr[ i ]; 138 return input; // enables cin >> x >> y; 140 141 } // end function array1.cpp (6 of 7)

368 142 143 // overloaded output operator for class Array 144 ostream &operator<<( ostream &output, const Array &a ) 145 { int i; 147 // output private ptr-based array for ( i = 0; i < a.size; i++ ) { output << setw( 12 ) << a.ptr[ i ]; 151 if ( ( i + 1 ) % 4 == 0 ) // 4 numbers per row of output output << endl; 154 } // end for 156 if ( i % 4 != 0 ) // end last line of output output << endl; 159 return output; // enables cout << x << y; 161 162 } // end function operator<< array1.cpp (7 of 7)

369 fig08_06.cpp (1 of 3) 1 // Fig. 8.6: fig08_06.cpp
// Array class test program. #include <iostream> 4 using std::cout; using std::cin; using std::endl; 8 #include "array1.h" 10 11 int main() 12 { Array integers1( 7 ); // seven-element Array Array integers2; // 10-element Array by default 15 // print integers1 size and contents cout << "Size of array integers1 is " << integers1.getSize() << "\nArray after initialization:\n" << integers1; 20 // print integers2 size and contents cout << "\nSize of array integers2 is " << integers2.getSize() << "\nArray after initialization:\n" << integers2; 25 fig08_06.cpp (1 of 3)

370 fig08_06.cpp (2 of 3) 26 // input and print integers1 and integers2
cout << "\nInput 17 integers:\n"; cin >> integers1 >> integers2; 29 cout << "\nAfter input, the arrays contain:\n" << "integers1:\n" << integers1 << "integers2:\n" << integers2; 33 // use overloaded inequality (!=) operator cout << "\nEvaluating: integers1 != integers2\n"; 36 if ( integers1 != integers2 ) cout << "integers1 and integers2 are not equal\n"; 39 // create array integers3 using integers1 as an // initializer; print size and contents Array integers3( integers1 ); // calls copy constructor 43 cout << "\nSize of array integers3 is " << integers3.getSize() << "\nArray after initialization:\n" << integers3; 47 fig08_06.cpp (2 of 3)

371 fig08_06.cpp (3 of 3) 48 // use overloaded assignment (=) operator
cout << "\nAssigning integers2 to integers1:\n"; integers1 = integers2; // note target is smaller 51 cout << "integers1:\n" << integers1 << "integers2:\n" << integers2; 54 // use overloaded equality (==) operator cout << "\nEvaluating: integers1 == integers2\n"; 57 if ( integers1 == integers2 ) cout << "integers1 and integers2 are equal\n"; 60 // use overloaded subscript operator to create rvalue cout << "\nintegers1[5] is " << integers1[ 5 ]; 63 // use overloaded subscript operator to create lvalue cout << "\n\nAssigning 1000 to integers1[5]\n"; integers1[ 5 ] = 1000; cout << "integers1:\n" << integers1; 68 // attempt to use out-of-range subscript cout << "\nAttempt to assign 1000 to integers1[15]" << endl; integers1[ 15 ] = 1000; // ERROR: out of range 72 return 0; 74 75 } // end main fig08_06.cpp (3 of 3)

372 fig08_06.cpp output (1 of 3) Size of array integers1 is 7
Size of array integers1 is 7 Array after initialization: Size of array integers2 is 10 Input 17 integers: After input, the arrays contain: integers1: integers2: fig08_06.cpp output (1 of 3)

373 fig08_06.cpp output (2 of 3) Evaluating: integers1 != integers2
integers1 and integers2 are not equal Size of array integers3 is 7 Array after initialization: Assigning integers2 to integers1: integers1: integers2: Evaluating: integers1 == integers2 integers1 and integers2 are equal integers1[5] is 13 fig08_06.cpp output (2 of 3)

374 fig08_06.cpp output (3 of 3) Assigning 1000 to integers1[5] integers1:
Attempt to assign 1000 to integers1[15] Error: Subscript 15 out of range fig08_06.cpp output (3 of 3)

375 Converting between Types
Casting Traditionally, cast integers to floats, etc. May need to convert between user-defined types Cast operator (conversion operator) Convert from One class to another Class to built-in type (int, char, etc.) Must be non-static member function Cannot be friend Do not specify return type Implicitly returns type to which you are converting

376 Converting between Types
Example Prototype A::operator char *() const; Casts class A to a temporary char * (char *)s calls s.operator char*() Also A::operator int() const; A::operator OtherClass() const;

377 Converting between Types
Casting can prevent need for overloading Suppose class String can be cast to char * cout << s; // s is a String Compiler implicitly converts s to char * Do not have to overload << Compiler can only do 1 cast

378 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

379 Conversion constructor to make a String from a char *.
// Fig. 8.7: string1.h // String class definition. #ifndef STRING1_H #define STRING1_H 5 #include <iostream> 7 using std::ostream; using std::istream; 10 11 class String { friend ostream &operator<<( ostream &, const String & ); friend istream &operator>>( istream &, String & ); 14 15 public: String( const char * = "" ); // conversion/default ctor String( const String & ); // copy constructor ~String(); // destructor 19 const String &operator=( const String & ); // assignment const String &operator+=( const String & ); // concatenation 22 bool operator!() const; // is String empty? bool operator==( const String & ) const; // test s1 == s2 bool operator<( const String & ) const; // test s1 < s2 26 string1.h (1 of 3) Conversion constructor to make a String from a char *. s1 += s2 interpreted as s1.operator+=(s2) Can also concatenate a String and a char * because the compiler will cast the char * argument to a String. However, it can only do 1 level of casting.

380 string1.h (2 of 3) 27 // test s1 != s2
bool operator!=( const String & right ) const { return !( *this == right ); 31 } // end function operator!= 33 // test s1 > s2 bool operator>( const String &right ) const { return right < *this; 38 } // end function operator> 40 // test s1 <= s2 bool operator<=( const String &right ) const { return !( right < *this ); 45 } // end function operator <= 47 // test s1 >= s2 bool operator>=( const String &right ) const { return !( *this < right ); 52 } // end function operator>= string1.h (2 of 3)

381 Two overloaded subscript operators, for const and non-const objects.
54 char &operator[]( int ); // subscript operator const char &operator[]( int ) const; // subscript operator 57 String operator()( int, int ); // return a substring 59 int getLength() const; // return string length 61 62 private: int length; // string length char *sPtr; // pointer to start of string 65 void setString( const char * ); // utility function 67 68 }; // end class String 69 70 #endif Two overloaded subscript operators, for const and non-const objects. string1.h (3 of 3) Overload the function call operator () to return a substring. This operator can have any amount of operands.

382 string1.cpp (1 of 8) 1 // Fig. 8.8: string1.cpp
// Member function definitions for class String. #include <iostream> 4 using std::cout; using std::endl; 7 #include <iomanip> 9 10 using std::setw; 11 12 #include <new> // C++ standard "new" operator 13 14 #include <cstring> // strcpy and strcat prototypes 15 #include <cstdlib> // exit prototype 16 17 #include "string1.h" // String class definition 18 19 // conversion constructor converts char * to String 20 String::String( const char *s ) : length( strlen( s ) ) 22 { cout << "Conversion constructor: " << s << '\n'; setString( s ); // call utility function 25 26 } // end String conversion constructor string1.cpp (1 of 8)

383 string1.cpp (2 of 8) 27 28 // copy constructor
29 String::String( const String &copy ) : length( copy.length ) 31 { cout << "Copy constructor: " << copy.sPtr << '\n'; setString( copy.sPtr ); // call utility function 34 35 } // end String copy constructor 36 37 // destructor 38 String::~String() 39 { cout << "Destructor: " << sPtr << '\n'; delete [] sPtr; // reclaim string 42 43 } // end ~String destructor 44 45 // overloaded = operator; avoids self assignment 46 const String &String::operator=( const String &right ) 47 { cout << "operator= called\n"; 49 if ( &right != this ) { // avoid self assignment delete [] sPtr; // prevents memory leak length = right.length; // new String length setString( right.sPtr ); // call utility function } string1.cpp (2 of 8)

384 55 else cout << "Attempted assignment of a String to itself\n"; 58 return *this; // enables cascaded assignments 60 61 } // end function operator= 62 63 // concatenate right operand to this object and 64 // store in this object. 65 const String &String::operator+=( const String &right ) 66 { size_t newLength = length + right.length; // new length char *tempPtr = new char[ newLength + 1 ]; // create memory 69 strcpy( tempPtr, sPtr ); // copy sPtr strcpy( tempPtr + length, right.sPtr ); // copy right.sPtr 72 delete [] sPtr; // reclaim old space sPtr = tempPtr; // assign new array to sPtr length = newLength; // assign new length to length 76 return *this; // enables cascaded calls 78 79 } // end function operator+= 80 string1.cpp (3 of 8)

385 string1.cpp (4 of 8) 81 // is this String empty?
82 bool String::operator!() const 83 { return length == 0; 85 86 } // end function operator! 87 88 // is this String equal to right String? 89 bool String::operator==( const String &right ) const 90 { return strcmp( sPtr, right.sPtr ) == 0; 92 93 } // end function operator== 94 95 // is this String less than right String? 96 bool String::operator<( const String &right ) const 97 { return strcmp( sPtr, right.sPtr ) < 0; 99 100 } // end function operator< 101 string1.cpp (4 of 8)

386 102 // return reference to character in String as lvalue
103 char &String::operator[]( int subscript ) 104 { // test for subscript out of range if ( subscript < 0 || subscript >= length ) { cout << "Error: Subscript " << subscript << " out of range" << endl; 109 exit( 1 ); // terminate program } 112 return sPtr[ subscript ]; // creates lvalue 114 115 } // end function operator[] 116 117 // return reference to character in String as rvalue 118 const char &String::operator[]( int subscript ) const 119 { // test for subscript out of range if ( subscript < 0 || subscript >= length ) { cout << "Error: Subscript " << subscript << " out of range" << endl; 124 exit( 1 ); // terminate program } 127 return sPtr[ subscript ]; // creates rvalue 129 130 } // end function operator[] string1.cpp (5 of 8)

387 131 132 // return a substring beginning at index and 133 // of length subLength 134 String String::operator()( int index, int subLength ) 135 { // if index is out of range or substring length < 0, // return an empty String object if ( index < 0 || index >= length || subLength < 0 ) return ""; // converted to a String object automatically 140 // determine length of substring int len; 143 if ( ( subLength == 0 ) || ( index + subLength > length ) ) len = length - index; else len = subLength; 148 // allocate temporary array for substring and // terminating null character char *tempPtr = new char[ len + 1 ]; 152 // copy substring into char array and terminate string strncpy( tempPtr, &sPtr[ index ], len ); tempPtr[ len ] = '\0'; string1.cpp (6 of 8)

388 156 // create temporary String object containing the substring String tempString( tempPtr ); delete [] tempPtr; // delete temporary array 160 return tempString; // return copy of the temporary String 162 163 } // end function operator() 164 165 // return string length 166 int String::getLength() const 167 { return length; 169 170 } // end function getLenth 171 172 // utility function called by constructors and operator= 173 void String::setString( const char *string2 ) 174 { sPtr = new char[ length + 1 ]; // allocate memory strcpy( sPtr, string2 ); // copy literal to object 177 178 } // end function setString string1.cpp (7 of 8)

389 string1.cpp (8 of 8) 179 180 // overloaded output operator
181 ostream &operator<<( ostream &output, const String &s ) 182 { output << s.sPtr; 184 return output; // enables cascading 186 187 } // end function operator<< 188 189 // overloaded input operator 190 istream &operator>>( istream &input, String &s ) 191 { char temp[ 100 ]; // buffer to store input 193 input >> setw( 100 ) >> temp; s = temp; // use String class assignment operator 196 return input; // enables cascading 198 199 } // end function operator>> string1.cpp (8 of 8)

390 fig08_09.cpp (1 of 4) 1 // Fig. 8.9: fig08_09.cpp
// String class test program. #include <iostream> 4 using std::cout; using std::endl; 7 #include "string1.h" 9 10 int main() 11 { String s1( "happy" ); String s2( " birthday" ); String s3; 15 // test overloaded equality and relational operators cout << "s1 is \"" << s1 << "\"; s2 is \"" << s2 << "\"; s3 is \"" << s3 << '\"' << "\n\nThe results of comparing s2 and s1:" << "\ns2 == s1 yields " << ( s2 == s1 ? "true" : "false" ) << "\ns2 != s1 yields " << ( s2 != s1 ? "true" : "false" ) << "\ns2 > s1 yields " << ( s2 > s1 ? "true" : "false" ) fig08_09.cpp (1 of 4)

391 fig08_09.cpp (2 of 4) 26 << "\ns2 < s1 yields "
<< ( s2 < s1 ? "true" : "false" ) << "\ns2 >= s1 yields " << ( s2 >= s1 ? "true" : "false" ) << "\ns2 <= s1 yields " << ( s2 <= s1 ? "true" : "false" ); 32 // test overloaded String empty (!) operator cout << "\n\nTesting !s3:\n"; 35 if ( !s3 ) { cout << "s3 is empty; assigning s1 to s3;\n"; s3 = s1; // test overloaded assignment cout << "s3 is \"" << s3 << "\""; } 41 // test overloaded String concatenation operator cout << "\n\ns1 += s2 yields s1 = "; s1 += s2; // test overloaded concatenation cout << s1; 46 // test conversion constructor cout << "\n\ns1 += \" to you\" yields\n"; s1 += " to you"; // test conversion constructor cout << "s1 = " << s1 << "\n\n"; fig08_09.cpp (2 of 4)

392 51 // test overloaded function call operator () for substring cout << "The substring of s1 starting at\n" << "location 0 for 14 characters, s1(0, 14), is:\n" << s1( 0, 14 ) << "\n\n"; 56 // test substring "to-end-of-String" option cout << "The substring of s1 starting at\n" << "location 15, s1(15, 0), is: " << s1( 15, 0 ) << "\n\n"; // 0 is "to end of string" 61 // test copy constructor String *s4Ptr = new String( s1 ); cout << "\n*s4Ptr = " << *s4Ptr << "\n\n"; 65 // test assignment (=) operator with self-assignment cout << "assigning *s4Ptr to *s4Ptr\n"; *s4Ptr = *s4Ptr; // test overloaded assignment cout << "*s4Ptr = " << *s4Ptr << '\n'; 70 // test destructor delete s4Ptr; 73 fig08_09.cpp (3 of 4)

393 74 // test using subscript operator to create lvalue
s1[ 0 ] = 'H'; s1[ 6 ] = 'B'; cout << "\ns1 after s1[0] = 'H' and s1[6] = 'B' is: " << s1 << "\n\n"; 79 // test subscript out of range cout << "Attempt to assign 'd' to s1[30] yields:" << endl; s1[ 30 ] = 'd'; // ERROR: subscript out of range 83 return 0; 85 86 } // end main fig08_09.cpp (4 of 4)

394 Conversion constructor: happy
Conversion constructor: birthday Conversion constructor: s1 is "happy"; s2 is " birthday"; s3 is "" The results of comparing s2 and s1: s2 == s1 yields false s2 != s1 yields true s2 > s1 yields false s2 < s1 yields true s2 >= s1 yields false s2 <= s1 yields true Testing !s3: s3 is empty; assigning s1 to s3; operator= called s3 is "happy" s1 += s2 yields s1 = happy birthday s1 += " to you" yields Conversion constructor: to you Destructor: to you s1 = happy birthday to you fig08_09.cpp (1 of 3) The constructor and destructor are called for the temporary String (converted from the char * “to you”).

395 fig08_09.cpp (2 of 3) Conversion constructor: happy birthday
Copy constructor: happy birthday Destructor: happy birthday The substring of s1 starting at location 0 for 14 characters, s1(0, 14), is: happy birthday Conversion constructor: to you Copy constructor: to you Destructor: to you location 15, s1(15, 0), is: to you Copy constructor: happy birthday to you *s4Ptr = happy birthday to you assigning *s4Ptr to *s4Ptr operator= called Attempted assignment of a String to itself Destructor: happy birthday to you fig08_09.cpp (2 of 3)

396 s1 after s1[0] = 'H' and s1[6] = 'B' is: Happy Birthday to you
Attempt to assign 'd' to s1[30] yields: Error: Subscript 30 out of range fig08_09.cpp (3 of 3)

397 Increment/decrement operators can be overloaded
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 )

398 To distinguish pre/post increment
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

399 Decrement operator analogous
8.11 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) Decrement operator analogous

400 Case Study: A Date Class
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

401 Note difference between pre and post increment.
// Fig. 8.10: date1.h // Date class definition. #ifndef DATE1_H #define DATE1_H #include <iostream> 6 using std::ostream; 8 class Date { friend ostream &operator<<( ostream &, const Date & ); 11 12 public: Date( int m = 1, int d = 1, int y = 1900 ); // constructor void setDate( int, int, int ); // set the date 15 Date &operator++(); // preincrement operator Date operator++( int ); // postincrement operator 18 const Date &operator+=( int ); // add days, modify object 20 bool leapYear( int ) const; // is this a leap year? bool endOfMonth( int ) const; // is this end of month? date1.h (1 of 2) Note difference between pre and post increment.

402 date1.h (2 of 2) 23 24 private: 25 int month; 26 int day; 27 int year;
28 static const int days[]; // array of days per month void helpIncrement(); // utility function 31 32 }; // end class Date 33 34 #endif date1.h (2 of 2)

403 date1.cpp (1 of 5) 1 // Fig. 8.11: date1.cpp
// Date class member function definitions. #include <iostream> #include "date1.h" 5 // initialize static member at file scope; // one class-wide copy const int Date::days[] = { 0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }; 10 11 // Date constructor 12 Date::Date( int m, int d, int y ) 13 { setDate( m, d, y ); 15 16 } // end Date constructor 17 18 // set month, day and year 19 void Date::setDate( int mm, int dd, int yy ) 20 { month = ( mm >= 1 && mm <= 12 ) ? mm : 1; year = ( yy >= 1900 && yy <= 2100 ) ? yy : 1900; 23 date1.cpp (1 of 5)

404 Also note that the integer parameter does not have a name.
// test for a leap year if ( month == 2 && leapYear( year ) ) day = ( dd >= 1 && dd <= 29 ) ? dd : 1; else day = ( dd >= 1 && dd <= days[ month ] ) ? dd : 1; 29 30 } // end function setDate 31 32 // overloaded preincrement operator 33 Date &Date::operator++() 34 { helpIncrement(); 36 return *this; // reference return to create an lvalue 38 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 { Date temp = *this; // hold current state of object helpIncrement(); 47 // return unincremented, saved, temporary object return temp; // value return; not a reference return 50 51 } // end function operator++ date1.cpp (2 of 5) Postincrement updates object and returns a copy of the original. Do not return a reference to temp, because it is a local variable that will be destroyed. Also note that the integer parameter does not have a name.

405 date1.cpp (3 of 5) 52 53 // add specified number of days to date
54 const Date &Date::operator+=( int additionalDays ) 55 { for ( int i = 0; i < additionalDays; i++ ) helpIncrement(); 58 return *this; // enables cascading 60 61 } // end function operator+= 62 63 // if the year is a leap year, return true; 64 // otherwise, return false 65 bool Date::leapYear( int testYear ) const 66 { if ( testYear % 400 == 0 || ( testYear % 100 != 0 && testYear % 4 == 0 ) ) return true; // a leap year else return false; // not a leap year 72 73 } // end function leapYear 74 date1.cpp (3 of 5)

406 75 // determine whether the day is the last day of the month
76 bool Date::endOfMonth( int testDay ) const 77 { if ( month == 2 && leapYear( year ) ) return testDay == 29; // last day of Feb. in leap year else return testDay == days[ month ]; 82 83 } // end function endOfMonth 84 85 // function to help increment the date 86 void Date::helpIncrement() 87 { // day is not end of month if ( !endOfMonth( day ) ) day; 91 else 93 // day is end of month and month < 12 if ( month < 12 ) { month; day = 1; } 99 date1.cpp (4 of 5)

407 date1.cpp (5 of 5) 100 // last day of year 101 else { 102 ++year;
month = 1; day = 1; } 106 107 } // end function helpIncrement 108 109 // overloaded output operator 110 ostream &operator<<( ostream &output, const Date &d ) 111 { static char *monthName[ 13 ] = { "", "January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December" }; 116 output << monthName[ d.month ] << ' ' << d.day << ", " << d.year; 119 return output; // enables cascading 121 122 } // end function operator<< date1.cpp (5 of 5)

408 fig08_12.cpp (1 of 2) 1 // Fig. 8.12: fig08_12.cpp
// Date class test program. #include <iostream> 4 using std::cout; using std::endl; 7 #include "date1.h" // Date class definition 9 10 int main() 11 { Date d1; // defaults to January 1, 1900 Date d2( 12, 27, 1992 ); Date d3( 0, 99, 8045 ); // invalid date 15 cout << "d1 is " << d1 << "\nd2 is " << d2 << "\nd3 is " << d3; 18 cout << "\n\nd2 += 7 is " << ( d2 += 7 ); 20 d3.setDate( 2, 28, 1992 ); cout << "\n\n d3 is " << d3; cout << "\n++d3 is " << ++d3; 24 Date d4( 7, 13, 2002 ); fig08_12.cpp (1 of 2)

409 26 cout << "\n\nTesting the preincrement operator:\n" << " d4 is " << d4 << '\n'; cout << "++d4 is " << ++d4 << '\n'; cout << " d4 is " << d4; 31 cout << "\n\nTesting the postincrement operator:\n" << " d4 is " << d4 << '\n'; cout << "d4++ is " << d4++ << '\n'; cout << " d4 is " << d4 << endl; 36 return 0; 38 39 } // end main fig08_12.cpp (2 of 2)

410 fig08_12.cpp output (1 of 1) d1 is January 1, 1900
d2 is December 27, 1992 d3 is January 1, 1900 d2 += 7 is January 3, 1993 d3 is February 28, 1992 ++d3 is February 29, 1992 Testing the preincrement operator: d4 is July 13, 2002 ++d4 is July 14, 2002 d4 is July 14, 2002 Testing the postincrement operator: d4++ is July 14, 2002 d4 is July 15, 2002 fig08_12.cpp output (1 of 1)

411 Standard Library Classes string and vector
Classes built into C++ Available for anyone to use string Similar to our String class vector Dynamically resizable array Redo our String and Array examples Use string and vector

412 8.13 Standard Library Classes string and vector
Class string Header <string>, namespace std Can initialize string s1(“hi”); Overloaded << cout << s1 Overloaded relational operators == != >= > <= < Assignment operator = Concatenation (overloaded +=)

413 Standard Library Classes string and vector
Class string Substring function substr s1.substr(0, 14); Starts at location 0, gets 14 characters S1.substr(15) Substring beginning at location 15 Overloaded [] Access one character No range checking (if subscript invalid) at function s1.at(10) Character at subscript 10 Has bounds checking Will end program if invalid (learn more in Chapter 13)

414 fig08_13.cpp (1 of 4) 1 // Fig. 8.13: fig08_13.cpp
// Standard library string class test program. #include <iostream> 4 using std::cout; using std::endl; 7 #include <string> 9 10 using std::string; 11 12 int main() 13 { string s1( "happy" ); string s2( " birthday" ); string s3; 17 // test overloaded equality and relational operators cout << "s1 is \"" << s1 << "\"; s2 is \"" << s2 << "\"; s3 is \"" << s3 << '\"' << "\n\nThe results of comparing s2 and s1:" << "\ns2 == s1 yields " << ( s2 == s1 ? "true" : "false" ) << "\ns2 != s1 yields " << ( s2 != s1 ? "true" : "false" ) fig08_13.cpp (1 of 4)

415 fig08_13.cpp (2 of 4) 26 << "\ns2 > s1 yields "
<< ( s2 > s1 ? "true" : "false" ) << "\ns2 < s1 yields " << ( s2 < s1 ? "true" : "false" ) << "\ns2 >= s1 yields " << ( s2 >= s1 ? "true" : "false" ) << "\ns2 <= s1 yields " << ( s2 <= s1 ? "true" : "false" ); 34 // test string member function empty cout << "\n\nTesting s3.empty():\n"; 37 if ( s3.empty() ) { cout << "s3 is empty; assigning s1 to s3;\n"; s3 = s1; // assign s1 to s3 cout << "s3 is \"" << s3 << "\""; } 43 // test overloaded string concatenation operator cout << "\n\ns1 += s2 yields s1 = "; s1 += s2; // test overloaded concatenation cout << s1; 48 fig08_13.cpp (2 of 4)

416 49 // test overloaded string concatenation operator
// with C-style string cout << "\n\ns1 += \" to you\" yields\n"; s1 += " to you"; cout << "s1 = " << s1 << "\n\n"; 54 // test string member function substr cout << "The substring of s1 starting at location 0 for\n" << "14 characters, s1.substr(0, 14), is:\n" << s1.substr( 0, 14 ) << "\n\n"; 59 // test substr "to-end-of-string" option cout << "The substring of s1 starting at\n" << "location 15, s1.substr(15), is:\n" << s1.substr( 15 ) << '\n'; 64 // test copy constructor string *s4Ptr = new string( s1 ); cout << "\n*s4Ptr = " << *s4Ptr << "\n\n"; 68 // test assignment (=) operator with self-assignment cout << "assigning *s4Ptr to *s4Ptr\n"; *s4Ptr = *s4Ptr; cout << "*s4Ptr = " << *s4Ptr << '\n'; 73 fig08_13.cpp (3 of 4)

417 fig08_13.cpp (4 of 4) 74 // test destructor 75 delete s4Ptr; 76
// test using subscript operator to create lvalue s1[ 0 ] = 'H'; s1[ 6 ] = 'B'; cout << "\ns1 after s1[0] = 'H' and s1[6] = 'B' is: " << s1 << "\n\n"; 82 // test subscript out of range with string member function "at" cout << "Attempt to assign 'd' to s1.at( 30 ) yields:" << endl; s1.at( 30 ) = 'd'; // ERROR: subscript out of range 86 return 0; 88 89 } // end main fig08_13.cpp (4 of 4)

418 Standard Library Classes string and vector
Class vector Header <vector>, namespace std Store any type vector< int > myArray(10) Function size ( myArray.size() ) Overloaded [] Get specific element, myArray[3] Overloaded !=, ==, and = Inequality, equality, assignment

419 fig08_14.cpp (1 of 5) 1 // Fig. 8.14: fig08_14.cpp
// Demonstrating standard library class vector. #include <iostream> 4 using std::cout; using std::cin; using std::endl; 8 #include <iomanip> 10 11 using std::setw; 12 13 #include <vector> 14 15 using std::vector; 16 17 void outputVector( const vector< int > & ); 18 void inputVector( vector< int > & ); 19 20 int main() 21 { vector< int > integers1( 7 ); // 7-element vector< int > vector< int > integers2( 10 ); // 10-element vector< int > 24 fig08_14.cpp (1 of 5)

420 fig08_14.cpp (2 of 5) 25 // print integers1 size and contents
cout << "Size of vector integers1 is " << integers1.size() << "\nvector after initialization:\n"; outputVector( integers1 ); 30 // print integers2 size and contents cout << "\nSize of vector integers2 is " << integers2.size() << "\nvector after initialization:\n"; outputVector( integers2 ); 36 // input and print integers1 and integers2 cout << "\nInput 17 integers:\n"; inputVector( integers1 ); inputVector( integers2 ); 41 cout << "\nAfter input, the vectors contain:\n" << "integers1:\n"; outputVector( integers1 ); cout << "integers2:\n"; outputVector( integers2 ); 47 // use overloaded inequality (!=) operator cout << "\nEvaluating: integers1 != integers2\n"; 50 fig08_14.cpp (2 of 5)

421 fig08_14.cpp (3 of 5) 51 if ( integers1 != integers2 )
cout << "integers1 and integers2 are not equal\n"; 53 // create vector integers3 using integers1 as an // initializer; print size and contents vector< int > integers3( integers1 ); // copy constructor 57 cout << "\nSize of vector integers3 is " << integers3.size() << "\nvector after initialization:\n"; outputVector( integers3 ); 62 63 // use overloaded assignment (=) operator cout << "\nAssigning integers2 to integers1:\n"; integers1 = integers2; 67 cout << "integers1:\n"; outputVector( integers1 ); cout << "integers2:\n"; outputVector( integers1 ); 72 fig08_14.cpp (3 of 5)

422 fig08_14.cpp (4 of 5) 73 // use overloaded equality (==) operator
cout << "\nEvaluating: integers1 == integers2\n"; 75 if ( integers1 == integers2 ) cout << "integers1 and integers2 are equal\n"; 78 // use overloaded subscript operator to create rvalue cout << "\nintegers1[5] is " << integers1[ 5 ]; 81 // use overloaded subscript operator to create lvalue cout << "\n\nAssigning 1000 to integers1[5]\n"; integers1[ 5 ] = 1000; cout << "integers1:\n"; outputVector( integers1 ); 87 // attempt to use out of range subscript cout << "\nAttempt to assign 1000 to integers1.at( 15 )" << endl; integers1.at( 15 ) = 1000; // ERROR: out of range 92 return 0; 94 95 } // end main 96 fig08_14.cpp (4 of 5)

423 fig08_14.cpp (5 of 5) 97 // output vector contents
98 void outputVector( const vector< int > &array ) 99 { for ( int i = 0; i < array.size(); i++ ) { cout << setw( 12 ) << array[ i ]; 102 if ( ( i + 1 ) % 4 == 0 ) // 4 numbers per row of output cout << endl; 105 } // end for 107 if ( i % 4 != 0 ) cout << endl; 110 111 } // end function outputVector 112 113 // input vector contents 114 void inputVector( vector< int > &array ) 115 { for ( int i = 0; i < array.size(); i++ ) cin >> array[ i ]; 118 119 } // end function inputVector fig08_14.cpp (5 of 5)

424 fig08_14.cpp output (1 of 2) Size of vector integers1 is 7
vector after initialization: Size of vector integers2 is 10 Input 17 integers: After input, the vectors contain: integers1: integers2: Evaluating: integers1 != integers2 integers1 and integers2 are not equal fig08_14.cpp output (1 of 2)

425 fig08_14.cpp output (2 of 2) Size of vector integers3 is 7
vector after initialization: Assigning integers2 to integers1: integers1: integers2: Evaluating: integers1 == integers2 integers1 and integers2 are equal integers1[5] is 13 Assigning 1000 to integers1[5] Attempt to assign 1000 to integers1.at( 15 ) abnormal program termination fig08_14.cpp output (2 of 2)

426 IS 0020 Program Design and Software Tools
Preprocessor Midterm Review Lecture 7 Feb 17, 2004

427 Introduction Preprocessing Occurs before program compiled
Inclusion of external files Definition of symbolic constants Macros Conditional compilation Conditional execution All directives begin with # Can only have whitespace before directives Directives not C++ statements Do not end with ;

428 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

429 The #include Preprocessor Directive
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

430 The #define Preprocessor Directive: Symbolic Constants
Constants represented as symbols When program compiled, all occurrences replaced Format #define identifier replacement-text #define PI Everything to right of identifier replaces text #define PI= Replaces PI with "= " Probably an error Cannot redefine symbolic constants

431 The #define Preprocessor Directive: Symbolic Constants
Advantages Takes no memory Disadvantages Name not be seen by debugger (only replacement text) Do not have specific data type const variables preferred

432 The #define Preprocessor Directive: Macros
Operation specified in #define Intended for legacy C programs 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

433 The #define Preprocessor Directive: Macros
Example #define CIRCLE_AREA( x ) ( PI * ( x ) * ( x ) ) area = CIRCLE_AREA( 4 ); becomes area = ( * ( 4 ) * ( 4 ) ); Use parentheses Without them, #define CIRCLE_AREA( x ) PI * x * x area = CIRCLE_AREA( c + 2 ); area = * c + 2 * c + 2; which evaluates incorrectly

434 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

435 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

436 Conditional Compilation
Can use else #else #elif is "else if" Abbreviations #ifdef short for #if defined(name) #ifndef short for #if !defined(name)

437 Conditional Compilation
"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

438 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

439 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

440 The # and ## Operators # operator ## 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

441 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

442 Predefined Symbolic Constants
Five predefined symbolic constants Cannot be used in #define or #undef

443 To remove assert statements
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

444 IS 0020 Program Design and Software Tools
Overview for Midterm

445 Background; phases of compilation Arithmetic operations
Lecture 1 Background; phases of compilation Arithmetic operations Control structure Sequential Conditional repetition Misc: Lvalues/Rvalues; logical operators; = ; = = Structured programming concept

446 Lecture 2 Functions Storage classes Scope rules Recursive functions References and parameters Arrays Pointers Function pointers

447 Structures and Classes Constructor and destructor Class scope
Lecture 3 Structures and Classes Constructor and destructor Order of calls Class scope Returning reference to private data member (bad!) Object assignment (memberwise) const objects/functions Composition

448 Dynamic memory management: new and delete static class member
Lecture 4 Friend Functions this pointed Cascaded sequence Dynamic memory management: new and delete static class member Data abstraction and information hiding Proxy classes etc.

449 Overloading binary operators Overloading ++ and --
Lecture 6 (5) , 7 Operator overloading Class members Overloading binary operators Case studies: Array, string Overloading ++ and -- Case studies: Date class Standard library : String and Vector Today preprocessor

450 Midterm Breakdown?

451 IS 0020 Program Design and Software Tools
Inheritance Lecture 8 March 2, 2004

452 Introduction 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

453 Introduction Class hierarchy Direct base class Indirect 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

454 Three types of inheritance
Introduction 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

455 Introduction Abstraction “is-a” vs. “has-a”
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

456 Base Classes and Derived Classes
Object of one class “is an” object of another class Example: Rectangle is quadrilateral. Class Rectangle inherits from class Quadrilateral Quadrilateral: base class Rectangle: derived class 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

457 Base Classes and Derived Classes
Inheritance examples

458 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

459 AdministratorTeacher
Fig. 9.2 Inheritance hierarchy for university CommunityMembers. Single inheritance CommunityMember Employee Student Administrator Teacher AdministratorTeacher Staff Faculty Alumnus Multiple inheritance

460 ThreeDimensionalShape
Fig. 9.3 Inheritance hierarchy for Shapes. Shape TwoDimensionalShape ThreeDimensionalShape Circle Square Triangle Sphere Cube Tetrahedron

461 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

462 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

463 Relationship between Base Classes and Derived Classes
Base class and derived class relationship Example: Point/circle inheritance hierarchy Point x-y coordinate pair Circle Radius

464 Maintain x- and y-coordinates as private data members.
// Fig. 9.4: point.h // Point class definition represents an x-y coordinate pair. #ifndef POINT_H #define POINT_H 5 class Point { 7 public: Point( int = 0, int = 0 ); // default constructor 10 void setX( int ); // set x in coordinate pair int getX() const; // return x from coordinate pair 13 void setY( int ); // set y in coordinate pair int getY() const; // return y from coordinate pair 16 void print() const; // output Point object 18 19 private: int x; // x part of coordinate pair int y; // y part of coordinate pair 22 23 }; // end class Point 24 25 #endif point.h (1 of 1) Maintain x- and y-coordinates as private data members.

465 point.cpp (1 of 3) 1 // Fig. 9.5: point.cpp
// Point class member-function definitions. #include <iostream> 4 using std::cout; 6 #include "point.h" // Point class definition 8 // default constructor 10 Point::Point( int xValue, int yValue ) 11 { x = xValue; y = yValue; 14 15 } // end Point constructor 16 17 // set x in coordinate pair 18 void Point::setX( int xValue ) 19 { x = xValue; // no need for validation 21 22 } // end function setX 23 point.cpp (1 of 3)

466 point.cpp (2 of 3) 24 // return x from coordinate pair
25 int Point::getX() const 26 { return x; 28 29 } // end function getX 30 31 // set y in coordinate pair 32 void Point::setY( int yValue ) 33 { y = yValue; // no need for validation 35 36 } // end function setY 37 38 // return y from coordinate pair 39 int Point::getY() const 40 { return y; 42 43 } // end function getY 44 point.cpp (2 of 3)

467 point.cpp (3 of 3) 45 // output Point object
46 void Point::print() const 47 { cout << '[' << x << ", " << y << ']'; 49 50 } // end function print point.cpp (3 of 3)

468 Invoke set functions to modify private data.
// Fig. 9.6: pointtest.cpp // Testing class Point. #include <iostream> 4 using std::cout; using std::endl; 7 #include "point.h" // Point class definition 9 10 int main() 11 { Point point( 72, 115 ); // instantiate Point object 13 // display point coordinates cout << "X coordinate is " << point.getX() << "\nY coordinate is " << point.getY(); 17 point.setX( 10 ); // set x-coordinate point.setY( 10 ); // set y-coordinate 20 // display new point value cout << "\n\nThe new location of point is "; point.print(); cout << endl; 25 pointtest.cpp (1 of 2) Create a Point object. Invoke set functions to modify private data. Invoke public function print to display new coordinates.

469 pointtest.cpp (2 of 2) pointtest.cpp output (1 of 1)
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] pointtest.cpp (2 of 2) pointtest.cpp output (1 of 1)

470 Note code similar to Point code.
// Fig. 9.7: circle.h // Circle class contains x-y coordinate pair and radius. #ifndef CIRCLE_H #define CIRCLE_H 5 class Circle { 7 public: 9 // default constructor Circle( int = 0, int = 0, double = 0.0 ); 12 void setX( int ); // set x in coordinate pair int getX() const; // return x from coordinate pair 15 void setY( int ); // set y in coordinate pair int getY() const; // return y from coordinate pair 18 void setRadius( double ); // set radius double getRadius() const; // return radius 21 double getDiameter() const; // return diameter double getCircumference() const; // return circumference double getArea() const; // return area 25 circle.h (1 of 2) Note code similar to Point code.

471 Maintain x-y coordinates and radius as private data members.
void print() const; // output Circle object 27 28 private: int x; // x-coordinate of Circle's center int y; // y-coordinate of Circle's center double radius; // Circle's radius 32 33 }; // end class Circle 34 35 #endif Maintain x-y coordinates and radius as private data members. circle.h (2 of 2) Note code similar to Point code.

472 circle.cpp (1 of 4) 1 // Fig. 9.8: circle.cpp
// Circle class member-function definitions. #include <iostream> 4 using std::cout; 6 #include "circle.h" // Circle class definition 8 // default constructor 10 Circle::Circle( int xValue, int yValue, double radiusValue ) 11 { x = xValue; y = yValue; setRadius( radiusValue ); 15 16 } // end Circle constructor 17 18 // set x in coordinate pair 19 void Circle::setX( int xValue ) 20 { x = xValue; // no need for validation 22 23 } // end function setX 24 circle.cpp (1 of 4)

473 circle.cpp (2 of 4) 25 // return x from coordinate pair
26 int Circle::getX() const 27 { return x; 29 30 } // end function getX 31 32 // set y in coordinate pair 33 void Circle::setY( int yValue ) 34 { y = yValue; // no need for validation 36 37 } // end function setY 38 39 // return y from coordinate pair 40 int Circle::getY() const 41 { return y; 43 44 } // end function getY 45 circle.cpp (2 of 4)

474 Ensure non-negative value for radius.
46 // set radius 47 void Circle::setRadius( double radiusValue ) 48 { radius = ( radiusValue < 0.0 ? 0.0 : radiusValue ); 50 51 } // end function setRadius 52 53 // return radius 54 double Circle::getRadius() const 55 { return radius; 57 58 } // end function getRadius 59 60 // calculate and return diameter 61 double Circle::getDiameter() const 62 { return 2 * radius; 64 65 } // end function getDiameter 66 circle.cpp (3 of 4) Ensure non-negative value for radius.

475 circle.cpp (4 of 4) 67 // calculate and return circumference
68 double Circle::getCircumference() const 69 { return * getDiameter(); 71 72 } // end function getCircumference 73 74 // calculate and return area 75 double Circle::getArea() const 76 { return * radius * radius; 78 79 } // end function getArea 80 81 // output Circle object 82 void Circle::print() const 83 { cout << "Center = [" << x << ", " << y << ']' << "; Radius = " << radius; 86 87 } // end function print circle.cpp (4 of 4)

476 circletest.cpp (1 of 2) Create Circle object.
// Fig. 9.9: circletest.cpp // Testing class Circle. #include <iostream> 4 using std::cout; using std::endl; using std::fixed; 8 #include <iomanip> 10 11 using std::setprecision; 12 13 #include "circle.h" // Circle class definition 14 15 int main() 16 { Circle circle( 37, 43, 2.5 ); // instantiate Circle object 18 // display point coordinates cout << "X coordinate is " << circle.getX() << "\nY coordinate is " << circle.getY() << "\nRadius is " << circle.getRadius(); 23 circletest.cpp (1 of 2) Create Circle object.

477 Use set functions to modify private data. circletest.cpp (2 of 2)
circle.setX( 2 ); // set new x-coordinate circle.setY( 2 ); // set new y-coordinate circle.setRadius( 4.25 ); // set new radius 27 // display new point value cout << "\n\nThe new location and radius of circle are\n"; circle.print(); 31 // display floating-point values with 2 digits of precision cout << fixed << setprecision( 2 ); 34 // display Circle's diameter cout << "\nDiameter is " << circle.getDiameter(); 37 // display Circle's circumference cout << "\nCircumference is " << circle.getCircumference(); 40 // display Circle's area cout << "\nArea is " << circle.getArea(); 43 cout << endl; 45 return 0; // indicates successful termination 47 48 } // end main Use set functions to modify private data. circletest.cpp (2 of 2) Invoke public function print to display new coordinates.

478 circletest.cpp output (1 of 1)
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 circletest.cpp output (1 of 1)

479 Class Circle2 inherits from class Point. circle2.h (1 of 2)
// Fig. 9.10: circle2.h // Circle2 class contains x-y coordinate pair and radius. #ifndef CIRCLE2_H #define CIRCLE2_H 5 #include "point.h" // Point class definition 7 class Circle2 : public Point { 9 10 public: 11 // default constructor Circle2( int = 0, int = 0, double = 0.0 ); 14 void setRadius( double ); // set radius double getRadius() const; // return radius 17 double getDiameter() const; // return diameter double getCircumference() const; // return circumference double getArea() const; // return area 21 void print() const; // output Circle2 object 23 24 private: double radius; // Circle2's radius Class Circle2 inherits from class Point. circle2.h (1 of 2) Colon indicates inheritance. Keyword public indicates type of inheritance. Maintain private data member radius.

480 circle2.h (2 of 2) circle2.cpp (1 of 3)
26 27 }; // end class Circle2 28 29 #endif circle2.h (2 of 2) circle2.cpp (1 of 3) // Fig. 9.11: circle2.cpp // Circle2 class member-function definitions. #include <iostream> 4 using std::cout; 6 #include "circle2.h" // Circle2 class definition 8 // default constructor 10 Circle2::Circle2( int xValue, int yValue, double radiusValue ) 11 { x = xValue; y = yValue; 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.

481 circle2.cpp (2 of 3) 18 // set radius
19 void Circle2::setRadius( double radiusValue ) 20 { radius = ( radiusValue < 0.0 ? 0.0 : radiusValue ); 22 23 } // end function setRadius 24 25 // return radius 26 double Circle2::getRadius() const 27 { return radius; 29 30 } // end function getRadius 31 32 // calculate and return diameter 33 double Circle2::getDiameter() const 34 { return 2 * radius; 36 37 } // end function getDiameter 38 circle2.cpp (2 of 3)

482 39 // calculate and return circumference
40 double Circle2::getCircumference() const 41 { return * getDiameter(); 43 44 } // end function getCircumference 45 46 // calculate and return area 47 double Circle2::getArea() const 48 { return * radius * radius; 50 51 } // end function getArea 52 53 // output Circle2 object 54 void Circle2::print() const 55 { cout << "Center = [" << x << ", " << y << ']' << "; Radius = " << radius; 58 59 } // end function print circle2.cpp (3 of 3) Attempting to access base class Point’s private data members x and y results in syntax errors.

483 C:\cpphtp4\examples\ch09\CircleTest\circle2
C:\cpphtp4\examples\ch09\CircleTest\circle2.cpp(12) : error C2248: 'x' : cannot access private member declared in class 'Point' C:\cpphtp4\examples\ch09\circletest\point.h(20) : see declaration of 'x' C:\cpphtp4\examples\ch09\CircleTest\circle2.cpp(13) : error C2248: 'y' : cannot access private member declared in class 'Point' C:\cpphtp4\examples\ch09\circletest\point.h(21) : see declaration of 'y' C:\cpphtp4\examples\ch09\CircleTest\circle2.cpp(56) : error C2248: 'x' : cannot access private member declared in class 'Point' C:\cpphtp4\examples\ch09\CircleTest\circle2.cpp(56) : error C2248: 'y' : cannot access private member declared in class 'Point' Attempting to access base class Point’s private data members x and y results in syntax errors. circle2.cpp output (1 of 1)

484 // Fig. 9.12: point2.h // Point2 class definition represents an x-y coordinate pair. #ifndef POINT2_H #define POINT2_H 5 class Point2 { 7 public: Point2( int = 0, int = 0 ); // default constructor 10 void setX( int ); // set x in coordinate pair int getX() const; // return x from coordinate pair 13 void setY( int ); // set y in coordinate pair int getY() const; // return y from coordinate pair 16 void print() const; // output Point2 object 18 19 protected: int x; // x part of coordinate pair int y; // y part of coordinate pair 22 23 }; // end class Point2 24 25 #endif point2.h (1 of 1) Maintain x- and y-coordinates as protected data, accessible to derived classes.

485 point2.cpp (1 of 3) 1 // Fig. 9.13: point2.cpp
// Point2 class member-function definitions. #include <iostream> 4 using std::cout; 6 #include "point2.h" // Point2 class definition 8 // default constructor 10 Point2::Point2( int xValue, int yValue ) 11 { x = xValue; y = yValue; 14 15 } // end Point2 constructor 16 17 // set x in coordinate pair 18 void Point2::setX( int xValue ) 19 { x = xValue; // no need for validation 21 22 } // end function setX 23 point2.cpp (1 of 3)

486 point2.cpp (2 of 3) 24 // return x from coordinate pair
25 int Point2::getX() const 26 { return x; 28 29 } // end function getX 30 31 // set y in coordinate pair 32 void Point2::setY( int yValue ) 33 { y = yValue; // no need for validation 35 36 } // end function setY 37 38 // return y from coordinate pair 39 int Point2::getY() const 40 { return y; 42 43 } // end function getY 44 point2.cpp (2 of 3)

487 point2.cpp (3 of 3) 45 // output Point2 object
46 void Point2::print() const 47 { cout << '[' << x << ", " << y << ']'; 49 50 } // end function print point2.cpp (3 of 3)

488 Class Circle3 inherits from class Point2. circle3.h (1 of 2)
// Fig. 9.14: circle3.h // Circle3 class contains x-y coordinate pair and radius. #ifndef CIRCLE3_H #define CIRCLE3_H 5 #include "point2.h" // Point2 class definition 7 class Circle3 : public Point2 { 9 10 public: 11 // default constructor Circle3( int = 0, int = 0, double = 0.0 ); 14 void setRadius( double ); // set radius double getRadius() const; // return radius 17 double getDiameter() const; // return diameter double getCircumference() const; // return circumference double getArea() const; // return area 21 void print() const; // output Circle3 object 23 24 private: double radius; // Circle3's radius Class Circle3 inherits from class Point2. circle3.h (1 of 2) Maintain private data member radius.

489 26 27 }; // end class Circle3 28 29 #endif
circle3.h (2 of 2)

490 Constructor first implicitly calls base class’s default constructor.
// Fig. 9.15: circle3.cpp // Circle3 class member-function definitions. #include <iostream> 4 using std::cout; 6 #include "circle3.h" // Circle3 class definition 8 // default constructor 10 Circle3::Circle3( int xValue, int yValue, double radiusValue ) 11 { x = xValue; y = yValue; setRadius( radiusValue ); 15 16 } // end Circle3 constructor 17 18 // set radius 19 void Circle3::setRadius( double radiusValue ) 20 { radius = ( radiusValue < 0.0 ? 0.0 : radiusValue ); 22 23 } // end function setRadius 24 circle3.cpp (1 of 3) Constructor first implicitly calls base class’s default constructor. Modify inherited data members x and y, declared protected in base class Point2.

491 circle3.cpp (2 of 3) 25 // return radius
26 double Circle3::getRadius() const 27 { return radius; 29 30 } // end function getRadius 31 32 // calculate and return diameter 33 double Circle3::getDiameter() const 34 { return 2 * radius; 36 37 } // end function getDiameter 38 39 // calculate and return circumference 40 double Circle3::getCircumference() const 41 { return * getDiameter(); 43 44 } // end function getCircumference 45 circle3.cpp (2 of 3)

492 46 // calculate and return area
47 double Circle3::getArea() const 48 { return * radius * radius; 50 51 } // end function getArea 52 53 // output Circle3 object 54 void Circle3::print() const 55 { cout << "Center = [" << x << ", " << y << ']' << "; Radius = " << radius; 58 59 } // end function print circle3.cpp (3 of 3) Access inherited data members x and y, declared protected in base class Point2.

493 Use Circle3 get function to access private data radius.
// Fig. 9.16: circletest3.cpp // Testing class Circle3. #include <iostream> 4 using std::cout; using std::endl; using std::fixed; 8 #include <iomanip> 10 11 using std::setprecision; 12 13 #include "circle3.h" // Circle3 class definition 14 15 int main() 16 { Circle3 circle( 37, 43, 2.5 ); // instantiate Circle3 object 18 // display point coordinates cout << "X coordinate is " << circle.getX() << "\nY coordinate is " << circle.getY() << "\nRadius is " << circle.getRadius(); 23 circletest3.cpp (1 of 2) Create Circle3 object. Use inherited get functions to access inherited protected data x and y. Use Circle3 get function to access private data radius.

494 Use Circle3 set function to modify private data radius.
circle.setX( 2 ); // set new x-coordinate circle.setY( 2 ); // set new y-coordinate circle.setRadius( 4.25 ); // set new radius 27 // display new point value cout << "\n\nThe new location and radius of circle are\n"; circle.print(); 31 // display floating-point values with 2 digits of precision cout << fixed << setprecision( 2 ); 34 // display Circle3's diameter cout << "\nDiameter is " << circle.getDiameter(); 37 // display Circle3's circumference cout << "\nCircumference is " << circle.getCircumference(); 40 // display Circle3's area cout << "\nArea is " << circle.getArea(); 43 cout << endl; 45 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. circletest3.cpp (2 of 2)

495 circletest3.cpp output (1 of 1)
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 circletest3.cpp output (1 of 1)

496 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

497 // Fig. 9.17: point3.h // Point3 class definition represents an x-y coordinate pair. #ifndef POINT3_H #define POINT3_H 5 class Point3 { 7 public: Point3( int = 0, int = 0 ); // default constructor 10 void setX( int ); // set x in coordinate pair int getX() const; // return x from coordinate pair 13 void setY( int ); // set y in coordinate pair int getY() const; // return y from coordinate pair 16 void print() const; // output Point3 object 18 19 private: int x; // x part of coordinate pair int y; // y part of coordinate pair 22 23 }; // end class Point3 24 25 #endif point3.h (1 of 1) Better software-engineering practice: private over protected when possible.

498 Member initializers specify values of x and y.
// Fig. 9.18: point3.cpp // Point3 class member-function definitions. #include <iostream> 4 using std::cout; 6 #include "point3.h" // Point3 class definition 8 // default constructor 10 Point3::Point3( int xValue, int yValue ) : x( xValue ), y( yValue ) 12 { // empty body 14 15 } // end Point3 constructor 16 17 // set x in coordinate pair 18 void Point3::setX( int xValue ) 19 { x = xValue; // no need for validation 21 22 } // end function setX 23 point3.cpp (1 of 3) Member initializers specify values of x and y.

499 point3.cpp (2 of 3) 24 // return x from coordinate pair
25 int Point3::getX() const 26 { return x; 28 29 } // end function getX 30 31 // set y in coordinate pair 32 void Point3::setY( int yValue ) 33 { y = yValue; // no need for validation 35 36 } // end function setY 37 38 // return y from coordinate pair 39 int Point3::getY() const 40 { return y; 42 43 } // end function getY 44 point3.cpp (2 of 3)

500 Invoke non-private member functions to access private data.
45 // output Point3 object 46 void Point3::print() const 47 { cout << '[' << getX() << ", " << getY() << ']'; 49 50 } // end function print point3.cpp (3 of 3) Invoke non-private member functions to access private data.

501 Class Circle4 inherits from class Point3.
// Fig. 9.19: circle4.h // Circle4 class contains x-y coordinate pair and radius. #ifndef CIRCLE4_H #define CIRCLE4_H 5 #include "point3.h" // Point3 class definition 7 class Circle4 : public Point3 { 9 10 public: 11 // default constructor Circle4( int = 0, int = 0, double = 0.0 ); 14 void setRadius( double ); // set radius double getRadius() const; // return radius 17 double getDiameter() const; // return diameter double getCircumference() const; // return circumference double getArea() const; // return area 21 void print() const; // output Circle4 object 23 24 private: double radius; // Circle4's radius circle4.h (1 of 2) Class Circle4 inherits from class Point3. Maintain private data member radius.

502 26 27 }; // end class Circle4 28 29 #endif
circle4.h (2 of 2)

503 Base-class initializer syntax passes arguments to base class Point3.
// Fig. 9.20: circle4.cpp // Circle4 class member-function definitions. #include <iostream> 4 using std::cout; 6 #include "circle4.h" // Circle4 class definition 8 // default constructor 10 Circle4::Circle4( int xValue, int yValue, double radiusValue ) : Point3( xValue, yValue ) // call base-class constructor 12 { setRadius( radiusValue ); 14 15 } // end Circle4 constructor 16 17 // set radius 18 void Circle4::setRadius( double radiusValue ) 19 { radius = ( radiusValue < 0.0 ? 0.0 : radiusValue ); 21 22 } // end function setRadius 23 circle4.cpp (1 of 3) Base-class initializer syntax passes arguments to base class Point3.

504 24 // return radius 25 double Circle4::getRadius() const 26 { return radius; 28 29 } // end function getRadius 30 31 // calculate and return diameter 32 double Circle4::getDiameter() const 33 { return 2 * getRadius(); 35 36 } // end function getDiameter 37 38 // calculate and return circumference 39 double Circle4::getCircumference() const 40 { return * getDiameter(); 42 43 } // end function getCircumference 44 circle4.cpp (2 of 3) Invoke function getRadius rather than directly accessing data member radius.

505 Redefine class Point3’s member function print.
45 // calculate and return area 46 double Circle4::getArea() const 47 { return * getRadius() * getRadius(); 49 50 } // end function getArea 51 52 // output Circle4 object 53 void Circle4::print() const 54 { cout << "Center = "; Point3::print(); // invoke Point3's print function cout << "; Radius = " << getRadius(); 58 59 } // end function print circle4.cpp (3 of 3) Redefine class Point3’s member function print. Invoke function getRadius rather than directly accessing data member radius. Invoke base-class Point3’s print function using binary scope-resolution operator (::).

506 Use Circle3 get function to access private data radius.
// Fig. 9.21: circletest4.cpp // Testing class Circle4. #include <iostream> 4 using std::cout; using std::endl; using std::fixed; 8 #include <iomanip> 10 11 using std::setprecision; 12 13 #include "circle4.h" // Circle4 class definition 14 15 int main() 16 { Circle4 circle( 37, 43, 2.5 ); // instantiate Circle4 object 18 // display point coordinates cout << "X coordinate is " << circle.getX() << "\nY coordinate is " << circle.getY() << "\nRadius is " << circle.getRadius(); 23 circletest4.cpp (1 of 2) Create Circle4 object. Use inherited get functions to access inherited protected data x and y. Use Circle3 get function to access private data radius.

507 Use Circle3 set function to modify private data radius.
circle.setX( 2 ); // set new x-coordinate circle.setY( 2 ); // set new y-coordinate circle.setRadius( 4.25 ); // set new radius 27 // display new circle value cout << "\n\nThe new location and radius of circle are\n"; circle.print(); 31 // display floating-point values with 2 digits of precision cout << fixed << setprecision( 2 ); 34 // display Circle4's diameter cout << "\nDiameter is " << circle.getDiameter(); 37 // display Circle4's circumference cout << "\nCircumference is " << circle.getCircumference(); 40 // display Circle4's area cout << "\nArea is " << circle.getArea(); 43 cout << endl; 45 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. circletest4.cpp (2 of 2)

508 circletest4.cpp output (1 of 1)
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 circletest4.cpp output (1 of 1)

509 Case Study: Three-Level Inheritance Hierarchy
Three level point/circle/cylinder hierarchy Point x-y coordinate pair Circle Radius Cylinder Height

510 Class Cylinder inherits from class Circle4. cylinder.h (1 of 2)
// Fig. 9.22: cylinder.h // Cylinder class inherits from class Circle4. #ifndef CYLINDER_H #define CYLINDER_H 5 #include "circle4.h" // Circle4 class definition 7 class Cylinder : public Circle4 { 9 10 public: 11 // default constructor Cylinder( int = 0, int = 0, double = 0.0, double = 0.0 ); 14 void setHeight( double ); // set Cylinder's height double getHeight() const; // return Cylinder's height 17 double getArea() const; // return Cylinder's area double getVolume() const; // return Cylinder's volume void print() const; // output Cylinder 21 22 private: double height; // Cylinder's height 24 25 }; // end class Cylinder Class Cylinder inherits from class Circle4. cylinder.h (1 of 2) Maintain private data member height.

511 cylinder.h (2 of 2) cylinder.cpp (1 of 3)
26 27 #endif cylinder.h (2 of 2) cylinder.cpp (1 of 3) // Fig. 9.23: cylinder.cpp // Cylinder class inherits from class Circle4. #include <iostream> 4 using std::cout; 6 #include "cylinder.h" // Cylinder class definition 8 // default constructor 10 Cylinder::Cylinder( int xValue, int yValue, double radiusValue, double heightValue ) : Circle4( xValue, yValue, radiusValue ) 13 { setHeight( heightValue ); 15 16 } // end Cylinder constructor 17 Base-class initializer syntax passes arguments to base class Circle4.

512 18 // set Cylinder's height
19 void Cylinder::setHeight( double heightValue ) 20 { height = ( heightValue < 0.0 ? 0.0 : heightValue ); 22 23 } // end function setHeight 24 25 // get Cylinder's height 26 double Cylinder::getHeight() const 27 { return height; 29 30 } // end function getHeight 31 32 // redefine Circle4 function getArea to calculate Cylinder area 33 double Cylinder::getArea() const 34 { return 2 * Circle4::getArea() + getCircumference() * getHeight(); 37 38 } // end function getArea 39 cylinder.cpp (2 of 3) 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 (::).

513 Redefine class Circle4’s member function print.
40 // calculate Cylinder volume 41 double Cylinder::getVolume() const 42 { return Circle4::getArea() * getHeight(); 44 45 } // end function getVolume 46 47 // output Cylinder object 48 void Cylinder::print() const 49 { Circle4::print(); cout << "; Height = " << getHeight(); 52 53 } // end function print Invoke base-class Circle4’s getArea function using binary scope-resolution operator (::). cylinder.cpp (3 of 3) Redefine class Circle4’s member function print. Invoke base-class Circle4’s print function using binary scope-resolution operator (::).

514 Invoke indirectly inherited Point3 member functions.
// Fig. 9.24: cylindertest.cpp // Testing class Cylinder. #include <iostream> 4 using std::cout; using std::endl; using std::fixed; 8 #include <iomanip> 10 11 using std::setprecision; 12 13 #include "cylinder.h" // Cylinder class definition 14 15 int main() 16 { // instantiate Cylinder object Cylinder cylinder( 12, 23, 2.5, 5.7 ); 19 // display point coordinates cout << "X coordinate is " << cylinder.getX() << "\nY coordinate is " << cylinder.getY() << "\nRadius is " << cylinder.getRadius() << "\nHeight is " << cylinder.getHeight(); 25 cylindertest.cpp (1 of 3) Invoke indirectly inherited Point3 member functions. Invoke directly inherited Circle4 member function. Invoke Cylinder member function.

515 Invoke indirectly inherited Point3 member functions.
cylinder.setX( 2 ); // set new x-coordinate cylinder.setY( 2 ); // set new y-coordinate cylinder.setRadius( 4.25 ); // set new radius cylinder.setHeight( 10 ); // set new height 30 // display new cylinder value cout << "\n\nThe new location and radius of circle are\n"; cylinder.print(); 34 // display floating-point values with 2 digits of precision cout << fixed << setprecision( 2 ); 37 // display cylinder's diameter cout << "\n\nDiameter is " << cylinder.getDiameter(); 40 // display cylinder's circumference cout << "\nCircumference is " << cylinder.getCircumference(); 44 // display cylinder's area cout << "\nArea is " << cylinder.getArea(); 47 // display cylinder's volume cout << "\nVolume is " << cylinder.getVolume(); 50 Invoke indirectly inherited Point3 member functions. Invoke directly inherited Circle4 member function. cylindertest.cpp (2 of 3) Invoke Cylinder member function. Invoke redefined print function. Invoke redefined getArea function.

516 cylindertest.cpp (3 of 3) cylindertest.cpp output (1 of 1)
cout << endl; 52 return 0; // indicates successful termination 54 55 } // end main cylindertest.cpp (3 of 3) cylindertest.cpp output (1 of 1) 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 Volume is

517 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

518 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

519 Constructors and Destructors in Derived Classes
Base-class constructors, destructors, assignment operators Not inherited by derived classes Derived class constructors, assignment operators can call Constructors Assignment operators

520 // Fig. 9.25: point4.h // Point4 class definition represents an x-y coordinate pair. #ifndef POINT4_H #define POINT4_H 5 class Point4 { 7 public: Point4( int = 0, int = 0 ); // default constructor ~Point4(); // destructor 11 void setX( int ); // set x in coordinate pair int getX() const; // return x from coordinate pair 14 void setY( int ); // set y in coordinate pair int getY() const; // return y from coordinate pair 17 void print() const; // output Point3 object 19 20 private: int x; // x part of coordinate pair int y; // y part of coordinate pair 23 24 }; // end class Point4 25 26 #endif point4.h (1 of 1) Constructor and destructor output messages to demonstrate function call order.

521 Output message to demonstrate constructor function call order.
// Fig. 9.26: point4.cpp // Point4 class member-function definitions. #include <iostream> 4 using std::cout; using std::endl; 7 #include "point4.h" // Point4 class definition 9 10 // default constructor 11 Point4::Point4( int xValue, int yValue ) : x( xValue ), y( yValue ) 13 { cout << "Point4 constructor: "; print(); cout << endl; 17 18 } // end Point4 constructor 19 20 // destructor 21 Point4::~Point4() 22 { cout << "Point4 destructor: "; print(); cout << endl; point4.cpp (1 of 3) Output message to demonstrate constructor function call order. Output message to demonstrate destructor function call order.

522 point4.cpp (2 of 3) 26 27 } // end Point4 destructor 28
29 // set x in coordinate pair 30 void Point4::setX( int xValue ) 31 { x = xValue; // no need for validation 33 34 } // end function setX 35 36 // return x from coordinate pair 37 int Point4::getX() const 38 { return x; 40 41 } // end function getX 42 43 // set y in coordinate pair 44 void Point4::setY( int yValue ) 45 { y = yValue; // no need for validation 47 48 } // end function setY 49 point4.cpp (2 of 3)

523 point4.cpp (3 of 3) 50 // return y from coordinate pair
51 int Point4::getY() const 52 { return y; 54 55 } // end function getY 56 57 // output Point4 object 58 void Point4::print() const 59 { cout << '[' << getX() << ", " << getY() << ']'; 61 62 } // end function print point4.cpp (3 of 3)

524 // Fig. 9.27: circle5.h // Circle5 class contains x-y coordinate pair and radius. #ifndef CIRCLE5_H #define CIRCLE5_H 5 #include "point4.h" // Point4 class definition 7 class Circle5 : public Point4 { 9 10 public: 11 // default constructor Circle5( int = 0, int = 0, double = 0.0 ); 14 ~Circle5(); // destructor void setRadius( double ); // set radius double getRadius() const; // return radius 18 double getDiameter() const; // return diameter double getCircumference() const; // return circumference double getArea() const; // return area 22 void print() const; // output Circle5 object 24 circle5.h (1 of 2) Constructor and destructor output messages to demonstrate function call order.

525 circle5.h (2 of 2) 25 private: 26 double radius; // Circle5's radius
27 28 }; // end class Circle5 29 30 #endif circle5.h (2 of 2)

526 Output message to demonstrate constructor function call order.
// Fig. 9.28: circle5.cpp // Circle5 class member-function definitions. #include <iostream> 4 using std::cout; using std::endl; 7 #include "circle5.h" // Circle5 class definition 9 10 // default constructor 11 Circle5::Circle5( int xValue, int yValue, double radiusValue ) : Point4( xValue, yValue ) // call base-class constructor 13 { setRadius( radiusValue ); 15 cout << "Circle5 constructor: "; print(); cout << endl; 19 20 } // end Circle5 constructor 21 circle5.cpp (1 of 4) Output message to demonstrate constructor function call order.

527 Output message to demonstrate destructor function call order.
23 Circle5::~Circle5() 24 { cout << "Circle5 destructor: "; print(); cout << endl; 28 29 } // end Circle5 destructor 30 31 // set radius 32 void Circle5::setRadius( double radiusValue ) 33 { radius = ( radiusValue < 0.0 ? 0.0 : radiusValue ); 35 36 } // end function setRadius 37 38 // return radius 39 double Circle5::getRadius() const 40 { return radius; 42 43 } // end function getRadius 44 circle5.cpp (2 of 4) Output message to demonstrate destructor function call order.

528 circle5.cpp (3 of 4) 45 // calculate and return diameter
46 double Circle5::getDiameter() const 47 { return 2 * getRadius(); 49 50 } // end function getDiameter 51 52 // calculate and return circumference 53 double Circle5::getCircumference() const 54 { return * getDiameter(); 56 57 } // end function getCircumference 58 59 // calculate and return area 60 double Circle5::getArea() const 61 { return * getRadius() * getRadius(); 63 64 } // end function getArea 65 circle5.cpp (3 of 4)

529 circle5.cpp (4 of 4) 66 // output Circle5 object
67 void Circle5::print() const 68 { cout << "Center = "; Point4::print(); // invoke Point4's print function cout << "; Radius = " << getRadius(); 72 73 } // end function print circle5.cpp (4 of 4)

530 Point4 object goes in and out of scope immediately.
// Fig. 9.29: fig09_29.cpp // Display order in which base-class and derived-class // constructors are called. #include <iostream> 5 using std::cout; using std::endl; 8 #include "circle5.h" // Circle5 class definition 10 11 int main() 12 { { // begin new scope 14 Point4 point( 11, 22 ); 16 } // end scope 18 cout << endl; Circle5 circle1( 72, 29, 4.5 ); 21 cout << endl; Circle5 circle2( 5, 5, 10 ); 24 cout << endl; fig09_29.cpp (1 of 2) Point4 object goes in and out of scope immediately. Instantiate two Circle5 objects to demonstrate order of derived-class and base-class constructor/destructor function calls.

531 fig09_29.cpp (2 of 2) fig09_29.cpp output (1 of 1)
26 return 0; // indicates successful termination 28 29 } // end main Point4 constructor called for object in block; destructor called immediately as execution leaves scope. fig09_29.cpp (2 of 2) fig09_29.cpp output (1 of 1) Point4 constructor: [11, 22] Point4 destructor: [11, 22] Point4 constructor: [72, 29] Circle5 constructor: Center = [72, 29]; Radius = 4.5 Point4 constructor: [5, 5] Circle5 constructor: Center = [5, 5]; Radius = 10 Circle5 destructor: Center = [5, 5]; Radius = 10 Point4 destructor: [5, 5] Circle5 destructor: Center = [72, 29]; Radius = 4.5 Point4 destructor: [72, 29] Base-class Point4 constructor executes first when instantiating derived-class Circle5 object. Derived-class Circle5 constructor body executes after base-class Point4’s constructor finishes execution. Base-class Point4 constructor executes first when instantiating derived-class Circle5 object. Derived-class Circle5 constructor body executes after base-class Point4’s constructor finishes execution. Destructors for Circle5 object called in reverse order of constructors. Destructors for Circle5 object called in reverse order of constructors.

532 public, protected and private Inheritance

533 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

534 IS 0020 Program Design and Software Tools
Polymorphism Lecture 9 March 16, 2004

535 Introduction Polymorphism Examples “Program in the general”
Treat objects in same class hierarchy as if all base class Virtual functions and dynamic binding Will explain how polymorphism works 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 Class Employee for a natural example

536 Relationships Among Objects in an Inheritance Hierarchy
Previously, Circle inherited from Point Manipulated Point and Circle objects using member functions Now Invoke functions using base-class/derived-class pointers Introduce virtual functions Key concept Derived-class object can be treated as base-class object “is-a” relationship Base class is not a derived class object

537 10.2.1 Invoking Base-Class Functions from Derived-Class Objects
Aim pointers (base, derived) at objects (base, derived) Base pointer aimed at base object Derived pointer aimed at derived object Both straightforward Base pointer aimed at derived object “is a” relationship Circle “is a” Point Will invoke base class functions Function call depends on the class of the pointer/handle Does not depend on object to which it points With virtual functions, this can be changed (more later)

538 Base class print function.
// Fig. 10.1: point.h // Point class definition represents an x-y coordinate pair. #ifndef POINT_H #define POINT_H 5 class Point { 7 public: Point( int = 0, int = 0 ); // default constructor 10 void setX( int ); // set x in coordinate pair int getX() const; // return x from coordinate pair 13 void setY( int ); // set y in coordinate pair int getY() const; // return y from coordinate pair 16 void print() const; // output Point object 18 19 private: int x; // x part of coordinate pair int y; // y part of coordinate pair 22 23 }; // end class Point 24 25 #endif point.h (1 of 1) Base class print function.

539 point.cpp (1 of 2) 1 // Fig. 10.2: point.cpp
// Point class member-function definitions. #include <iostream> 4 using std::cout; 6 #include "point.h" // Point class definition 8 // default constructor 10 Point::Point( int xValue, int yValue ) : x( xValue ), y( yValue ) 12 { // empty body 14 15 } // end Point constructor 16 17 // set x in coordinate pair 18 void Point::setX( int xValue ) 19 { x = xValue; // no need for validation 21 22 } // end function setX 23 point.cpp (1 of 2)

540 Output the x,y coordinates of the Point.
24 // return x from coordinate pair 25 int Point::getX() const 26 { return x; 28 29 } // end function getX 30 31 // set y in coordinate pair 32 void Point::setY( int yValue ) 33 { y = yValue; // no need for validation 35 36 } // end function setY 37 38 // return y from coordinate pair 39 int Point::getY() const 40 { return y; 42 43 } // end function getY 44 45 // output Point object 46 void Point::print() const 47 { cout << '[' << getX() << ", " << getY() << ']'; 49 50 } // end function print point.cpp (2 of 2) Output the x,y coordinates of the Point.

541 Circle inherits from Point, but redefines its print function.
// Fig. 10.3: circle.h // Circle class contains x-y coordinate pair and radius. #ifndef CIRCLE_H #define CIRCLE_H 5 #include "point.h" // Point class definition 7 class Circle : public Point { 9 10 public: 11 // default constructor Circle( int = 0, int = 0, double = 0.0 ); 14 void setRadius( double ); // set radius double getRadius() const; // return radius 17 double getDiameter() const; // return diameter double getCircumference() const; // return circumference double getArea() const; // return area 21 void print() const; // output Circle object 23 24 private: double radius; // Circle's radius 26 27 }; // end class Circle 28 29 #endif circle.h (1 of 1) Circle inherits from Point, but redefines its print function.

542 circle.cpp (1 of 3) 1 // Fig. 10.4: circle.cpp
// Circle class member-function definitions. #include <iostream> 4 using std::cout; 6 #include "circle.h" // Circle class definition 8 // default constructor 10 Circle::Circle( int xValue, int yValue, double radiusValue ) : Point( xValue, yValue ) // call base-class constructor 12 { setRadius( radiusValue ); 14 15 } // end Circle constructor 16 17 // set radius 18 void Circle::setRadius( double radiusValue ) 19 { radius = ( radiusValue < 0.0 ? 0.0 : radiusValue ); 21 22 } // end function setRadius 23 circle.cpp (1 of 3)

543 circle.cpp (2 of 3) 24 // return radius
25 double Circle::getRadius() const 26 { return radius; 28 29 } // end function getRadius 30 31 // calculate and return diameter 32 double Circle::getDiameter() const 33 { return 2 * getRadius(); 35 36 } // end function getDiameter 37 38 // calculate and return circumference 39 double Circle::getCircumference() const 40 { return * getDiameter(); 42 43 } // end function getCircumference 44 45 // calculate and return area 46 double Circle::getArea() const 47 { return * getRadius() * getRadius(); 49 50 } // end function getArea circle.cpp (2 of 3)

544 51 52 // output Circle object 53 void Circle::print() const 54 { cout << "center = "; Point::print(); // invoke Point's print function cout << "; radius = " << getRadius(); 58 59 } // end function print Circle redefines its print function. It calls Point’s print function to output the x,y coordinates of the center, then prints the radius. circle.cpp (3 of 3)

545 fig10_05.cpp (1 of 3) 1 // Fig. 10.5: fig10_05.cpp
// Aiming base-class and derived-class pointers at base-class // and derived-class objects, respectively. #include <iostream> 5 using std::cout; using std::endl; 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 { Point point( 30, 50 ); Point *pointPtr = 0; // base-class pointer 21 Circle circle( 120, 89, 2.7 ); Circle *circlePtr = 0; // derived-class pointer 24 fig10_05.cpp (1 of 3)

546 25 // set floating-point numeric formatting
cout << fixed << setprecision( 2 ); 27 // output objects point and circle cout << "Print point and circle objects:" << "\nPoint: "; point.print(); // invokes Point's print cout << "\nCircle: "; circle.print(); // invokes Circle's print 34 // aim base-class pointer at base-class object and print pointPtr = &point; cout << "\n\nCalling print with base-class pointer to " << "\nbase-class object invokes base-class print " << "function:\n"; pointPtr->print(); // invokes Point's print 41 // aim derived-class pointer at derived-class object // and print circlePtr = &circle; cout << "\n\nCalling print with derived-class pointer to " << "\nderived-class object invokes derived-class " << "print function:\n"; 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. fig10_05.cpp (2 of 3)

547 50 // aim base-class pointer at derived-class object and print
pointPtr = &circle; cout << "\n\nCalling print with base-class pointer to " << "derived-class object\ninvokes base-class print " << "function on that derived-class object:\n"; pointPtr->print(); // invokes Point's print cout << endl; 57 return 0; 59 60 } // end main fig10_05.cpp (3 of 3) 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.

548 fig10_05.cpp output (1 of 1) Print point and circle objects:
Circle: center = [120, 89]; radius = 2.70 Calling print with base-class pointer to base-class object invokes base-class print function: [30, 50] Calling print with derived-class pointer to derived-class object invokes derived-class print function: center = [120, 89]; radius = 2.70 Calling print with base-class pointer to derived-class object invokes base-class print function on that derived-class object: [120, 89] fig10_05.cpp output (1 of 1)

549 Aiming Derived-Class Pointers at Base-Class Objects
Previous example Aimed base-class pointer at derived object Circle “is a” Point Aim a derived-class pointer at a base-class object Compiler error No “is a” relationship Point is not a Circle Circle has data/functions that Point does not setRadius (defined in Circle) not defined in Point Can cast base-object’s address to derived-class pointer Called downcasting (more in 10.9) Allows derived-class functionality

550 fig10_06.cpp (1 of 1) fig10_06.cpp output (1 of 1)
// Fig. 10.6: fig10_06.cpp // Aiming a derived-class pointer at a base-class object. #include "point.h" // Point class definition #include "circle.h" // Circle class definition 5 int main() { Point point( 30, 50 ); Circle *circlePtr = 0; 10 // aim derived-class pointer at base-class object circlePtr = &point; // Error: a Point is not a Circle 13 return 0; 15 16 } // end main fig10_06.cpp (1 of 1) fig10_06.cpp output (1 of 1) C:\cpphtp4\examples\ch10\fig10_06\Fig10_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

551 Derived-Class Member-Function Calls via Base-Class Pointers
Handle (pointer/reference) Base-pointer can aim at derived-object But can only call base-class functions Calling derived-class functions is a compiler error Functions not defined in base-class Common theme Data type of pointer/reference determines functions it can call

552 fig10_07.cpp (1 of 2) 1 // Fig. 10.7: fig10_07.cpp
// Attempting to invoke derived-class-only member functions // through a base-class pointer. #include "point.h" // Point class definition #include "circle.h" // Circle class definition 6 int main() { Point *pointPtr = 0; Circle circle( 120, 89, 2.7 ); 11 // aim base-class pointer at derived-class object pointPtr = &circle; 14 // invoke base-class member functions on derived-class // object through base-class pointer int x = pointPtr->getX(); int y = pointPtr->getY(); pointPtr->setX( 10 ); pointPtr->setY( 10 ); pointPtr->print(); 22 fig10_07.cpp (1 of 2)

553 23 // attempt to invoke derived-class-only member functions
// on derived-class object through base-class pointer double radius = pointPtr->getRadius(); pointPtr->setRadius( ); double diameter = pointPtr->getDiameter(); double circumference = pointPtr->getCircumference(); double area = pointPtr->getArea(); 30 return 0; 32 33 } // end main fig10_07.cpp (2 of 2) These functions are only defined in Circle. However, pointPtr is of class Point.

554 C:\cpphtp4\examples\ch10\fig10_07\fig10_07
C:\cpphtp4\examples\ch10\fig10_07\fig10_07.cpp(25) : error C2039: 'getRadius' : is not a member of 'Point' C:\cpphtp4\examples\ch10\fig10_07\point.h(6) : see declaration of 'Point' C:\cpphtp4\examples\ch10\fig10_07\fig10_07.cpp(26) : error C2039: 'setRadius' : is not a member of 'Point' C:\cpphtp4\examples\ch10\fig10_07\fig10_07.cpp(27) : error C2039: 'getDiameter' : is not a member of 'Point' C:\cpphtp4\examples\ch10\fig10_07\fig10_07.cpp(28) : error C2039: 'getCircumference' : is not a member of 'Point' C:\cpphtp4\examples\ch10\fig10_07\fig10_07.cpp(29) : error C2039: 'getArea' : is not a member of 'Point' fig10_07.cpp output (1 of 1)

555 Typically, pointer-class determines 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

556 Declare draw as virtual in base class
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

557 Virtual Functions Example
Redo Point, Circle example with virtual functions Base-class pointer to derived-class object Will call derived-class function

558 Print declared virtual. It will be virtual in all derived classes.
// Fig. 10.8: point.h // Point class definition represents an x-y coordinate pair. #ifndef POINT_H #define POINT_H 5 class Point { 7 public: Point( int = 0, int = 0 ); // default constructor 10 void setX( int ); // set x in coordinate pair int getX() const; // return x from coordinate pair 13 void setY( int ); // set y in coordinate pair int getY() const; // return y from coordinate pair 16 virtual void print() const; // output Point object 18 19 private: int x; // x part of coordinate pair int y; // y part of coordinate pair 22 23 }; // end class Point 24 25 #endif point.h (1 of 1) Print declared virtual. It will be virtual in all derived classes.

559 circle.h (1 of 1) 1 // Fig. 10.9: circle.h
// Circle class contains x-y coordinate pair and radius. #ifndef CIRCLE_H #define CIRCLE_H 5 #include "point.h" // Point class definition 7 class Circle : public Point { 9 10 public: 11 // default constructor Circle( int = 0, int = 0, double = 0.0 ); 14 void setRadius( double ); // set radius double getRadius() const; // return radius 17 double getDiameter() const; // return diameter double getCircumference() const; // return circumference double getArea() const; // return area 21 virtual void print() const; // output Circle object 23 24 private: double radius; // Circle's radius 26 27 }; // end class Circle 28 29 #endif circle.h (1 of 1)

560 fig10_10.cpp (1 of 3) 1 // Fig. 10.10: fig10_10.cpp
// Introducing polymorphism, virtual functions and dynamic // binding. #include <iostream> 5 using std::cout; using std::endl; 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 { Point point( 30, 50 ); Point *pointPtr = 0; 21 Circle circle( 120, 89, 2.7 ); Circle *circlePtr = 0; 24 fig10_10.cpp (1 of 3)

561 fig10_10.cpp (2 of 3) 25 // set floating-point numeric formatting
cout << fixed << setprecision( 2 ); 27 // output objects point and circle using static binding cout << "Invoking print function on point and circle " << "\nobjects with static binding " << "\n\nPoint: "; point.print(); // static binding cout << "\nCircle: "; circle.print(); // static binding 35 // output objects point and circle using dynamic binding cout << "\n\nInvoking print function on point and circle " << "\nobjects with dynamic binding"; 39 // aim base-class pointer at base-class object and print pointPtr = &point; cout << "\n\nCalling virtual function print with base-class" << "\npointer to base-class object" << "\ninvokes base-class print function:\n"; pointPtr->print(); 46 fig10_10.cpp (2 of 3)

562 47 // aim derived-class pointer at derived-class
// object and print circlePtr = &circle; cout << "\n\nCalling virtual function print with " << "\nderived-class pointer to derived-class object " << "\ninvokes derived-class print function:\n"; circlePtr->print(); 54 // aim base-class pointer at derived-class object and print pointPtr = &circle; cout << "\n\nCalling virtual function print with base-class" << "\npointer to derived-class object " << "\ninvokes derived-class print function:\n"; pointPtr->print(); // polymorphism: invokes circle's print cout << endl; 62 return 0; 64 65 } // end main fig10_10.cpp (3 of 3) At run time, the program determines that pointPtr is aiming at a Circle object, and calls Circle’s print function. This is an example of polymorphism.

563 Invoking print function on point and circle
objects with static binding Point: [30, 50] Circle: Center = [120, 89]; Radius = 2.70 objects with dynamic binding Calling virtual function print with base-class pointer to base-class object invokes base-class print function: [30, 50] Calling virtual function print with derived-class pointer to derived-class object invokes derived-class print function: Center = [120, 89]; Radius = 2.70 pointer to derived-class object fig10_10.cpp output (1 of 1)

564 Virtual Functions Polymorphism Summary
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 (more in section 10.9)

565 Polymorphism Examples
Suppose Rectangle derives from Quadrilateral Rectangle more specific Quadrilateral Any operation on Quadrilateral can be done on Rectangle (i.e., perimeter, area) 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

566 Polymorphism Examples
Video game example, continued 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” Polymorphism Command many objects without knowing type Extensible programs Add classes easily

567 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

568 Abstract Classes Abstract classes Concrete 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

569 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

570 Abstract base class pointers Application example
Abstract Classes Abstract base class pointers Useful for polymorphism Application example Abstract class Shape Defines draw as pure virtual function Circle, Triangle, Rectangle derived from Shape Each must implement draw Screen manager knows that each object can draw itself Iterators (more in later chapter) Walk through elements in vector/array Use base-class pointer to send draw message to each

571 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

572 Case Study: Inheriting Interface and Implementation
0.0 = 0 "Point" [x,y] pr2 "Circle" center=[x,y]; radius=r 2pr2 +2prh pr2h "Cylinder" center=[x,y]; radius=r; height=h getArea print getName getVolume Shape Point Circle Cylinder

573 Virtual and pure virtual functions.
// Fig. 10.12: shape.h // Shape abstract-base-class definition. #ifndef SHAPE_H #define SHAPE_H 5 #include <string> // C++ standard string class 7 using std::string; 9 10 class Shape { 11 12 public: 13 // virtual function that returns shape area virtual double getArea() const; 16 // virtual function that returns shape volume virtual double getVolume() const; 19 // pure virtual functions; overridden in derived classes virtual string getName() const = 0; // return shape name virtual void print() const = 0; // output shape 23 24 }; // end class Shape 25 26 #endif shape.h (1 of 1) Virtual and pure virtual functions.

574 shape.cpp (1 of 1) 1 // Fig. 10.13: shape.cpp
// Shape class member-function definitions. #include <iostream> 4 using std::cout; 6 #include "shape.h" // Shape class definition 8 // return area of shape; 0.0 by default 10 double getArea() const 11 { return 0.0; 13 14 } // end function getArea 15 16 // return volume of shape; 0.0 by default 17 double getVolume() const 18 { return 0.0; 20 21 } // end function getVolume shape.cpp (1 of 1)

575 // Fig. 10.14: point.h // Point class definition represents an x-y coordinate pair. #ifndef POINT_H #define POINT_H 5 #include "shape.h" // Shape class definition 7 class Point : public Shape { 9 10 public: Point( int = 0, int = 0 ); // default constructor 12 void setX( int ); // set x in coordinate pair int getX() const; // return x from coordinate pair 15 void setY( int ); // set y in coordinate pair int getY() const; // return y from coordinate pair 18 // return name of shape (i.e., "Point" ) virtual string getName() const; 21 virtual void print() const; // output Point object 23 point.h (1 of 2) Point only redefines getName and print, since getArea and getVolume are zero (it can use the default implementation).

576 point.h (2 of 2) 24 private: 25 int x; // x part of coordinate pair
int y; // y part of coordinate pair 27 28 }; // end class Point 29 30 #endif point.h (2 of 2)

577 point.cpp (1 of 3) 1 // Fig. 10.15: point.cpp
// Point class member-function definitions. #include <iostream> 4 using std::cout; 6 #include "point.h" // Point class definition 8 // default constructor 10 Point::Point( int xValue, int yValue ) : x( xValue ), y( yValue ) 12 { // empty body 14 15 } // end Point constructor 16 17 // set x in coordinate pair 18 void Point::setX( int xValue ) 19 { x = xValue; // no need for validation 21 22 } // end function setX 23 point.cpp (1 of 3)

578 point.cpp (2 of 3) 24 // return x from coordinate pair
25 int Point::getX() const 26 { return x; 28 29 } // end function getX 30 31 // set y in coordinate pair 32 void Point::setY( int yValue ) 33 { y = yValue; // no need for validation 35 36 } // end function setY 37 38 // return y from coordinate pair 39 int Point::getY() const 40 { return y; 42 43 } // end function getY 44 point.cpp (2 of 3)

579 Must override pure virtual functions getName and print.
45 // override pure virtual function getName: return name of Point 46 string Point::getName() const 47 { return "Point"; 49 50 } // end function getName 51 52 // override pure virtual function print: output Point object 53 void Point::print() const 54 { cout << '[' << getX() << ", " << getY() << ']'; 56 57 } // end function print Must override pure virtual functions getName and print. point.cpp (3 of 3)

580 circle.h (1 of 2) 1 // Fig. 10.16: circle.h
// Circle class contains x-y coordinate pair and radius. #ifndef CIRCLE_H #define CIRCLE_H 5 #include "point.h" // Point class definition 7 class Circle : public Point { 9 10 public: 11 // default constructor Circle( int = 0, int = 0, double = 0.0 ); 14 void setRadius( double ); // set radius double getRadius() const; // return radius 17 double getDiameter() const; // return diameter double getCircumference() const; // return circumference virtual double getArea() const; // return area 21 // return name of shape (i.e., "Circle") virtual string getName() const; 24 virtual void print() const; // output Circle object circle.h (1 of 2)

581 circle.h (2 of 2) 26 27 private: 28 double radius; // Circle's radius
29 30 }; // end class Circle 31 32 #endif circle.h (2 of 2)

582 circle.cpp (1 of 3) 1 // Fig. 10.17: circle.cpp
// Circle class member-function definitions. #include <iostream> 4 using std::cout; 6 #include "circle.h" // Circle class definition 8 // default constructor 10 Circle::Circle( int xValue, int yValue, double radiusValue ) : Point( xValue, yValue ) // call base-class constructor 12 { setRadius( radiusValue ); 14 15 } // end Circle constructor 16 17 // set radius 18 void Circle::setRadius( double radiusValue ) 19 { radius = ( radiusValue < 0.0 ? 0.0 : radiusValue ); 21 22 } // end function setRadius 23 circle.cpp (1 of 3)

583 circle.cpp (2 of 3) 24 // return radius
25 double Circle::getRadius() const 26 { return radius; 28 29 } // end function getRadius 30 31 // calculate and return diameter 32 double Circle::getDiameter() const 33 { return 2 * getRadius(); 35 36 } // end function getDiameter 37 38 // calculate and return circumference 39 double Circle::getCircumference() const 40 { return * getDiameter(); 42 43 } // end function getCircumference 44 circle.cpp (2 of 3)

584 Override getArea because it now applies to Circle.
45 // override virtual function getArea: return area of Circle 46 double Circle::getArea() const 47 { return * getRadius() * getRadius(); 49 50 } // end function getArea 51 52 // override virutual function getName: return name of Circle 53 string Circle::getName() const 54 { return "Circle"; 56 57 } // end function getName 58 59 // override virtual function print: output Circle object 60 void Circle::print() const 61 { cout << "center is "; Point::print(); // invoke Point's print function cout << "; radius is " << getRadius(); 65 66 } // end function print circle.cpp (3 of 3) Override getArea because it now applies to Circle.

585 cylinder.h (1 of 2) 1 // Fig. 10.18: cylinder.h
// Cylinder class inherits from class Circle. #ifndef CYLINDER_H #define CYLINDER_H 5 #include "circle.h" // Circle class definition 7 class Cylinder : public Circle { 9 10 public: 11 // default constructor Cylinder( int = 0, int = 0, double = 0.0, double = 0.0 ); 14 void setHeight( double ); // set Cylinder's height double getHeight() const; // return Cylinder's height 17 virtual double getArea() const; // return Cylinder's area virtual double getVolume() const; // return Cylinder's volume 20 cylinder.h (1 of 2)

586 cylinder.h (2 of 2) 21 // return name of shape (i.e., "Cylinder" )
virtual string getName() const; 23 virtual void print() const; // output Cylinder 25 26 private: double height; // Cylinder's height 28 29 }; // end class Cylinder 30 31 #endif cylinder.h (2 of 2)

587 cylinder.cpp (1 of 3) 1 // Fig. 10.19: cylinder.cpp
// Cylinder class inherits from class Circle. #include <iostream> 4 using std::cout; 6 #include "cylinder.h" // Cylinder class definition 8 // default constructor 10 Cylinder::Cylinder( int xValue, int yValue, double radiusValue, double heightValue ) : Circle( xValue, yValue, radiusValue ) 13 { setHeight( heightValue ); 15 16 } // end Cylinder constructor 17 18 // set Cylinder's height 19 void Cylinder::setHeight( double heightValue ) 20 { height = ( heightValue < 0.0 ? 0.0 : heightValue ); 22 23 } // end function setHeight cylinder.cpp (1 of 3)

588 cylinder.cpp (2 of 3) 24 25 // get Cylinder's height
26 double Cylinder::getHeight() const 27 { return height; 29 30 } // end function getHeight 31 32 // override virtual function getArea: return Cylinder area 33 double Cylinder::getArea() const 34 { return 2 * Circle::getArea() // code reuse getCircumference() * getHeight(); 37 38 } // end function getArea 39 40 // override virtual function getVolume: return Cylinder volume 41 double Cylinder::getVolume() const 42 { return Circle::getArea() * getHeight(); // code reuse 44 45 } // end function getVolume 46 cylinder.cpp (2 of 3)

589 47 // override virtual function getName: return name of Cylinder
48 string Cylinder::getName() const 49 { return "Cylinder"; 51 52 } // end function getName 53 54 // output Cylinder object 55 void Cylinder::print() const 56 { Circle::print(); // code reuse cout << "; height is " << getHeight(); 59 60 } // end function print cylinder.cpp (3 of 3)

590 fig10_20.cpp (1 of 5) 1 // Fig. 10.20: fig10_20.cpp
// Driver for shape, point, circle, cylinder hierarchy. #include <iostream> 4 using std::cout; using std::endl; using std::fixed; 8 #include <iomanip> 10 11 using std::setprecision; 12 13 #include <vector> 14 15 using std::vector; 16 17 #include "shape.h" // Shape class definition 18 #include "point.h" // Point class definition 19 #include "circle.h" // Circle class definition 20 #include "cylinder.h" // Cylinder class definition 21 22 void virtualViaPointer( const Shape * ); 23 void virtualViaReference( const Shape & ); 24 fig10_20.cpp (1 of 5)

591 fig10_20.cpp (2 of 5) 25 int main() 26 {
26 { // set floating-point number format cout << fixed << setprecision( 2 ); 29 Point point( 7, 11 ); // create a Point Circle circle( 22, 8, 3.5 ); // create a Circle Cylinder cylinder( 10, 10, 3.3, 10 ); // create a Cylinder 33 cout << point.getName() << ": "; // static binding point.print(); // static binding cout << '\n'; 37 cout << circle.getName() << ": "; // static binding circle.print(); // static binding cout << '\n'; 41 cout << cylinder.getName() << ": "; // static binding cylinder.print(); // static binding cout << "\n\n"; 45 fig10_20.cpp (2 of 5)

592 The types are dynamically bound at run-time. fig10_20.cpp (3 of 5)
// create vector of three base-class pointers vector< Shape * > shapeVector( 3 ); 48 // aim shapeVector[0] at derived-class Point object shapeVector[ 0 ] = &point; 51 // aim shapeVector[1] at derived-class Circle object shapeVector[ 1 ] = &circle; 54 // aim shapeVector[2] at derived-class Cylinder object shapeVector[ 2 ] = &cylinder; 57 // loop through shapeVector and call virtualViaPointer // to print the shape name, attributes, area and volume // of each object using dynamic binding cout << "\nVirtual function calls made off " << "base-class pointers:\n\n"; 63 for ( int i = 0; i < shapeVector.size(); i++ ) virtualViaPointer( shapeVector[ i ] ); 66 Create a vector of generic Shape pointers, and aim them at various objects. Function virtualViaPointer calls the virtual functions (print, getName, etc.) using the base-class pointers. The types are dynamically bound at run-time. fig10_20.cpp (3 of 5)

593 Use references instead of pointers, for the same effect.
// loop through shapeVector and call virtualViaReference // to print the shape name, attributes, area and volume // of each object using dynamic binding cout << "\nVirtual function calls made off " << "base-class references:\n\n"; 72 for ( int j = 0; j < shapeVector.size(); j++ ) virtualViaReference( *shapeVector[ j ] ); 75 return 0; 77 78 } // end main 79 80 // make virtual function calls off a base-class pointer 81 // using dynamic binding 82 void virtualViaPointer( const Shape *baseClassPtr ) 83 { cout << baseClassPtr->getName() << ": "; 85 baseClassPtr->print(); 87 cout << "\narea is " << baseClassPtr->getArea() << "\nvolume is " << baseClassPtr->getVolume() << "\n\n"; 91 92 } // end function virtualViaPointer 93 Use references instead of pointers, for the same effect. fig10_20.cpp (4 of 5) Call virtual functions; the proper class function will be called at run-time.

594 94 // make virtual function calls off a base-class reference
95 // using dynamic binding 96 void virtualViaReference( const Shape &baseClassRef ) 97 { cout << baseClassRef.getName() << ": "; 99 baseClassRef.print(); 101 cout << "\narea is " << baseClassRef.getArea() << "\nvolume is " << baseClassRef.getVolume() << "\n\n"; 104 105 } // end function virtualViaReference fig10_20.cpp (5 of 5)

595 fig10_20.cpp output (1 of 2) Point: [7, 11]
Circle: center is [22, 8]; radius is 3.50 Cylinder: center is [10, 10]; radius is 3.30; height is 10.00 Virtual function calls made off base-class pointers: area is 0.00 volume is 0.00 area is 38.48 area is volume is fig10_20.cpp output (1 of 2)

596 Virtual function calls made off base-class references:
Point: [7, 11] area is 0.00 volume is 0.00 Circle: center is [22, 8]; radius is 3.50 area is 38.48 Cylinder: center is [10, 10]; radius is 3.30; height is 10.00 area is volume is fig10_20.cpp output (2 of 2)

597 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 (Fig )

598 Base class pointer to derived object Simple fix
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

599 Base class pointer to derived object Simple fix
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

600 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%

601 10.9 Case Study: 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 HourlyEmployee CommissionEmployee BasePlusCommissionEmployee

602 Case Study: Payroll System Using Polymorphism
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()

603 employee.h (1 of 2) 1 // Fig. 10.23: employee.h
// Employee abstract base class. #ifndef EMPLOYEE_H #define EMPLOYEE_H 5 #include <string> // C++ standard string class 7 using std::string; 9 10 class Employee { 11 12 public: Employee( const string &, const string &, const string & ); 14 void setFirstName( const string & ); string getFirstName() const; 17 void setLastName( const string & ); string getLastName() const; 20 void setSocialSecurityNumber( const string & ); string getSocialSecurityNumber() const; 23 employee.h (1 of 2)

604 24 // pure virtual function makes Employee abstract base class
virtual double earnings() const = 0; // pure virtual virtual void print() const; // virtual 27 28 private: string firstName; string lastName; string socialSecurityNumber; 32 33 }; // end class Employee 34 35 #endif // EMPLOYEE_H employee.h (2 of 2)

605 employee.cpp (1 of 3) 1 // Fig. 10.24: employee.cpp
// Abstract-base-class Employee member-function definitions. // Note: No definitions are given for pure virtual functions. #include <iostream> 5 using std::cout; using std::endl; 8 #include "employee.h" // Employee class definition 10 11 // constructor 12 Employee::Employee( const string &first, const string &last, const string &SSN ) : firstName( first ), lastName( last ), socialSecurityNumber( SSN ) 17 { // empty body 19 20 } // end Employee constructor 21 employee.cpp (1 of 3)

606 employee.cpp (2 of 3) 22 // return first name
23 string Employee::getFirstName() const 24 { return firstName; 26 27 } // end function getFirstName 28 29 // return last name 30 string Employee::getLastName() const 31 { return lastName; 33 34 } // end function getLastName 35 36 // return social security number 37 string Employee::getSocialSecurityNumber() const 38 { return socialSecurityNumber; 40 41 } // end function getSocialSecurityNumber 42 43 // set first name 44 void Employee::setFirstName( const string &first ) 45 { firstName = first; 47 48 } // end function setFirstName 49 employee.cpp (2 of 3)

607 Default implementation for virtual function print.
50 // set last name 51 void Employee::setLastName( const string &last ) 52 { lastName = last; 54 55 } // end function setLastName 56 57 // set social security number 58 void Employee::setSocialSecurityNumber( const string &number ) 59 { socialSecurityNumber = number; // should validate 61 62 } // end function setSocialSecurityNumber 63 64 // print Employee's information 65 void Employee::print() const 66 { cout << getFirstName() << ' ' << getLastName() << "\nsocial security number: " << getSocialSecurityNumber() << endl; 70 71 } // end function print employee.cpp (3 of 3) Default implementation for virtual function print.

608 // Fig. 10.25: salaried.h // SalariedEmployee class derived from Employee. #ifndef SALARIED_H #define SALARIED_H 5 #include "employee.h" // Employee class definition 7 class SalariedEmployee : public Employee { 9 10 public: SalariedEmployee( const string &, const string &, const string &, double = 0.0 ); 13 void setWeeklySalary( double ); double getWeeklySalary() const; 16 virtual double earnings() const; virtual void print() const; // "salaried employee: " 19 20 private: double weeklySalary; 22 23 }; // end class SalariedEmployee 24 25 #endif // SALARIED_H salaried.h (1 of 1) New functions for the SalariedEmployee class. earnings must be overridden. print is overridden to specify that this is a salaried employee.

609 Use base class constructor for basic fields.
// Fig. 10.26: salaried.cpp // SalariedEmployee class member-function definitions. #include <iostream> 4 using std::cout; 6 #include "salaried.h" // SalariedEmployee class definition 8 // SalariedEmployee constructor 10 SalariedEmployee::SalariedEmployee( const string &first, const string &last, const string &socialSecurityNumber, double salary ) : Employee( first, last, socialSecurityNumber ) 14 { setWeeklySalary( salary ); 16 17 } // end SalariedEmployee constructor 18 19 // set salaried employee's salary 20 void SalariedEmployee::setWeeklySalary( double salary ) 21 { weeklySalary = salary < 0.0 ? 0.0 : salary; 23 24 } // end function setWeeklySalary 25 salaried.cpp (1 of 2) Use base class constructor for basic fields.

610 Must implement pure virtual functions. salaried.cpp (2 of 2)
26 // calculate salaried employee's pay 27 double SalariedEmployee::earnings() const 28 { return getWeeklySalary(); 30 31 } // end function earnings 32 33 // return salaried employee's salary 34 double SalariedEmployee::getWeeklySalary() const 35 { return weeklySalary; 37 38 } // end function getWeeklySalary 39 40 // print salaried employee's name 41 void SalariedEmployee::print() const 42 { cout << "\nsalaried employee: "; Employee::print(); // code reuse 45 46 } // end function print Must implement pure virtual functions. salaried.cpp (2 of 2)

611 hourly.h (1 of 1) 1 // Fig. 10.27: hourly.h
// HourlyEmployee class definition. #ifndef HOURLY_H #define HOURLY_H 5 #include "employee.h" // Employee class definition 7 class HourlyEmployee : public Employee { 9 10 public: HourlyEmployee( const string &, const string &, const string &, double = 0.0, double = 0.0 ); 13 void setWage( double ); double getWage() const; 16 void setHours( double ); double getHours() const; 19 virtual double earnings() const; virtual void print() const; 22 23 private: double wage; // wage per hour double hours; // hours worked for week 26 27 }; // end class HourlyEmployee 28 29 #endif // HOURLY_H hourly.h (1 of 1)

612 hourly.cpp (1 of 3) 1 // Fig. 10.28: hourly.cpp
// HourlyEmployee class member-function definitions. #include <iostream> 4 using std::cout; 6 #include "hourly.h" 8 // constructor for class HourlyEmployee 10 HourlyEmployee::HourlyEmployee( const string &first, const string &last, const string &socialSecurityNumber, double hourlyWage, double hoursWorked ) : Employee( first, last, socialSecurityNumber ) 14 { setWage( hourlyWage ); setHours( hoursWorked ); 17 18 } // end HourlyEmployee constructor 19 20 // set hourly employee's wage 21 void HourlyEmployee::setWage( double wageAmount ) 22 { wage = wageAmount < 0.0 ? 0.0 : wageAmount; 24 25 } // end function setWage hourly.cpp (1 of 3)

613 hourly.cpp (2 of 3) 26 27 // set hourly employee's hours worked
28 void HourlyEmployee::setHours( double hoursWorked ) 29 { hours = ( hoursWorked >= 0.0 && hoursWorked <= ) ? hoursWorked : 0.0; 32 33 } // end function setHours 34 35 // return hours worked 36 double HourlyEmployee::getHours() const 37 { return hours; 39 40 } // end function getHours 41 42 // return wage 43 double HourlyEmployee::getWage() const 44 { return wage; 46 47 } // end function getWage 48 hourly.cpp (2 of 3)

614 hourly.cpp (3 of 3) 49 // get hourly employee's pay
50 double HourlyEmployee::earnings() const 51 { if ( hours <= 40 ) // no overtime return wage * hours; else // overtime is paid at wage * 1.5 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 { cout << "\nhourly employee: "; Employee::print(); // code reuse 64 65 } // end function print hourly.cpp (3 of 3)

615 commission.h (1 of 1) Must set rate and sales.
// Fig. 10.29: commission.h // CommissionEmployee class derived from Employee. #ifndef COMMISSION_H #define COMMISSION_H 5 #include "employee.h" // Employee class definition 7 class CommissionEmployee : public Employee { 9 10 public: CommissionEmployee( const string &, const string &, const string &, double = 0.0, double = 0.0 ); 13 void setCommissionRate( double ); double getCommissionRate() const; 16 void setGrossSales( double ); double getGrossSales() const; 19 virtual double earnings() const; virtual void print() const; 22 23 private: double grossSales; // gross weekly sales double commissionRate; // commission percentage 26 27 }; // end class CommissionEmployee 28 29 #endif // COMMISSION_H commission.h (1 of 1) Must set rate and sales.

616 commission.cpp (1 of 3) 1 // Fig. 10.30: commission.cpp
// CommissionEmployee class member-function definitions. #include <iostream> 4 using std::cout; 6 #include "commission.h" // Commission class 8 // CommissionEmployee constructor 10 CommissionEmployee::CommissionEmployee( const string &first, const string &last, const string &socialSecurityNumber, double grossWeeklySales, double percent ) : Employee( first, last, socialSecurityNumber ) 14 { setGrossSales( grossWeeklySales ); setCommissionRate( percent ); 17 18 } // end CommissionEmployee constructor 19 20 // return commission employee's rate 21 double CommissionEmployee::getCommissionRate() const 22 { return commissionRate; 24 25 } // end function getCommissionRate commission.cpp (1 of 3)

617 26 27 // return commission employee's gross sales amount 28 double CommissionEmployee::getGrossSales() const 29 { return grossSales; 31 32 } // end function getGrossSales 33 34 // set commission employee's weekly base salary 35 void CommissionEmployee::setGrossSales( double sales ) 36 { 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 { commissionRate = ( rate > 0.0 && rate < 1.0 ) ? rate : 0.0; 45 46 } // end function setCommissionRate 47 commission.cpp (2 of 3)

618 commission.cpp (3 of 3) 48 // calculate commission employee's earnings
49 double CommissionEmployee::earnings() const 50 { return getCommissionRate() * getGrossSales(); 52 53 } // end function earnings 54 55 // print commission employee's name 56 void CommissionEmployee::print() const 57 { cout << "\ncommission employee: "; Employee::print(); // code reuse 60 61 } // end function print commission.cpp (3 of 3)

619 Inherits from CommissionEmployee (and from Employee indirectly).
// Fig. 10.31: baseplus.h // BasePlusCommissionEmployee class derived from Employee. #ifndef BASEPLUS_H #define BASEPLUS_H 5 #include "commission.h" // Employee class definition 7 class BasePlusCommissionEmployee : public CommissionEmployee { 9 10 public: BasePlusCommissionEmployee( const string &, const string &, const string &, double = 0.0, double = 0.0, double = 0.0 ); 13 void setBaseSalary( double ); double getBaseSalary() const; 16 virtual double earnings() const; virtual void print() const; 19 20 private: double baseSalary; // base salary per week 22 23 }; // end class BasePlusCommissionEmployee 24 25 #endif // BASEPLUS_H Inherits from CommissionEmployee (and from Employee indirectly). baseplus.h (1 of 1)

620 baseplus.cpp (1 of 2) 1 // Fig. 10.32: baseplus.cpp
// BasePlusCommissionEmployee member-function definitions. #include <iostream> 4 using std::cout; 6 #include "baseplus.h" 8 // constructor for class BasePlusCommissionEmployee 10 BasePlusCommissionEmployee::BasePlusCommissionEmployee( const string &first, const string &last, const string &socialSecurityNumber, double grossSalesAmount, double rate, double baseSalaryAmount ) : CommissionEmployee( first, last, socialSecurityNumber, grossSalesAmount, rate ) 17 { setBaseSalary( baseSalaryAmount ); 19 20 } // end BasePlusCommissionEmployee constructor 21 22 // set base-salaried commission employee's wage 23 void BasePlusCommissionEmployee::setBaseSalary( double salary ) 24 { baseSalary = salary < 0.0 ? 0.0 : salary; 26 27 } // end function setBaseSalary baseplus.cpp (1 of 2)

621 28 29 // return base-salaried commission employee's base salary 30 double BasePlusCommissionEmployee::getBaseSalary() const 31 { return baseSalary; 33 34 } // end function getBaseSalary 35 36 // return base-salaried commission employee's earnings 37 double BasePlusCommissionEmployee::earnings() const 38 { return getBaseSalary() + CommissionEmployee::earnings(); 40 41 } // end function earnings 42 43 // print base-salaried commission employee's name 44 void BasePlusCommissionEmployee::print() const 45 { cout << "\nbase-salaried commission employee: "; Employee::print(); // code reuse 48 49 } // end function print baseplus.cpp (2 of 2)

622 fig10_33.cpp (1 of 4) 1 // Fig. 10.33: fig10_33.cpp
// Driver for Employee hierarchy. #include <iostream> 4 using std::cout; using std::endl; using std::fixed; 8 #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 fig10_33.cpp (1 of 4)

623 fig10_33.cpp (2 of 4) 25 int main() 26 {
26 { // set floating-point output formatting cout << fixed << setprecision( 2 ); 29 // create vector employees vector < Employee * > employees( 4 ); 32 // initialize vector with Employees employees[ 0 ] = new SalariedEmployee( "John", "Smith", " ", ); employees[ 1 ] = new CommissionEmployee( "Sue", "Jones", " ", 10000, .06 ); employees[ 2 ] = new BasePlusCommissionEmployee( "Bob", "Lewis", " ", 300, 5000, .04 ); employees[ 3 ] = new HourlyEmployee( "Karen", "Price", " ", 16.75, 40 ); 42 fig10_33.cpp (2 of 4)

624 43 // generically process each element in vector employees
for ( int i = 0; i < employees.size(); i++ ) { 45 // output employee information employees[ i ]->print(); 48 // downcast pointer BasePlusCommissionEmployee *commissionPtr = dynamic_cast < BasePlusCommissionEmployee * > ( employees[ i ] ); 53 // determine whether element points to base-salaried // commission employee if ( commissionPtr != 0 ) { cout << "old base salary: $" << commissionPtr->getBaseSalary() << endl; commissionPtr->setBaseSalary( * commissionPtr->getBaseSalary() ); cout << "new base salary with 10% increase is: $" << commissionPtr->getBaseSalary() << endl; 63 } // end if 65 cout << "earned $" << employees[ i ]->earnings() << endl; 67 } // 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. fig10_33.cpp (3 of 4)

625 70 // release memory held by vector employees
for ( int j = 0; j < employees.size(); j++ ) { 72 // output class name cout << "\ndeleting object of " << typeid( *employees[ j ] ).name(); 76 delete employees[ j ]; 78 } // end for 80 cout << endl; 82 return 0; 84 85 } // end main fig10_33.cpp (4 of 4) typeid returns a type_info object. This object contains information about the operand, including its name.

626 fig10_33.cpp output (1 of 1) salaried employee: John Smith
social security number: earned $800.00 commission employee: Sue Jones social security number: earned $600.00 base-salaried commission employee: Bob Lewis social security number: old base salary: $300.00 new base salary with 10% increase is: $330.00 earned $530.00 hourly employee: Karen Price social security number: earned $670.00 deleting object of class SalariedEmployee deleting object of class CommissionEmployee deleting object of class BasePlusCommissionEmployee deleting object of class HourlyEmployee fig10_33.cpp output (1 of 1)

627 IS 0020 Program Design and Software Tools
Templates Lecture 10 March 23, 2004

628 Introduction Templates Function templates Class templates
Specify entire range of related (overloaded) functions Function-template specializations Class templates Specify entire range of related classes Class-template specializations

629 Function Templates Overloaded functions Function templates
Similar operations Different types of data Function templates Identical operations Single function template Compiler generates separate object-code functions Unlike Macros they allow Type checking

630 Function-template definitions
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

631 Function template definition; declare single formal type parameter T.
// Fig. 11.1: fig11_01.cpp // Using template functions. #include <iostream> 4 using std::cout; using std::endl; 7 // function template printArray definition template< class T > 10 void printArray( const T *array, const int count ) 11 { for ( int i = 0; i < count; i++ ) cout << array[ i ] << " "; 14 cout << endl; 16 17 } // end function printArray 18 19 int main() 20 { const int aCount = 5; const int bCount = 7; const int cCount = 6; 24 fig11_01.cpp (1 of 2) 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.

632 int a[ aCount ] = { 1, 2, 3, 4, 5 }; double b[ bCount ] = { 1.1, 2.2, 3.3, 4.4, 5.5, 6.6, 7.7 }; char c[ cCount ] = "HELLO"; // 6th position for null 28 cout << "Array a contains:" << endl; 30 // call integer function-template specialization printArray( a, aCount ); 33 cout << "Array b contains:" << endl; 35 // call double function-template specialization printArray( b, bCount ); 38 cout << "Array c contains:" << endl; 40 // call character function-template specialization printArray( c, cCount ); 43 return 0; 45 46 } // end main fig11_01.cpp (2 of 2) 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.

633 fig11_01.cpp output (1 of 1) Array a contains: 1 2 3 4 5
Array b contains: Array c contains: H E L L O fig11_01.cpp output (1 of 1)

634 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

635 Class Templates Stack Class templates
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

636 Function parameters of type T.
// Fig. 11.2: tstack1.h // Stack class template. #ifndef TSTACK1_H #define TSTACK1_H 5 template< class T > class Stack { 8 public: Stack( int = 10 ); // default constructor (stack size 10) 11 // destructor ~Stack() { delete [] stackPtr; 16 } // end ~Stack destructor 18 bool push( const T& ); // push an element onto the stack 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. tstack1.h (1 of 4) Function parameters of type T.

637 Array of elements of type T.
// determine whether Stack is empty bool isEmpty() const { return top == -1; 26 } // end function isEmpty 28 // determine whether Stack is full bool isFull() const { return top == size - 1; 33 } // end function isFull 35 36 private: int size; // # of elements in the stack int top; // location of the top element T *stackPtr; // pointer to the stack 40 41 }; // end class Stack 42 tstack1.h (2 of 4) Array of elements of type T.

638 Member functions preceded with header
43 // constructor 44 template< class T > 45 Stack< T >::Stack( int s ) 46 { size = s > 0 ? s : 10; top = -1; // Stack initially empty 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 { if ( !isFull() ) { stackPtr[ ++top ] = pushValue; // place item on Stack return true; // push successful 61 } // end if 63 return false; // push unsuccessful 65 66 } // end function push 67 Member functions preceded with header template< class T > Constructor creates array of type T. For example, compiler generates stackPtr = new T[ size ]; for class-template specialization Stack< double >. Use binary scope resolution operator (::) with class-template name (Stack< T >) to tie definition to class template’s scope. tstack1.h (3 of 4)

639 Member function preceded with header
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 { if ( !isEmpty() ) { popValue = stackPtr[ top-- ]; // remove item from Stack return true; // pop successful 76 } // end if 78 return false; // pop unsuccessful 80 81 } // end function pop 82 83 #endif Member function preceded with header template< class T > tstack1.h (4 of 4) Use binary scope resolution operator (::) with class-template name (Stack< T >) to tie definition to class template’s scope.

640 Link to class template definition.
// Fig. 11.3: fig11_03.cpp // Stack-class-template test program. #include <iostream> 4 using std::cout; using std::cin; using std::endl; 8 #include "tstack1.h" // Stack class template definition 10 11 int main() 12 { Stack< double > doubleStack( 5 ); double doubleValue = 1.1; 15 cout << "Pushing elements onto doubleStack\n"; 17 while ( doubleStack.push( doubleValue ) ) { cout << doubleValue << ' '; doubleValue += 1.1; 21 } // end while 23 cout << "\nStack is full. Cannot push " << doubleValue << "\n\nPopping elements from doubleStack\n"; fig11_03.cpp (1 of 3) Link to class template definition. Instantiate object of class Stack< double >. Invoke function push of class-template specialization Stack< double >.

641 26 while ( doubleStack.pop( doubleValue ) ) cout << doubleValue << ' '; 29 cout << "\nStack is empty. Cannot pop\n"; 31 Stack< int > intStack; int intValue = 1; cout << "\nPushing elements onto intStack\n"; 35 while ( intStack.push( intValue ) ) { cout << intValue << ' '; intValue; 39 } // end while 41 cout << "\nStack is full. Cannot push " << intValue << "\n\nPopping elements from intStack\n"; 44 while ( intStack.pop( intValue ) ) cout << intValue << ' '; 47 cout << "\nStack is empty. Cannot pop\n"; 49 return 0; Invoke function pop of class-template specialization Stack< double >. fig11_03.cpp (2 of 3) Note similarity of code for Stack< int > to code for Stack< double >.

642 fig11_03.cpp (3 of 3) fig11_03.cpp output (1 of 1)
51 52 } // end main Pushing elements onto doubleStack Stack is full. Cannot push 6.6 Popping elements from doubleStack Stack is empty. Cannot pop Pushing elements onto intStack Stack is full. Cannot push 11 Popping elements from intStack fig11_03.cpp (3 of 3) fig11_03.cpp output (1 of 1)

643 // Fig. 11.4: fig11_04.cpp // Stack class template test program. Function main uses a // function template to manipulate objects of type Stack< T >. #include <iostream> 5 using std::cout; using std::cin; 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( Stack< T > &theStack, // reference to Stack< T > T value, // initial value to push T increment, // increment for subsequent values const char *stackName ) // name of the Stack < T > object 19 { cout << "\nPushing elements onto " << stackName << '\n'; 21 while ( theStack.push( value ) ) { cout << value << ' '; value += increment; 25 } // end while fig11_04.cpp (1 of 2) Function template to manipulate Stack< T > eliminates similar code from previous file for Stack< double > and Stack< int >.

644 27 cout << "\nStack is full. Cannot push " << value << "\n\nPopping elements from " << stackName << '\n'; 30 while ( theStack.pop( value ) ) cout << value << ' '; 33 cout << "\nStack is empty. Cannot pop\n"; 35 36 } // end function testStack 37 38 int main() 39 { Stack< double > doubleStack( 5 ); Stack< int > intStack; 42 testStack( doubleStack, 1.1, 1.1, "doubleStack" ); testStack( intStack, 1, 1, "intStack" ); 45 return 0; 47 48 } // end main fig11_04.cpp (2 of 2)

645 Note output identical to that of fig11_03.cpp.
Pushing elements onto doubleStack Stack is full. Cannot push 6.6 Popping elements from doubleStack Stack is empty. Cannot pop Pushing elements onto intStack Stack is full. Cannot push 11 Popping elements from intStack fig11_04.cpp output (1 of 1) Note output identical to that of fig11_03.cpp.

646 Class Templates and Nontype Parameters
Default arguments Treated as consts Example: template< class T, int elements > Stack< double, 100 > mostRecentSalesFigures; Declares object of type Stack< double, 100> Type parameter Default type template< class T = string >

647 Class Templates and Nontype Parameters
Overriding class templates Class for specific type Does not match common class template Example: template<> Class Array< Martian > { // body of class definition };

648 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

649 Friendships between class template and
Templates and Friends Friendships between class template and Global function Member function of another class Entire class

650 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

651 Templates and Friends friend functions friend classes
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 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.

652 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

653 IS 0020 Program Design and Software Tools
Data Structures Lecture 10 March 23, 2004

654 Fixed-size data structures Dynamic data structures
Introduction Fixed-size data structures Arrays, structs Dynamic data structures Grow and shrink as program runs Linked lists Insert/remove items anywhere Stacks Insert/remove from top of stack Queues Like a line, insert at back, remove from front Binary trees High-speed searching/sorting of data

655 Self-Referential Classes
Has pointer to object of same class Link together to form useful data structures Lists, stacks, queues, trees Terminated with NULL pointer 15 10 Data member and pointer NULL pointer (points to nothing)

656 Self-Referential Classes
Sample code class Node { public: Node( int ); void setData( int ); int getData() const; void setNextPtr( Node * ); const Node *getNextPtr() const; private: int data; Node *nextPtr; }; Pointer to object called a link nextPtr points to a Node

657 Dynamic Memory Allocation and Data Structures
Obtain and release memory during program execution Create and remove nodes Operator new Takes type of object to create Returns pointer to newly created object Node *newPtr = new Node( 10 ); Returns bad_alloc if not enough memory 10 is the node's object data

658 Dynamic Memory Allocation and Data Structures
Operator delete delete newPtr; Deallocates memory allocated by new, calls destructor Memory returned to system, can be used in future newPtr not deleted, only the space it points to

659 Linked Lists Linked list
Collection of self-referential class objects (nodes) connected by pointers (links) Accessed using pointer to first node of list Subsequent nodes accessed using the links in each node Link in last node is null (zero) Indicates end of list Data stored dynamically Nodes created as necessary Node can have data of any type

660 Linked Lists H D Q firstPtr lastPtr ...

661 Linked Lists Linked lists vs. arrays Arrays can become full
Allocating "extra" space in array wasteful, may never be used Linked lists can grow/shrink as needed Linked lists only become full when system runs out of memory Linked lists can be maintained in sorted order Insert element at proper position Existing elements do not need to be moved

662 Selected linked list operations
Linked Lists Selected linked list operations Insert node at front Insert node at back Remove node from front Remove node from back In following illustrations List has firstPtr and lastPtr (a) is before, (b) is after

663 Insert at front firstPtr = newPtr If list empty, then
7 11 firstPtr 12 newPtr a) b) firstPtr = newPtr If list empty, then firstPtr = lastPtr = newPtr newPtr->nextPtr = firstPtr

664 Insert at back lastPtr->nextPtr = newPtr lastPtr = newPtr
firstPtr lastPtr a) newPtr b) 12 7 11 5 lastPtr = newPtr If list empty, then firstPtr = lastPtr = newPtr lastPtr->nextPtr = newPtr

665 Remove from front tempPtr = firstPtr firstPtr = firstPtr->next
lastPtr a) b) tempPtr 12 7 5 11 tempPtr = firstPtr firstPtr = firstPtr->next If there are no more nodes, firstPtr = lastPtr = 0 delete tempPtr

666 Remove from back "Walk" list until get next-to-last node, until currentPtr->nextPtr = lastPtr a) firstPtr lastPtr 12 7 11 5 b) firstPtr currentPtr lastPtr lastPtr = currentPtr 12 7 11 5 tempPtr = lastPtr tempPtr delete tempPtr

667 Upcoming program has two class templates
Linked Lists Upcoming program has two class templates Create two class templates ListNode data (type depends on class template) nextPtr List Linked list of ListNode objects List manipulation functions insertAtFront insertAtBack removeFromFront removeFromBack

668 // Fig. 17.3: listnode.h // Template ListNode class definition. #ifndef LISTNODE_H #define LISTNODE_H 5 // forward declaration of class List template< class NODETYPE > class List; 8 template< class NODETYPE> 10 class ListNode { friend class List< NODETYPE >; // make List a friend 12 13 public: ListNode( const NODETYPE & ); // constructor NODETYPE getData() const; // return data in node 16 17 private: NODETYPE data; // data ListNode< NODETYPE > *nextPtr; // next node in list 20 21 }; // end class ListNode 22 listnode.h (1 of 2) Template class ListNode. The type of member data depends on how the class template is used.

669 listnode.h (2 of 2) 23 // constructor
24 template< class NODETYPE> 25 ListNode< NODETYPE >::ListNode( const NODETYPE &info ) : data( info ), nextPtr( 0 ) 28 { // empty body 30 31 } // end ListNode constructor 32 33 // return copy of data in node 34 template< class NODETYPE > 35 NODETYPE ListNode< NODETYPE >::getData() const 36 { return data; 38 39 } // end function getData 40 41 #endif listnode.h (2 of 2)

670 list.h (1 of 9) 1 // Fig. 17.4: list.h
// Template List class definition. #ifndef LIST_H #define LIST_H 5 #include <iostream> 7 using std::cout; 9 10 #include <new> 11 #include "listnode.h" // ListNode class definition 12 13 template< class NODETYPE > 14 class List { 15 16 public: List(); // constructor ~List(); // destructor void insertAtFront( const NODETYPE & ); void insertAtBack( const NODETYPE & ); bool removeFromFront( NODETYPE & ); bool removeFromBack( NODETYPE & ); bool isEmpty() const; void print() const; 25 list.h (1 of 9)

671 Each List has a firstPtr and lastPtr.
26 private: ListNode< NODETYPE > *firstPtr; // pointer to first node ListNode< NODETYPE > *lastPtr; // pointer to last node 29 // utility function to allocate new node ListNode< NODETYPE > *getNewNode( const NODETYPE & ); 32 33 }; // end class List 34 35 // default constructor 36 template< class NODETYPE > 37 List< NODETYPE >::List() : firstPtr( 0 ), lastPtr( 0 ) 40 { // empty body 42 43 } // end List constructor 44 Each List has a firstPtr and lastPtr. list.h (2 of 9)

672 list.h (3 of 9) 45 // destructor 46 template< class NODETYPE >
47 List< NODETYPE >::~List() 48 { if ( !isEmpty() ) { // List is not empty cout << "Destroying nodes ...\n"; 51 ListNode< NODETYPE > *currentPtr = firstPtr; ListNode< NODETYPE > *tempPtr; 54 while ( currentPtr != 0 ) { // delete remaining nodes tempPtr = currentPtr; cout << tempPtr->data << '\n'; currentPtr = currentPtr->nextPtr; delete tempPtr; 60 } // end while 62 } // end if 64 cout << "All nodes destroyed\n\n"; 66 67 } // end List destructor 68 list.h (3 of 9)

673 Insert a new node as described in the previous diagrams.
69 // insert node at front of list 70 template< class NODETYPE > 71 void List< NODETYPE >::insertAtFront( const NODETYPE &value ) 72 { ListNode< NODETYPE > *newPtr = getNewNode( value ); 74 if ( isEmpty() ) // List is empty firstPtr = lastPtr = newPtr; 77 else { // List is not empty newPtr->nextPtr = firstPtr; firstPtr = newPtr; 81 } // end else 83 84 } // end function insertAtFront 85 Insert a new node as described in the previous diagrams. list.h (4 of 9)

674 list.h (5 of 9) 86 // insert node at back of list
87 template< class NODETYPE > 88 void List< NODETYPE >::insertAtBack( const NODETYPE &value ) 89 { ListNode< NODETYPE > *newPtr = getNewNode( value ); 91 if ( isEmpty() ) // List is empty firstPtr = lastPtr = newPtr; 94 else { // List is not empty lastPtr->nextPtr = newPtr; lastPtr = newPtr; 98 } // end else 100 101 } // end function insertAtBack 102 list.h (5 of 9)

675 list.h (6 of 9) 103 // delete node from front of list
104 template< class NODETYPE > 105 bool List< NODETYPE >::removeFromFront( NODETYPE &value ) 106 { if ( isEmpty() ) // List is empty return false; // delete unsuccessful 109 else { ListNode< NODETYPE > *tempPtr = firstPtr; 112 if ( firstPtr == lastPtr ) firstPtr = lastPtr = 0; else firstPtr = firstPtr->nextPtr; 117 value = tempPtr->data; // data being removed delete tempPtr; 120 return true; // delete successful 122 } // end else 124 125 } // end function removeFromFront 126 list.h (6 of 9)

676 list.h (7 of 9) 127 // delete node from back of list
128 template< class NODETYPE > 129 bool List< NODETYPE >::removeFromBack( NODETYPE &value ) 130 { if ( isEmpty() ) return false; // delete unsuccessful 133 else { ListNode< NODETYPE > *tempPtr = lastPtr; 136 if ( firstPtr == lastPtr ) firstPtr = lastPtr = 0; else { ListNode< NODETYPE > *currentPtr = firstPtr; 141 // locate second-to-last element while ( currentPtr->nextPtr != lastPtr ) currentPtr = currentPtr->nextPtr; 145 lastPtr = currentPtr; currentPtr->nextPtr = 0; 148 } // end else 150 value = tempPtr->data; delete tempPtr; 153 list.h (7 of 9)

677 Note use of new operator to dynamically allocate a node.
return true; // delete successful 155 } // end else 157 158 } // end function removeFromBack 159 160 // is List empty? 161 template< class NODETYPE > 162 bool List< NODETYPE >::isEmpty() const 163 { return firstPtr == 0; 165 166 } // end function isEmpty 167 168 // return pointer to newly allocated node 169 template< class NODETYPE > 170 ListNode< NODETYPE > *List< NODETYPE >::getNewNode( const NODETYPE &value ) 172 { return new ListNode< NODETYPE >( value ); 174 175 } // end function getNewNode 176 list.h (8 of 9) Note use of new operator to dynamically allocate a node.

678 list.h (9 of 9) 177 // display contents of List
178 template< class NODETYPE > 179 void List< NODETYPE >::print() const 180 { if ( isEmpty() ) { cout << "The list is empty\n\n"; return; 184 } // end if 186 ListNode< NODETYPE > *currentPtr = firstPtr; 188 cout << "The list is: "; 190 while ( currentPtr != 0 ) { cout << currentPtr->data << ' '; currentPtr = currentPtr->nextPtr; 194 } // end while 196 cout << "\n\n"; 198 199 } // end function print 200 201 #endif list.h (9 of 9)

679 Program to give user a menu to add/remove nodes from a list.
// Fig. 17.5: fig17_05.cpp // List class test program. #include <iostream> 4 using std::cin; using std::endl; 7 #include <string> 9 10 using std::string; 11 12 #include "list.h" // List class definition 13 14 // function to test a List 15 template< class T > 16 void testList( List< T > &listObject, const string &typeName ) 17 { cout << "Testing a List of " << typeName << " values\n"; 19 instructions(); // display instructions 21 int choice; T value; 24 Program to give user a menu to add/remove nodes from a list. fig17_05.cpp (1 of 4)

680 fig17_05.cpp (2 of 4) 25 do { 26 cout << "? ";
cin >> choice; 28 switch ( choice ) { case 1: cout << "Enter " << typeName << ": "; cin >> value; listObject.insertAtFront( value ); listObject.print(); break; 36 case 2: cout << "Enter " << typeName << ": "; cin >> value; listObject.insertAtBack( value ); listObject.print(); break; 43 case 3: if ( listObject.removeFromFront( value ) ) cout << value << " removed from list\n"; 47 listObject.print(); break; 50 fig17_05.cpp (2 of 4)

681 case 4: if ( listObject.removeFromBack( value ) ) cout << value << " removed from list\n"; 54 listObject.print(); break; 57 } // end switch 59 } while ( choice != 5 ); // end do/while 61 cout << "End list test\n\n"; 63 64 } // end function testList 65 66 // display program instructions to user 67 void instructions() 68 { cout << "Enter one of the following:\n" << " 1 to insert at beginning of list\n" << " 2 to insert at end of list\n" << " 3 to delete from beginning of list\n" << " 4 to delete from end of list\n" << " 5 to end list processing\n"; 75 76 } // end function instructions fig17_05.cpp (3 of 4)

682 fig17_05.cpp (4 of 4) 77 78 int main() 79 {
79 { // test List of int values List< int > integerList; testList( integerList, "integer" ); 83 // test List of double values List< double > doubleList; testList( doubleList, "double" ); 87 return 0; 89 90 } // end main fig17_05.cpp (4 of 4)

683 fig17_05.cpp output (1 of 4) Testing a List of integer values
Enter one of the following: 1 to insert at beginning of list 2 to insert at end of list 3 to delete from beginning of list 4 to delete from end of list 5 to end list processing ? 1 Enter integer: 1 The list is: 1 Enter integer: 2 The list is: 2 1 ? 2 Enter integer: 3 The list is: 2 1 3 Enter integer: 4 The list is: fig17_05.cpp output (1 of 4)

684 fig17_05.cpp output (2 of 4) ? 3 2 removed from list
The list is: 1 3 4 1 removed from list The list is: 3 4 ? 4 4 removed from list The list is: 3 3 removed from list The list is empty ? 5 End list test fig17_05.cpp output (2 of 4)

685 fig17_05.cpp output (3 of 4) Testing a List of double values
Enter one of the following: 1 to insert at beginning of list 2 to insert at end of list 3 to delete from beginning of list 4 to delete from end of list 5 to end list processing ? 1 Enter double: 1.1 The list is: 1.1 Enter double: 2.2 The list is: ? 2 Enter double: 3.3 The list is: Enter double: 4.4 The list is: ? 3 2.2 removed from list The list is: fig17_05.cpp output (3 of 4)

686 fig17_05.cpp output (4 of 4) ? 3 1.1 removed from list
The list is: ? 4 4.4 removed from list The list is: 3.3 3.3 removed from list The list is empty ? 5 End list test All nodes destroyed fig17_05.cpp output (4 of 4)

687 Linked Lists Types of linked lists
Singly linked list (used in example) Pointer to first node Travel in one direction (null-terminated) Circular, singly-linked As above, but last node points to first Doubly-linked list Each node has a forward and backwards pointer Travel forward or backward Last node null-terminated Circular, double-linked As above, but first and last node joined

688 Stacks Stack Stack operations Nodes can be added/removed from top
Constrained version of linked list Like a stack of plates Last-in, first-out (LIFO) data structure Bottom of stack has null link Stack operations Push: add node to top Pop: remove node from top Stores value in reference variable

689 Stacks Stack applications Function calls: know how to return to caller
Return address pushed on stack Most recent function call on top If function A calls B which calls C: Used to store automatic variables Popped of stack when no longer needed Used by compilers Example in the exercises in book C B B B A A A A A

690 Stacks Upcoming program Create stack from list Software reusability
insertAtFront, removeFromFront Software reusability Inheritance Stack inherits from List Composition Stack contains a private List object Performs operations on that object Makes stack implementation simple

691 Stack inherits from List.
// Fig : stack.h // Template Stack class definition derived from class List. #ifndef STACK_H #define STACK_H 5 #include "list.h" // List class definition 7 template< class STACKTYPE > class Stack : private List< STACKTYPE > { 10 11 public: // push calls List function insertAtFront void push( const STACKTYPE &data ) { insertAtFront( data ); 16 } // end function push 18 // pop calls List function removeFromFront bool pop( STACKTYPE &data ) { return removeFromFront( data ); 23 } // end function pop 25 stack.h (1 of 2) Stack inherits from List. Define push and pop, which call insertAtFront and removeFromFront.

692 stack.h (2 of 2) 26 // isStackEmpty calls List function isEmpty
bool isStackEmpty() const { return isEmpty(); 30 } // end function isStackEmpty 32 // printStack calls List function print void printStack() const { print(); 37 } // end function print 39 40 }; // end class Stack 41 42 #endif stack.h (2 of 2)

693 fig17_11.cpp (1 of 3) 1 // Fig. 17.11: fig17_11.cpp
// Template Stack class test program. #include <iostream> 4 using std::endl; 6 #include "stack.h" // Stack class definition 8 int main() 10 { Stack< int > intStack; // create Stack of ints 12 cout << "processing an integer Stack" << endl; 14 // push integers onto intStack for ( int i = 0; i < 4; i++ ) { intStack.push( i ); intStack.printStack(); 19 } // end for 21 // pop integers from intStack int popInteger; 24 fig17_11.cpp (1 of 3)

694 fig17_11.cpp (2 of 3) 25 while ( !intStack.isStackEmpty() ) {
intStack.pop( popInteger ); cout << popInteger << " popped from stack" << endl; intStack.printStack(); 29 } // end while 31 Stack< double > doubleStack; // create Stack of doubles double value = 1.1; 34 cout << "processing a double Stack" << endl; 36 // push floating-point values onto doubleStack for ( int j = 0; j< 4; j++ ) { doubleStack.push( value ); doubleStack.printStack(); value += 1.1; 42 } // end for 44 fig17_11.cpp (2 of 3)

695 fig17_11.cpp (3 of 3) 45 // pop floating-point values from doubleStack
double popDouble; 47 while ( !doubleStack.isStackEmpty() ) { doubleStack.pop( popDouble ); cout << popDouble << " popped from stack" << endl; doubleStack.printStack(); 52 } // end while 54 return 0; 56 57 } // end main fig17_11.cpp (3 of 3)

696 fig17_11.cpp output (1 of 2) processing an integer Stack
The list is: 0 The list is: 1 0 The list is: 2 1 0 The list is: 3 popped from stack 2 popped from stack 1 popped from stack 0 popped from stack The list is empty processing a double Stack The list is: 1.1 The list is: The list is: fig17_11.cpp output (1 of 2)

697 fig17_11.cpp output (2 of 2) The list is: 4.4 3.3 2.2 1.1
4.4 popped from stack The list is: 3.3 popped from stack The list is: 2.2 popped from stack The list is: 1.1 1.1 popped from stack The list is empty All nodes destroyed fig17_11.cpp output (2 of 2)

698 stackcomposition.h (1 of 2)
// Fig : stackcomposition.h // Template Stack class definition with composed List object. #ifndef STACKCOMPOSITION #define STACKCOMPOSITION 5 #include "list.h" // List class definition 7 template< class STACKTYPE > class Stack { 10 11 public: // no constructor; List constructor does initialization 13 // push calls stackList object's insertAtFront function void push( const STACKTYPE &data ) { stackList.insertAtFront( data ); 18 } // end function push 20 // pop calls stackList object's removeFromFront function bool pop( STACKTYPE &data ) { return stackList.removeFromFront( data ); 25 } // end function pop 27 stackcomposition.h (1 of 2) Alternative implementation of stack.h, using composition. Declare a private List member, use to manipulate stack.

699 stackcomposition.h (2 of 2)
// isStackEmpty calls stackList object's isEmpty function bool isStackEmpty() const { return stackList.isEmpty(); 32 } // end function isStackEmpty 34 // printStack calls stackList object's print function void printStack() const { stackList.print(); 39 } // end function printStack 41 42 private: List< STACKTYPE > stackList; // composed List object 44 45 }; // end class Stack 46 47 #endif stackcomposition.h (2 of 2)

700 Queues Queue Applications Like waiting in line
Nodes added to back (tail), removed from front (head) First-in, first-out (FIFO) data structure Insert/remove called enqueue/dequeue Applications Print spooling Documents wait in queue until printer available Packets on network File requests from server

701 Queues Upcoming program Queue implementation Reuse List as before
insertAtBack (enqueue) removeFromFront (dequeue)

702 Inherit from template class List.
// Fig : queue.h // Template Queue class definition derived from class List. #ifndef QUEUE_H #define QUEUE_H 5 #include "list.h" // List class definition 7 template< class QUEUETYPE > class Queue : private List< QUEUETYPE > { 10 11 public: // enqueue calls List function insertAtBack void enqueue( const QUEUETYPE &data ) { insertAtBack( data ); 16 } // end function enqueue 18 // dequeue calls List function removeFromFront bool dequeue( QUEUETYPE &data ) { return removeFromFront( data ); 23 } // end function dequeue 25 queue.h (1 of 2) Inherit from template class List. Reuse the appropriate List functions.

703 queue.h (2 of 2) 26 // isQueueEmpty calls List function isEmpty
bool isQueueEmpty() const { return isEmpty(); 30 } // end function isQueueEmpty 32 // printQueue calls List function print void printQueue() const { print(); 37 } // end function printQueue 39 40 }; // end class Queue 41 42 #endif queue.h (2 of 2)

704 fig17_14.cpp (1 of 3) 1 // Fig. 17.14: fig17_14.cpp
// Template Queue class test program. #include <iostream> 4 using std::endl; 6 #include "queue.h" // Queue class definition 8 int main() 10 { Queue< int > intQueue; // create Queue of ints 12 cout << "processing an integer Queue" << endl; 14 // enqueue integers onto intQueue for ( int i = 0; i < 4; i++ ) { intQueue.enqueue( i ); intQueue.printQueue(); 19 } // end for 21 // dequeue integers from intQueue int dequeueInteger; 24 fig17_14.cpp (1 of 3)

705 fig17_14.cpp (2 of 3) 25 while ( !intQueue.isQueueEmpty() ) {
intQueue.dequeue( dequeueInteger ); cout << dequeueInteger << " dequeued" << endl; intQueue.printQueue(); 29 } // end while 31 Queue< double > doubleQueue; // create Queue of doubles double value = 1.1; 34 cout << "processing a double Queue" << endl; 36 // enqueue floating-point values onto doubleQueue for ( int j = 0; j< 4; j++ ) { doubleQueue.enqueue( value ); doubleQueue.printQueue(); value += 1.1; 42 } // end for 44 fig17_14.cpp (2 of 3)

706 45 // dequeue floating-point values from doubleQueue
double dequeueDouble; 47 while ( !doubleQueue.isQueueEmpty() ) { doubleQueue.dequeue( dequeueDouble ); cout << dequeueDouble << " dequeued" << endl; doubleQueue.printQueue(); 52 } // end while 54 return 0; 56 57 } // end main fig17_14.cpp (3 of 3)

707 fig17_14.cpp output (1 of 2) processing an integer Queue
The list is: 0 The list is: 0 1 The list is: 0 1 2 The list is: 0 dequeued The list is: 1 2 3 1 dequeued The list is: 2 3 2 dequeued The list is: 3 3 dequeued The list is empty processing a double Queue The list is: 1.1 The list is: fig17_14.cpp output (1 of 2)

708 fig17_14.cpp output (2 of 2) The list is: 1.1 2.2 3.3
The list is: 1.1 dequeued The list is: 2.2 dequeued The list is: 3.3 dequeued The list is: 4.4 4.4 dequeued The list is empty All nodes destroyed fig17_14.cpp output (2 of 2)

709 Linear data structures Trees
Lists, queues, stacks Trees Nonlinear, two-dimensional Tree nodes have 2 or more links Binary trees have exactly 2 links/node None, both, or one link can be null

710 Trees Terminology Root node: first node on tree
Link refers to child of node Left child is root of left subtree Right child is root of right subtree Leaf node: node with no children Trees drawn from root downwards B A D C

711 Trees Binary search tree 47 25 77 11 43 65 93 68 7 17 31 44
Values in left subtree less than parent node Values in right subtree greater than parent Does not allow duplicate values (good way to remove them) Fast searches, log2n comparisons for a balanced tree 47 25 77 11 43 65 93 68 7 17 31 44

712 Trees Inserting nodes Use recursive function Begin at root
If current node empty, insert new node here (base case) Otherwise, If value > node, insert into right subtree If value < node, insert into left subtree If neither > nor <, must be = Ignore duplicate

713 Trees Tree traversals In-order (print tree values from least to greatest) Traverse left subtree (call function again) Print node Traverse right subtree Preorder Traverse left subtree Postorder Traverse rigth subtree

714 Trees Upcoming program Create 2 template classes TreeNode Tree data
leftPtr rightPtr Tree rootPtr Functions InsertNode inOrderTraversal preOrderTraversal postOrderTraversal

715 Binary trees have two pointers.
// Fig : treenode.h // Template TreeNode class definition. #ifndef TREENODE_H #define TREENODE_H 5 // forward declaration of class Tree template< class NODETYPE > class Tree; 8 template< class NODETYPE > 10 class TreeNode { friend class Tree< NODETYPE >; 12 13 public: 14 // constructor TreeNode( const NODETYPE &d ) : leftPtr( 0 ), data( d ), rightPtr( 0 ) { // empty body 22 } // end TreeNode constructor 24 treenode.h (1 of 2) Binary trees have two pointers.

716 treenode.h (2 of 2) 25 // return copy of node's data
NODETYPE getData() const { return data; 29 } // end getData function 31 32 private: TreeNode< NODETYPE > *leftPtr; // pointer to left subtree NODETYPE data; TreeNode< NODETYPE > *rightPtr; // pointer to right subtree 36 37 }; // end class TreeNode 38 39 #endif treenode.h (2 of 2)

717 tree.h (1 of 6) 1 // Fig. 17.18: tree.h
// Template Tree class definition. #ifndef TREE_H #define TREE_H 5 #include <iostream> 7 using std::endl; 9 10 #include <new> 11 #include "treenode.h" 12 13 template< class NODETYPE > 14 class Tree { 15 16 public: Tree(); void insertNode( const NODETYPE & ); void preOrderTraversal() const; void inOrderTraversal() const; void postOrderTraversal() const; 22 23 private: TreeNode< NODETYPE > *rootPtr; 25 tree.h (1 of 6)

718 tree.h (2 of 6) 26 // utility functions 27 void insertNodeHelper(
TreeNode< NODETYPE > **, const NODETYPE & ); void preOrderHelper( TreeNode< NODETYPE > * ) const; void inOrderHelper( TreeNode< NODETYPE > * ) const; void postOrderHelper( TreeNode< NODETYPE > * ) const; 32 33 }; // end class Tree 34 35 // constructor 36 template< class NODETYPE > 37 Tree< NODETYPE >::Tree() 38 { rootPtr = 0; 40 41 } // end Tree constructor 42 43 // insert node in Tree 44 template< class NODETYPE > 45 void Tree< NODETYPE >::insertNode( const NODETYPE &value ) 46 { insertNodeHelper( &rootPtr, value ); 48 49 } // end function insertNode 50 tree.h (2 of 6)

719 If less, insert into left subtree.
51 // utility function called by insertNode; receives a pointer 52 // to a pointer so that the function can modify pointer's value 53 template< class NODETYPE > 54 void Tree< NODETYPE >::insertNodeHelper( TreeNode< NODETYPE > **ptr, const NODETYPE &value ) 56 { // subtree is empty; create new TreeNode containing value if ( *ptr == 0 ) *ptr = new TreeNode< NODETYPE >( value ); 60 else // subtree is not empty 62 // data to insert is less than data in current node if ( value < ( *ptr )->data ) insertNodeHelper( &( ( *ptr )->leftPtr ), value ); 66 else 68 // data to insert is greater than data in current node if ( value > ( *ptr )->data ) insertNodeHelper( &( ( *ptr )->rightPtr ), value ); 72 else // duplicate data value ignored cout << value << " dup" << endl; 75 76 } // end function insertNodeHelper tree.h (3 of 6) Recursive function to insert a new node. If the current node is empty, insert the new node here. If new value greater than current node (ptr), insert into right subtree. If less, insert into left subtree. If neither case applies, node is a duplicate -- ignore.

720 Preorder: print, left, right
77 78 // begin preorder traversal of Tree 79 template< class NODETYPE > 80 void Tree< NODETYPE >::preOrderTraversal() const 81 { preOrderHelper( rootPtr ); 83 84 } // end function preOrderTraversal 85 86 // utility function to perform preorder traversal of Tree 87 template< class NODETYPE > 88 void Tree< NODETYPE >::preOrderHelper( TreeNode< NODETYPE > *ptr ) const 90 { if ( ptr != 0 ) { cout << ptr->data << ' '; // process node preOrderHelper( ptr->leftPtr ); // go to left subtree preOrderHelper( ptr->rightPtr ); // go to right subtree 95 } // end if 97 98 } // end function preOrderHelper 99 tree.h (4 of 6) Preorder: print, left, right

721 In order: left, print, right
100 // begin inorder traversal of Tree 101 template< class NODETYPE > 102 void Tree< NODETYPE >::inOrderTraversal() const 103 { inOrderHelper( rootPtr ); 105 106 } // end function inOrderTraversal 107 108 // utility function to perform inorder traversal of Tree 109 template< class NODETYPE > 110 void Tree< NODETYPE >::inOrderHelper( TreeNode< NODETYPE > *ptr ) const 112 { if ( ptr != 0 ) { inOrderHelper( ptr->leftPtr ); // go to left subtree cout << ptr->data << ' '; // process node inOrderHelper( ptr->rightPtr ); // go to right subtree 117 } // end if 119 120 } // end function inOrderHelper 121 tree.h (5 of 6) In order: left, print, right

722 Postorder: left, right, print
122 // begin postorder traversal of Tree 123 template< class NODETYPE > 124 void Tree< NODETYPE >::postOrderTraversal() const 125 { postOrderHelper( rootPtr ); 127 128 } // end function postOrderTraversal 129 130 // utility function to perform postorder traversal of Tree 131 template< class NODETYPE > 132 void Tree< NODETYPE >::postOrderHelper( TreeNode< NODETYPE > *ptr ) const 134 { if ( ptr != 0 ) { postOrderHelper( ptr->leftPtr ); // go to left subtree postOrderHelper( ptr->rightPtr ); // go to right subtree cout << ptr->data << ' '; // process node 139 } // end if 141 142 } // end function postOrderHelper 143 144 #endif tree.h (6 of 6) Postorder: left, right, print

723 fig17_19.cpp (1 of 3) 1 // Fig. 17.19: fig17_19.cpp
// Tree class test program. #include <iostream> 4 using std::cout; using std::cin; using std::fixed; 8 #include <iomanip> 10 using std::setprecision; 11 12 #include "tree.h" // Tree class definition 13 14 int main() 15 { Tree< int > intTree; // create Tree of int values int intValue; 18 cout << "Enter 10 integer values:\n"; 20 for( int i = 0; i < 10; i++ ) { cin >> intValue; intTree.insertNode( intValue ); 24 } // end for fig17_19.cpp (1 of 3)

724 fig17_19.cpp (2 of 3) 26 27 cout << "\nPreorder traversal\n";
intTree.preOrderTraversal(); 29 cout << "\nInorder traversal\n"; intTree.inOrderTraversal(); 32 cout << "\nPostorder traversal\n"; intTree.postOrderTraversal(); 35 Tree< double > doubleTree; // create Tree of double values double doubleValue; 38 cout << fixed << setprecision( 1 ) << "\n\n\nEnter 10 double values:\n"; 41 for ( int j = 0; j < 10; j++ ) { cin >> doubleValue; doubleTree.insertNode( doubleValue ); 45 } // end for 47 cout << "\nPreorder traversal\n"; doubleTree.preOrderTraversal(); 50 fig17_19.cpp (2 of 3)

725 fig17_19.cpp (3 of 3) 51 cout << "\nInorder traversal\n";
doubleTree.inOrderTraversal(); 53 cout << "\nPostorder traversal\n"; doubleTree.postOrderTraversal(); 56 cout << endl; 58 return 0; 60 61 } // end main fig17_19.cpp (3 of 3)

726 fig17_19.cpp output (1 of 1) Enter 10 integer values:
Preorder traversal Inorder traversal Postorder traversal Enter 10 double values: fig17_19.cpp output (1 of 1)

727 IS 0020 Program Design and Software Tools
Exception Handling, File Processing Lecture 11 March 30, 2004

728 Introduction Exceptions Exception Handling
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

729 Exception-Handling Overview
Consider pseudocode Perform a task If the preceding task did not execute correctly Perform error processing Perform next task Mixing logic and error handling Can make program difficult to read/debug Exception handling removes error correction from "main line" of program

730 Exception-Handling Overview
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

731 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

732 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, 13.8) If no exception Program skips catch blocks

733 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

734 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

735 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

736 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

737 // Fig. 13.1: fig13_01.cpp // A simple exception-handling example that checks for // divide-by-zero exceptions. #include <iostream> 5 using std::cout; using std::cin; 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 // constructor specifies default error message DivideByZeroException::DivideByZeroException() : exception( "attempted to divide by zero" ) {} 23 24 }; // end class DivideByZeroException 25 fig13_01.cpp (1 of 3) Define new exception class (inherit from runtime_error ). Pass a descriptive message to the constructor.

738 If the denominator is zero, throw a DivideByZeroException object.
26 // perform division and throw DivideByZeroException object if 27 // divide-by-zero exception occurs 28 double quotient( int numerator, int denominator ) 29 { // throw DivideByZeroException if trying to divide by zero if ( denominator == 0 ) throw DivideByZeroException(); // terminate function 33 // return division result return static_cast< double >( numerator ) / denominator; 36 37 } // end function quotient 38 39 int main() 40 { int number1; // user-specified numerator int number2; // user-specified denominator double result; // result of division 44 cout << "Enter two integers (end-of-file to end): "; 46 fig13_01.cpp (2 of 3) If the denominator is zero, throw a DivideByZeroException object.

739 Member function what returns the string describing the exception.
// enable user to enter two integers to divide while ( cin >> number1 >> number2 ) { 49 // try block contains code that might throw exception // and code that should not execute if an exception occurs try { result = quotient( number1, number2 ); cout << "The quotient is: " << result << endl; 55 } // end try 57 // exception handler handles a divide-by-zero exception catch ( DivideByZeroException &divideByZeroException ) { cout << "Exception occurred: " << divideByZeroException.what() << endl; 62 } // end catch 64 cout << "\nEnter two integers (end-of-file to end): "; 66 } // end while 68 cout << endl; 70 return 0; // terminate normally 72 73 } // end main fig13_01.cpp (3 of 3) 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.

740 Enter two integers (end-of-file to end): 100 7
The quotient is: 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 fig13_01.cpp output (1 of 1)

741 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

742 // Fig. 13.2: fig13_02.cpp // Demonstrating exception rethrowing. #include <iostream> 4 using std::cout; using std::endl; 7 #include <exception> 9 10 using std::exception; 11 12 // throw, catch and rethrow exception 13 void throwException() 14 { // throw exception and catch it immediately try { cout << " Function throwException throws an exception\n"; throw exception(); // generate exception 19 } // end try 21 // handle exception catch ( exception &caughtException ) { cout << " Exception handled in function throwException" << "\n Function throwException rethrows exception"; 26 throw; // rethrow exception for further processing 28 } // end catch fig13_02.cpp (1 of 2) Exception handler generates a default exception (base class exception). It immediately catches and rethrows it (note use of throw;).

743 30 cout << "This also should not print\n"; 32 33 } // end function throwException 34 35 int main() 36 { // throw exception try { cout << "\nmain invokes function throwException\n"; throwException(); cout << "This should not print\n"; 42 } // end try 44 // handle exception catch ( exception &caughtException ) { cout << "\n\nException handled in main\n"; 48 } // end catch 50 cout << "Program control continues after catch in main\n"; 52 return 0; 54 55 } // end main This should never be reached, since the throw immediately exits the function. fig13_02.cpp (2 of 2) throwException rethrows an exception to main. It is caught and handled.

744 fig13_02.cpp output (1 of 1) 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 fig13_02.cpp output (1 of 1)

745 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

746 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

747 If exception thrown but not caught
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

748 // Fig. 13.3: fig13_03.cpp // Demonstrating stack unwinding. #include <iostream> 4 using std::cout; using std::endl; 7 #include <stdexcept> 9 10 using std::runtime_error; 11 12 // function3 throws run-time error 13 void function3() throw ( runtime_error ) 14 { throw runtime_error( "runtime_error in function3" ); // fourth 16 } 17 18 // function2 invokes function3 19 void function2() throw ( runtime_error ) 20 { function3(); // third 22 } 23 fig13_03.cpp (1 of 2) Note the use of the throw list. Throws a runtime error exception, defined in <stdexcept>.

749 24 // function1 invokes function2
25 void function1() throw ( runtime_error ) 26 { function2(); // second 28 } 29 30 // demonstrate stack unwinding 31 int main() 32 { // invoke function1 try { function1(); // first 36 } // end try 38 // handle run-time error catch ( runtime_error &error ) // fifth { cout << "Exception occurred: " << error.what() << endl; 43 } // end catch 45 return 0; 47 48 } // end main fig13_03.cpp (2 of 2) function1 calls function2 which calls function3. The exception occurs, and unwinds until an appropriate try/catch block can be found. Exception occurred: runtime_error in function3

750 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

751 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

752 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

753 Demonstrating new that returns 0 on allocation failure.
// Fig. 13.4: fig13_04.cpp // Demonstrating pre-standard new returning 0 when memory // is not allocated. #include <iostream> 5 using std::cout; 7 int main() { double *ptr[ 50 ]; 11 // allocate memory for ptr for ( int i = 0; i < 50; i++ ) { ptr[ i ] = new double[ ]; 15 // new returns 0 on failure to allocate memory if ( ptr[ i ] == 0 ) { cout << "Memory allocation failed for ptr[ " << i << " ]\n"; 20 break; 22 } // end if 24 fig13_04.cpp (1 of 2) Demonstrating new that returns 0 on allocation failure.

754 fig13_04.cpp (2 of 2) fig13_04.cpp output (1 of 1)
// successful memory allocation else cout << "Allocated doubles in ptr[ " << i << " ]\n"; 29 } // end for 31 return 0; 33 34 } // end main fig13_04.cpp (2 of 2) fig13_04.cpp output (1 of 1) Allocated doubles in ptr[ 0 ] Allocated doubles in ptr[ 1 ] Allocated doubles in ptr[ 2 ] Allocated doubles in ptr[ 3 ] Memory allocation failed for ptr[ 4 ]

755 Demonstrating new that throws an exception.
// Fig. 13.5: fig13_05.cpp // Demonstrating standard new throwing bad_alloc when memory // cannot be allocated. #include <iostream> 5 using std::cout; using std::endl; 8 #include <new> // standard operator new 10 11 using std::bad_alloc; 12 13 int main() 14 { double *ptr[ 50 ]; 16 // attempt to allocate memory try { 19 // allocate memory for ptr[ i ]; new throws bad_alloc 21 // on failure for ( int i = 0; i < 50; i++ ) { ptr[ i ] = new double[ ]; cout << "Allocated doubles in ptr[ " << i << " ]\n"; } 27 } // end try fig13_05.cpp (1 of 2) Demonstrating new that throws an exception.

756 fig13_05.cpp (2 of 2) fig13_05.cpp output (1 of 1)
29 // handle bad_alloc exception catch ( bad_alloc &memoryAllocationException ) { cout << "Exception occurred: " << memoryAllocationException.what() << endl; 34 } // end catch 36 return 0; 38 39 } // end main fig13_05.cpp (2 of 2) fig13_05.cpp output (1 of 1) Allocated doubles in ptr[ 0 ] Allocated doubles in ptr[ 1 ] Allocated doubles in ptr[ 2 ] Allocated doubles in ptr[ 3 ] Exception occurred: Allocation Failure

757 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

758 The custom handler must take no arguments and return void.
// Fig. 13.6: fig13_06.cpp // Demonstrating set_new_handler. #include <iostream> 4 using std::cout; using std::cerr; 7 #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 { cerr << "customNewHandler was called"; abort(); 18 } 19 20 // using set_new_handler to handle failed memory allocation 21 int main() 22 { double *ptr[ 50 ]; 24 fig13_06.cpp (1 of 2) The custom handler must take no arguments and return void.

759 fig13_06.cpp (2 of 2) fig13_06.cpp output (1 of 1)
// specify that customNewHandler should be called on failed // memory allocation set_new_handler( customNewHandler ); 28 // allocate memory for ptr[ i ]; customNewHandler will be // called on failed memory allocation for ( int i = 0; i < 50; i++ ) { ptr[ i ] = new double[ ]; 33 cout << "Allocated doubles in ptr[ " << i << " ]\n"; 36 } // end for 38 return 0; 40 41 } // end main Note call to set_new_handler. fig13_06.cpp (2 of 2) fig13_06.cpp output (1 of 1) Allocated doubles in ptr[ 0 ] Allocated doubles in ptr[ 1 ] Allocated doubles in ptr[ 2 ] Allocated doubles in ptr[ 3 ] customNewHandler was called

760 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

761 fig13_07.cpp (1 of 3) 1 // Fig. 13.7: fig13_07.cpp
// Demonstrating auto_ptr. #include <iostream> 4 using std::cout; using std::endl; 7 #include <memory> 9 10 using std::auto_ptr; // auto_ptr class definition 11 12 class Integer { 13 14 public: 15 // Integer constructor Integer( int i = 0 ) : value( i ) { cout << "Constructor for Integer " << value << endl; 21 } // end Integer constructor 23 fig13_07.cpp (1 of 3)

762 fig13_07.cpp (2 of 3) 24 // Integer destructor 25 ~Integer() 26 {
{ cout << "Destructor for Integer " << value << endl; 28 } // end Integer destructor 30 // function to set Integer void setInteger( int i ) { value = i; 35 } // end function setInteger 37 // function to return Integer int getInteger() const { return value; 42 } // end function getInteger 44 45 private: int value; 47 48 }; // end class Integer 49 fig13_07.cpp (2 of 3)

763 Create an auto_ptr. It can be manipulated like a regular pointer.
50 // use auto_ptr to manipulate Integer object 51 int main() 52 { cout << "Creating an auto_ptr object that points to an " << "Integer\n"; 55 // "aim" auto_ptr at Integer object auto_ptr< Integer > ptrToInteger( new Integer( 7 ) ); 58 cout << "\nUsing the auto_ptr to manipulate the Integer\n"; 60 // use auto_ptr to set Integer value ptrToInteger->setInteger( 99 ); 63 // use auto_ptr to get Integer value cout << "Integer after setInteger: " << ( *ptrToInteger ).getInteger() << "\n\nTerminating program" << endl; 68 return 0; 70 71 } // end main Create an auto_ptr. It can be manipulated like a regular pointer. fig13_07.cpp (3 of 3) delete not explicitly called, but the auto_ptr will be destroyed once it leaves scope. Thus, the destructor for class Integer will be called.

764 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 fig13_07.cpp output (1 of 1)

765 Standard Library 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

766

767 Introduction Storage of data In this chapter
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

768 From smallest to largest
The Data Hierarchy From smallest to largest Bit (binary digit) 1 or 0 Everything in computer ultimately represented as bits Cumbersome for humans to use 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) Also Unicode for large character sets (wchar_t)

769 From smallest to largest (continued)
The Data Hierarchy 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…

770 The Data Hierarchy 1 01001010 Judy Green Sally Black Tom Blue Iris
Orange Randy Red File Record Field Byte (ASCII character J) Bit

771 C++ views file as sequence of bytes
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 3 1 2 4 5 8 9 ... n-1 end-of-file marker 6 7

772 To perform file processing
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)

773 Files and Streams Opening files Create objects from template
Derive from stream classes Can use stream methods from Ch. 12 put, get, peek, etc. basic_fstream basic_ios basic_ifstream basic_ofstream basic_iostream basic_istream basic_ostream

774 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);

775 Creating a Sequential-Access File
File-open modes ofstream opened for output by default ofstream outClientFile( "clients.dat", ios::out ); ofstream outClientFile( "clients.dat");

776 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 when failbit or badbit set, otherwise nonzero failbit set when EOF found while ( cin >> myVariable ) Implicitly converts cin to pointer Loops until EOF

777 Creating a Sequential-Access File
Operations Writing to file (just like cout) outClientFile << myVariable Closing file outClientFile.close() Automatically closed when destructor called

778 Notice the the header files required for file I/O.
// Fig. 14.4: fig14_04.cpp // Create a sequential file. #include <iostream> 4 using std::cout; using std::cin; using std::ios; using std::cerr; using std::endl; 10 11 #include <fstream> 12 13 using std::ofstream; 14 15 #include <cstdlib> // exit prototype 16 17 int main() 18 { // ofstream constructor opens file ofstream outClientFile( "clients.dat", ios::out ); 21 // exit program if unable to create file if ( !outClientFile ) { // overloaded ! operator cerr << "File could not be opened" << endl; exit( 1 ); 26 } // end if Notice the the header files required for file I/O. fig14_04.cpp (1 of 2) 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.

779 Write data to file like a regular stream.
28 cout << "Enter the account, name, and balance." << endl << "Enter end-of-file to end input.\n? "; 31 int account; char name[ 30 ]; double balance; 35 // read account, name and balance from cin, then place in file while ( cin >> account >> name >> balance ) { outClientFile << account << ' ' << name << ' ' << balance << endl; cout << "? "; 41 } // end while 43 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. fig14_04.cpp (2 of 2) Write data to file like a regular stream. File closed when destructor called for object. Can be explicitly closed with close().

780 fig14_04.cpp output (1 of 1) Enter the account, name, and balance.
Enter end-of-file to end input. ? 100 Jones 24.98 ? 200 Doe ? 300 White 0.00 ? 400 Stone ? 500 Rich ? ^Z fig14_04.cpp output (1 of 1)

781 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)

782 fig14_07.cpp (1 of 3) 1 // Fig. 14.7: fig14_07.cpp
// Reading and printing a sequential file. #include <iostream> 4 using std::cout; using std::cin; using std::ios; using std::cerr; using std::endl; 10 using std::left; 11 using std::right; 12 using std::fixed; 13 using std::showpoint; 14 15 #include <fstream> 16 17 using std::ifstream; 18 19 #include <iomanip> 20 21 using std::setw; 22 using std::setprecision; 23 24 #include <cstdlib> // exit prototype 25 26 void outputLine( int, const char * const, double ); 27 fig14_07.cpp (1 of 3)

783 Open and test file for input.
28 int main() 29 { // ifstream constructor opens the file ifstream inClientFile( "clients.dat", ios::in ); 32 // exit program if ifstream could not open file if ( !inClientFile ) { cerr << "File could not be opened" << endl; exit( 1 ); 37 } // end if 39 int account; char name[ 30 ]; double balance; 43 cout << left << setw( 10 ) << "Account" << setw( 13 ) << "Name" << "Balance" << endl << fixed << showpoint; 46 // display each record in file while ( inClientFile >> account >> name >> balance ) outputLine( account, name, balance ); 50 return 0; // ifstream destructor closes the file 52 53 } // end main Open and test file for input. fig14_07.cpp (2 of 3) Read from file until EOF found.

784 fig14_07.cpp (3 of 3) fig14_07.cpp output (1 of 1)
54 55 // display single record from file 56 void outputLine( int account, const char * const name, double balance ) 58 { cout << left << setw( 10 ) << account << setw( 13 ) << name << setw( 7 ) << setprecision( 2 ) << right << balance << endl; 62 63 } // end function outputLine fig14_07.cpp (3 of 3) fig14_07.cpp output (1 of 1) Account Name Balance Jones Doe White Stone Rich

785 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

786 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

787 Reading Data from a Sequential-Access File
To find pointer location tellg and tellp location = fileObject.tellg() Upcoming example Credit manager program List accounts with zero balance, credit, and debit

788 fig14_08.cpp (1 of 6) 1 // Fig. 14.8: fig14_08.cpp
// Credit-inquiry program. #include <iostream> 4 using std::cout; using std::cin; using std::ios; using std::cerr; using std::endl; 10 using std::fixed; 11 using std::showpoint; 12 using std::left; 13 using std::right; 14 15 #include <fstream> 16 17 using std::ifstream; 18 19 #include <iomanip> 20 21 using std::setw; 22 using std::setprecision; 23 24 #include <cstdlib> 25 fig14_08.cpp (1 of 6)

789 26 enum RequestType { ZERO_BALANCE = 1, CREDIT_BALANCE,
DEBIT_BALANCE, END }; 28 int getRequest(); 29 bool shouldDisplay( int, double ); 30 void outputLine( int, const char * const, double ); 31 32 int main() 33 { // ifstream constructor opens the file ifstream inClientFile( "clients.dat", ios::in ); 36 // exit program if ifstream could not open file if ( !inClientFile ) { cerr << "File could not be opened" << endl; exit( 1 ); 41 } // end if 43 int request; int account; char name[ 30 ]; double balance; 48 // get user's request (e.g., zero, credit or debit balance) request = getRequest(); 51 fig14_08.cpp (2 of 6)

790 fig14_08.cpp (3 of 6) 52 // process user's request
while ( request != END ) { 54 switch ( request ) { 56 case ZERO_BALANCE: cout << "\nAccounts with zero balances:\n"; break; 60 case CREDIT_BALANCE: cout << "\nAccounts with credit balances:\n"; break; 64 case DEBIT_BALANCE: cout << "\nAccounts with debit balances:\n"; break; 68 } // end switch 70 fig14_08.cpp (3 of 6)

791 71 // read account, name and balance from file
inClientFile >> account >> name >> balance; 73 // display file contents (until eof) while ( !inClientFile.eof() ) { 76 // display record if ( shouldDisplay( request, balance ) ) outputLine( account, name, balance ); 80 // read account, name and balance from file inClientFile >> account >> name >> balance; 83 } // end inner while 85 inClientFile.clear(); // reset eof for next input inClientFile.seekg( 0 ); // move to beginning of file request = getRequest(); // get additional request from user 89 } // end outer while 91 cout << "End of run." << endl; 93 return 0; // ifstream destructor closes the file 95 96 } // end main fig14_08.cpp (4 of 6) Use clear to reset eof. Use seekg to set file position pointer to beginning of file.

792 fig14_08.cpp (5 of 6) 97 98 // obtain request from user
99 int getRequest() 100 { int request; 102 // display request options cout << "\nEnter request" << endl << " 1 - List accounts with zero balances" << endl << " 2 - List accounts with credit balances" << endl << " 3 - List accounts with debit balances" << endl << " 4 - End of run" << fixed << showpoint; 109 // input user request do { cout << "\n? "; cin >> request; 114 } while ( request < ZERO_BALANCE && request > END ); 116 return request; 118 119 } // end function getRequest 120 fig14_08.cpp (5 of 6)

793 fig14_08.cpp (6 of 6) 121 // determine whether to display given record
122 bool shouldDisplay( int type, double balance ) 123 { // determine whether to display credit balances if ( type == CREDIT_BALANCE && balance < 0 ) return true; 127 // determine whether to display debit balances if ( type == DEBIT_BALANCE && balance > 0 ) return true; 131 // determine whether to display zero balances if ( type == ZERO_BALANCE && balance == 0 ) return true; 135 return false; 137 138 } // end function shouldDisplay 139 140 // display single record from file 141 void outputLine( int account, const char * const name, double balance ) 143 { cout << left << setw( 10 ) << account << setw( 13 ) << name << setw( 7 ) << setprecision( 2 ) << right << balance << endl; 147 148 } // end function outputLine fig14_08.cpp (6 of 6)

794 fig14_08.cpp output (1 of 2) Enter request
1 - List accounts with zero balances 2 - List accounts with credit balances 3 - List accounts with debit balances 4 - End of run ? 1 Accounts with zero balances: White ? 2 Accounts with credit balances: Stone fig14_08.cpp output (1 of 2)

795 fig14_08.cpp output (2 of 2) Enter request
1 - List accounts with zero balances 2 - List accounts with credit balances 3 - List accounts with debit balances 4 - End of run ? 3 Accounts with debit balances: Jones Doe Rich ? 4 End of run. fig14_08.cpp output (2 of 2)

796 Updating Sequential-Access Files
Updating sequential files Risk overwriting other data Example: change name "White" to "Worthington" Old data 300 White Jones 32.87 Insert new data Formatted text different from internal representation Problem can be avoided, but awkward 300 Worthington 0.00 300 White Jones 32.87 Data gets overwritten 300 Worthington 0.00ones 32.87

797 Random-access files are solution
Instant access Want to locate record quickly Airline reservations, ATMs Sequential files must search through each one Random-access files are solution Insert record without destroying other data Update/delete items without changing other data

798 C++ imposes no structure on files
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

799 Creating a Random-Access File
" " (char *) vs (int) char * takes 8 bytes (1 for each character + null) int takes fixed number of bytes (perhaps 4) 123 same size in bytes as << 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 *

800 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

801 Creating a Random-Access File
Usually write entire struct or object to file Problem statement Credit processing program Store at most 100 fixed-length records Record Account number (key) First and last name Balance Account operations Update, create new, delete, list all accounts in a file Next: program to create blank 100-record file

802 // Fig. 14.10: clientData.h // Class ClientData definition used in Fig. 14.12–Fig. 14.15. #ifndef CLIENTDATA_H #define CLIENTDATA_H 5 #include <iostream> 7 using std::string; 9 10 class ClientData { 11 12 public: 13 // default ClientData constructor ClientData( int = 0, string = "", string = "", double = 0.0 ); 16 // accessor functions for accountNumber void setAccountNumber( int ); int getAccountNumber() const; 20 // accessor functions for lastName void setLastName( string ); string getLastName() const; 24 Class ClientData stores the information for each person. 100 blank ClientData objects will be written to a file. clientData.h (1 of 2)

803 25 // accessor functions for firstName
void setFirstName( string ); string getFirstName() const; 28 // accessor functions for balance void setBalance( double ); double getBalance() const; 32 33 private: int accountNumber; char lastName[ 15 ]; char firstName[ 10 ]; double balance; 38 39 }; // end class ClientData 40 41 #endif clientData.h (2 of 2) Put limits on the size of the first and last name. accountNumber (an int) and balance (double) are already of a fixed size.

804 ClientData.cpp (1 of 4) 1 // Fig. 14.11: ClientData.cpp
// Class ClientData stores customer's credit information. #include <iostream> 4 using std::string; 6 #include <cstring> #include "clientData.h" 9 10 // default ClientData constructor 11 ClientData::ClientData( int accountNumberValue, string lastNameValue, string firstNameValue, double balanceValue ) 14 { setAccountNumber( accountNumberValue ); setLastName( lastNameValue ); setFirstName( firstNameValue ); setBalance( balanceValue ); 19 20 } // end ClientData constructor 21 22 // get account-number value 23 int ClientData::getAccountNumber() const 24 { return accountNumber; 26 27 } // end function getAccountNumber ClientData.cpp (1 of 4)

805 ClientData.cpp (2 of 4) 28 29 // set account-number value
30 void ClientData::setAccountNumber( int accountNumberValue ) 31 { accountNumber = accountNumberValue; 33 34 } // end function setAccountNumber 35 36 // get last-name value 37 string ClientData::getLastName() const 38 { return lastName; 40 41 } // end function getLastName 42 43 // set last-name value 44 void ClientData::setLastName( string lastNameString ) 45 { // copy at most 15 characters from string to lastName const char *lastNameValue = lastNameString.data(); int length = strlen( lastNameValue ); length = ( length < 15 ? length : 14 ); strncpy( lastName, lastNameValue, length ); 51 // append null character to lastName lastName[ length ] = '\0'; ClientData.cpp (2 of 4)

806 ClientData.cpp (3 of 4) 54 55 } // end function setLastName 56
57 // get first-name value 58 string ClientData::getFirstName() const 59 { return firstName; 61 62 } // end function getFirstName 63 64 // set first-name value 65 void ClientData::setFirstName( string firstNameString ) 66 { // copy at most 10 characters from string to firstName const char *firstNameValue = firstNameString.data(); int length = strlen( firstNameValue ); length = ( length < 10 ? length : 9 ); strncpy( firstName, firstNameValue, length ); 72 // append new-line character to firstName firstName[ length ] = '\0'; 75 76 } // end function setFirstName 77 ClientData.cpp (3 of 4)

807 ClientData.cpp (4 of 4) 78 // get balance value
79 double ClientData::getBalance() const 80 { return balance; 82 83 } // end function getBalance 84 85 // set balance value 86 void ClientData::setBalance( double balanceValue ) 87 { balance = balanceValue; 89 90 } // end function setBalance ClientData.cpp (4 of 4)

808 Open a file for raw writing using an ofstream object and ios::binary.
// Fig. 14.12: fig14_12.cpp // Creating a randomly accessed file. #include <iostream> 4 using std::cerr; using std::endl; using std::ios; 8 #include <fstream> 10 11 using std::ofstream; 12 13 #include <cstdlib> 14 #include "clientData.h" // ClientData class definition 15 16 int main() 17 { ofstream outCredit( "credit.dat", ios::binary ); 19 // exit program if ofstream could not open file if ( !outCredit ) { cerr << "File could not be opened." << endl; exit( 1 ); 24 } // end if fig14_12.cpp (1 of 2) Open a file for raw writing using an ofstream object and ios::binary.

809 26 // create ClientData with no information ClientData blankClient; 29 // output 100 blank records to file for ( int i = 0; i < 100; i++ ) outCredit.write( reinterpret_cast< const char * >( &blankClient ), sizeof( ClientData ) ); 35 return 0; 37 38 } // end main Create a blank object. Use write to output the raw data to a file (passing a pointer to the object and its size). fig14_12.cpp (2 of 2)

810 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)

811 fig14_13.cpp (1 of 4) 1 // Fig. 14.13: fig14_13.cpp
// Writing to a random access file. #include <iostream> 4 using std::cerr; using std::endl; using std::cout; using std::cin; using std::ios; 10 11 #include <iomanip> 12 13 using std::setw; 14 15 #include <fstream> 16 17 using std::ofstream; 18 19 #include <cstdlib> 20 #include "clientData.h" // ClientData class definition 21 fig14_13.cpp (1 of 4)

812 Open file for raw (binary) writing.
22 int main() 23 { int accountNumber; char lastName[ 15 ]; char firstName[ 10 ]; double balance; 28 ofstream outCredit( "credit.dat", ios::binary ); 30 // exit program if ofstream cannot open file if ( !outCredit ) { cerr << "File could not be opened." << endl; exit( 1 ); 35 } // end if 37 cout << "Enter account number " << "(1 to 100, 0 to end input)\n? "; 40 // require user to specify account number ClientData client; cin >> accountNumber; client.setAccountNumber( accountNumber ); 45 Open file for raw (binary) writing. fig14_13.cpp (2 of 4) Get account number, put into object. It has not yet been written to file.

813 Write ClientData object to file at specified position.
// user enters information, which is copied into file while ( client.getAccountNumber() > 0 && client.getAccountNumber() <= 100 ) { 49 // user enters last name, first name and balance cout << "Enter lastname, firstname, balance\n? "; cin >> setw( 15 ) >> lastName; cin >> setw( 10 ) >> firstName; cin >> balance; 55 // set record lastName, firstName and balance values client.setLastName( lastName ); client.setFirstName( firstName ); client.setBalance( balance ); 60 // seek position in file of user-specified record outCredit.seekp( ( client.getAccountNumber() - 1 ) * sizeof( ClientData ) ); 64 // write user-specified information in file outCredit.write( reinterpret_cast< const char * >( &client ), sizeof( ClientData ) ); 69 fig14_13.cpp (3 of 4) Position outCredit to the proper location in the file (based on the account number). Write ClientData object to file at specified position.

814 70 // enable user to specify another account number
cout << "Enter account number\n? "; cin >> accountNumber; client.setAccountNumber( accountNumber ); 74 } // end while 76 return 0; 78 79 } // end main fig14_13.cpp (4 of 4)

815 Notice that accounts can be created in any order.
Enter account number (1 to 100, 0 to end input) ? 37 Enter lastname, firstname, balance ? Barker Doug 0.00 Enter account number ? 29 ? Brown Nancy ? 96 ? Stone Sam 34.98 ? 88 ? Smith Dave ? 33 ? Dunn Stacey ? 0 Notice that accounts can be created in any order. fig14_13.cpp output (1 of 1)

816 Reading Data Sequentially from a Random-Access File
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 * Upcoming program Output data from a random-access file Go through each record sequentially If no data (accountNumber == 0) then skip

817 fig14_14.cpp (1 of 3) 1 // Fig. 14.14: fig14_14.cpp
// Reading a random access file. #include <iostream> 4 using std::cout; using std::endl; using std::ios; using std::cerr; using std::left; 10 using std::right; 11 using std::fixed; 12 using std::showpoint; 13 14 #include <iomanip> 15 16 using std::setprecision; 17 using std::setw; 18 19 #include <fstream> 20 21 using std::ifstream; 22 using std::ostream; 23 24 #include <cstdlib> // exit protoyype 25 #include "clientData.h" // ClientData class definition 26 fig14_14.cpp (1 of 3)

818 27 void outputLine( ostream&, const ClientData & );
28 29 int main() 30 { ifstream inCredit( "credit.dat", ios::in ); 32 // exit program if ifstream cannot open file if ( !inCredit ) { cerr << "File could not be opened." << endl; exit( 1 ); 37 } // end if 39 cout << left << setw( 10 ) << "Account" << setw( 16 ) << "Last Name" << setw( 11 ) << "First Name" << left << setw( 10 ) << right << "Balance" << endl; 43 ClientData client; // create record 45 // read first record from file inCredit.read( reinterpret_cast< char * >( &client ), sizeof( ClientData ) ); 49 fig14_14.cpp (2 of 3) Read sizeof(ClientData) bytes and put into object client. This may be an empty record.

819 50 // read all records from file
while ( inCredit && !inCredit.eof() ) { 52 // display record if ( client.getAccountNumber() != 0 ) outputLine( cout, client ); 56 // read next from file inCredit.read( reinterpret_cast< char * >( &client ), sizeof( ClientData ) ); 60 } // end while 62 return 0; 64 65 } // end main 66 67 // display single record 68 void outputLine( ostream &output, const ClientData &record ) 69 { output << left << setw( 10 ) << record.getAccountNumber() << setw( 16 ) << record.getLastName().data() << setw( 11 ) << record.getFirstName().data() << setw( 10 ) << setprecision( 2 ) << right << fixed << showpoint << record.getBalance() << endl; 75 76 } // end outputLine Loop exits if there is an error reading (inCredit == 0) or EOF is found (inCredit.eof() == 1) fig14_14.cpp (3 of 3) Output non-empty accounts. Note that outputLine takes an ostream argument. We could easily output to another file (opened with an ofstream object, which derives from ostream).

820 fig14_14.cpp output (1 of 1) Account Last Name First Name Balance
Brown Nancy Dunn Stacey Barker Doug Smith Dave Stone Sam fig14_14.cpp output (1 of 1)

821 Example: A Transaction-Processing Program
Instant access for bank accounts Use random access file (data in client.dat) Give user menu Option 1: store accounts to print.txt Option 2: update record Account Last Name First Name Balance Brown Nancy Dunn Stacey Barker Doug Smith Dave Stone Sam Enter account to update ( ): 37 Barker Doug Enter charge (+) or payment (-): Barker Doug

822 Example: A Transaction-Processing Program
Menu options (continued) Option 3: add new record Option 4: delete record To open file for reading and writing Use fstream object "Or" file-open modes together fstream inOutCredit( "credit.dat", ios::in | ios::out ); Enter new account number ( ): 22 Enter lastname, firstname, balance ? Johnston Sarah Enter account to delete ( ): 29 Account #29 deleted.

823 fig14_15.cpp (1 of 14) 1 // Fig. 14.15: fig14_15.cpp
// This program reads a random access file sequentially, updates // data previously written to the file, creates data to be placed // in the file, and deletes data previously in the file. #include <iostream> 6 using std::cout; using std::cerr; using std::cin; 10 using std::endl; 11 using std::ios; 12 using std::left; 13 using std::right; 14 using std::fixed; 15 using std::showpoint; 16 17 #include <fstream> 18 19 using std::ofstream; 20 using std::ostream; 21 using std::fstream; 22 23 #include <iomanip> 24 25 using std::setw; 26 using std::setprecision; 27 28 #include <cstdlib> // exit prototype 29 #include "clientData.h" // ClientData class definition fig14_15.cpp (1 of 14)

824 Open file for reading and writing (fstream object needed).
30 31 int enterChoice(); 32 void printRecord( fstream& ); 33 void updateRecord( fstream& ); 34 void newRecord( fstream& ); 35 void deleteRecord( fstream& ); 36 void outputLine( ostream&, const ClientData & ); 37 int getAccount( const char * const ); 38 39 enum Choices { PRINT = 1, UPDATE, NEW, DELETE, END }; 40 41 int main() 42 { // open file for reading and writing fstream inOutCredit( "credit.dat", ios::in | ios::out ); 45 // exit program if fstream cannot open file if ( !inOutCredit ) { cerr << "File could not be opened." << endl; exit ( 1 ); 50 } // end if 52 fig14_15.cpp (2 of 14) Open file for reading and writing (fstream object needed).

825 fig14_15.cpp (3 of 14) 53 int choice; 54
// enable user to specify action while ( ( choice = enterChoice() ) != END ) { 57 switch ( choice ) { 59 // create text file from record file case PRINT: printRecord( inOutCredit ); break; 64 // update record case UPDATE: updateRecord( inOutCredit ); break; 69 // create record case NEW: newRecord( inOutCredit ); break; 74 // delete existing record case DELETE: deleteRecord( inOutCredit ); break; 79 fig14_15.cpp (3 of 14)

826 Displays menu and returns user's choice.
int choice; 54 // enable user to specify action while ( ( choice = enterChoice() ) != END ) { 57 switch ( choice ) { 59 // create text file from record file case PRINT: printRecord( inOutCredit ); break; 64 // update record case UPDATE: updateRecord( inOutCredit ); break; 69 // create record case NEW: newRecord( inOutCredit ); break; 74 // delete existing record case DELETE: deleteRecord( inOutCredit ); break; 79 fig14_15.cpp (4 of 14) Displays menu and returns user's choice.

827 80 // display error if user does not select valid choice
default: cerr << "Incorrect choice" << endl; break; 84 } // end switch 86 inOutCredit.clear(); // reset end-of-file indicator 88 } // end while 90 return 0; 92 93 } // end main 94 95 // enable user to input menu choice 96 int enterChoice() 97 { // display available options cout << "\nEnter your choice" << endl << "1 - store a formatted text file of accounts" << endl << " called \"print.txt\" for printing" << endl << "2 - update an account" << endl << "3 - add a new account" << endl << "4 - delete an account" << endl << "5 - end program\n? "; fig14_15.cpp (5 of 14)

828 Output to print.txt. First, print the header for the table.
106 int menuChoice; cin >> menuChoice; // receive choice from user 109 return menuChoice; 111 112 } // end function enterChoice 113 114 // create formatted text file for printing 115 void printRecord( fstream &readFromFile ) 116 { // create text file ofstream outPrintFile( "print.txt", ios::out ); 119 // exit program if ofstream cannot create file if ( !outPrintFile ) { cerr << "File could not be created." << endl; exit( 1 ); 124 } // end if 126 outPrintFile << left << setw( 10 ) << "Account" << setw( 16 ) << "Last Name" << setw( 11 ) << "First Name" << right << setw( 10 ) << "Balance" << endl; 130 fig14_15.cpp (6 of 14) Output to print.txt. First, print the header for the table.

829 Go to front of file, read account data, and print record if not empty.
// set file-position pointer to beginning of record file readFromFile.seekg( 0 ); 133 // read first record from record file ClientData client; readFromFile.read( reinterpret_cast< char * >( &client ), sizeof( ClientData ) ); 138 // copy all records from record file into text file while ( !readFromFile.eof() ) { 141 // write single record to text file if ( client.getAccountNumber() != 0 ) outputLine( outPrintFile, client ); 145 // read next record from record file readFromFile.read( reinterpret_cast< char * >( &client ), sizeof( ClientData ) ); 149 } // end while 151 152 } // end function printRecord 153 Go to front of file, read account data, and print record if not empty. Note that outputLine takes an ostream object (base of ofstream). It can easily print to a file (as in this case) or cout. fig14_15.cpp (7 of 14)

830 154 // update balance in record
155 void updateRecord( fstream &updateFile ) 156 { // obtain number of account to update int accountNumber = getAccount( "Enter account to update" ); 159 // move file-position pointer to correct record in file updateFile.seekg( ( accountNumber - 1 ) * sizeof( ClientData ) ); 163 // read first record from file ClientData client; updateFile.read( reinterpret_cast< char * >( &client ), sizeof( ClientData ) ); 168 // update record if ( client.getAccountNumber() != 0 ) { outputLine( cout, client ); 172 // request user to specify transaction cout << "\nEnter charge (+) or payment (-): "; double transaction; // charge or payment cin >> transaction; 177 // update record balance double oldBalance = client.getBalance(); client.setBalance( oldBalance + transaction ); outputLine( cout, client ); 182 This is fstream (I/O) because we must read the old balance, update it, and write the new balance. fig14_15.cpp (8 of 14)

831 183 // move file-position pointer to correct record in file
updateFile.seekp( ( accountNumber - 1 ) * sizeof( ClientData ) ); 186 // write updated record over old record in file updateFile.write( reinterpret_cast< const char * >( &client ), sizeof( ClientData ) ); 191 } // end if 193 // display error if account does not exist else cerr << "Account #" << accountNumber << " has no information." << endl; 198 199 } // end function updateRecord 200 201 // create and insert record 202 void newRecord( fstream &insertInFile ) 203 { // obtain number of account to create int accountNumber = getAccount( "Enter new account number" ); 206 // move file-position pointer to correct record in file insertInFile.seekg( ( accountNumber - 1 ) * sizeof( ClientData ) ); fig14_15.cpp (9 of 14) This is fstream because we read to see if a non-empty record already exists. If not, we write a new record.

832 fig14_15.cpp (10 of 14) 210 211 // read record from file
ClientData client; insertInFile.read( reinterpret_cast< char * >( &client ), sizeof( ClientData ) ); 215 // create record, if record does not previously exist if ( client.getAccountNumber() == 0 ) { 218 char lastName[ 15 ]; char firstName[ 10 ]; double balance; 222 // user enters last name, first name and balance cout << "Enter lastname, firstname, balance\n? "; cin >> setw( 15 ) >> lastName; cin >> setw( 10 ) >> firstName; cin >> balance; 228 // use values to populate account values client.setLastName( lastName ); client.setFirstName( firstName ); client.setBalance( balance ); client.setAccountNumber( accountNumber ); 234 fig14_15.cpp (10 of 14)

833 235 // move file-position pointer to correct record in file
insertInFile.seekp( ( accountNumber - 1 ) * sizeof( ClientData ) ); 238 // insert record in file insertInFile.write( reinterpret_cast< const char * >( &client ), sizeof( ClientData ) ); 243 } // end if 245 // display error if account previously exists else cerr << "Account #" << accountNumber << " already contains information." << endl; 250 251 } // end function newRecord 252 fig14_15.cpp (11 of 14)

834 253 // delete an existing record
254 void deleteRecord( fstream &deleteFromFile ) 255 { // obtain number of account to delete int accountNumber = getAccount( "Enter account to delete" ); 258 // move file-position pointer to correct record in file deleteFromFile.seekg( ( accountNumber - 1 ) * sizeof( ClientData ) ); 262 // read record from file ClientData client; deleteFromFile.read( reinterpret_cast< char * >( &client ), sizeof( ClientData ) ); 267 // delete record, if record exists in file if ( client.getAccountNumber() != 0 ) { ClientData blankClient; 271 // move file-position pointer to correct record in file deleteFromFile.seekp( ( accountNumber - 1 ) * sizeof( ClientData ) ); 275 fstream because we read to check if the account exits. If it does, we write blank data (erase it). If it does not exist, there is no need to delete it. fig14_15.cpp (12 of 14)

835 276 // replace existing record with blank record
deleteFromFile.write( reinterpret_cast< const char * >( &blankClient ), sizeof( ClientData ) ); 280 cout << "Account #" << accountNumber << " deleted.\n"; 282 } // end if 284 // display error if record does not exist else cerr << "Account #" << accountNumber << " is empty.\n"; 288 289 } // end deleteRecord 290 291 // display single record 292 void outputLine( ostream &output, const ClientData &record ) 293 { output << left << setw( 10 ) << record.getAccountNumber() << setw( 16 ) << record.getLastName().data() << setw( 11 ) << record.getFirstName().data() << setw( 10 ) << setprecision( 2 ) << right << fixed << showpoint << record.getBalance() << endl; 299 300 } // end function outputLine 301 fig14_15.cpp (13 of 14) outputLine is very flexible, and can output to any ostream object (such as a file or cout).

836 fig14_15.cpp (14 of 14) 302 // obtain account-number value from user
303 int getAccount( const char * const prompt ) 304 { int accountNumber; 306 // obtain account-number value do { cout << prompt << " ( ): "; cin >> accountNumber; 311 } while ( accountNumber < 1 || accountNumber > 100 ); 313 return accountNumber; 315 316 } // end function getAccount fig14_15.cpp (14 of 14)

837 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)

838 IS 0020 Program Design and Software Tools
Standard Template Library Lecture 12 April 6, 2004

839 Introduction to the Standard Template Library (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

840 21.1.1 Introduction to Containers
Three types of containers Sequence containers Linear data structures (vectors, linked lists) First-class container Associative containers Non-linear, can find elements quickly Key/value pairs Container adapters Near containers Similar to containers, with reduced functionality Containers have some common functions

841 STL Container Classes (Fig. 21.1)
Sequence containers vector deque list Associative containers set multiset map multimap Container adapters stack queue priority_queue

842 Common STL Member Functions (Fig. 21.2)
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

843 Common STL typedefs (Fig. 21.4)
typedefs for first-class containers value_type reference const_reference pointer iterator const_iterator reverse_iterator const_reverse_iterator difference_type size_type

844 21.1.2 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

845 21.1.2 Introduction to 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

846 Access and assign the iterator like a pointer.
// Fig. 21.5: fig21_05.cpp // Demonstrating input and output with iterators. #include <iostream> 4 using std::cout; using std::cin; using std::endl; 8 #include <iterator> // ostream_iterator and istream_iterator 10 11 int main() 12 { cout << "Enter two integers: "; 14 // create istream_iterator for reading int values from cin std::istream_iterator< int > inputInt( cin ); 17 int number1 = *inputInt; // read int from standard input inputInt; // move iterator to next input value int number2 = *inputInt; // read int from standard input 21 fig21_05.cpp (1 of 2) Note creation of istream_iterator. For compilation reasons, we use std:: rather than a using statement. Access and assign the iterator like a pointer.

847 fig21_05.cpp (2 of 2) fig21_05.cpp output (1 of 1)
// create ostream_iterator for writing int values to cout std::ostream_iterator< int > outputInt( cout ); 24 cout << "The sum is: "; *outputInt = number1 + number2; // output result to cout cout << endl; 28 return 0; 30 31 } // end main fig21_05.cpp (2 of 2) fig21_05.cpp output (1 of 1) Create an ostream_iterator is similar. Assigning to this iterator outputs to cout. Enter two integers: 12 25 The sum is: 37

848 Iterator Categories (Fig. 21.6)
Input Read elements from container, can only move forward Output Write elements to container, only forward Forward Combines input and output, retains position Multi-pass (can pass through sequence twice) Bidirectional Like forward, but can move backwards as well Random access Like bidirectional, but can also jump to any element

849 Iterator Types Supported (Fig. 21.8)
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

850 Iterator Operations (Fig. 21.10)
All ++p, p++ Input iterators *p p = p1 p == p1, p != p1 Output iterators Forward iterators Have functionality of input and output iterators

851 Iterator Operations (Fig. 21.10)
Bidirectional --p, p-- Random access p + i, p += i p - i, p -= i p[i] p < p1, p <= p1 p > p1, p >= p1

852 21.1.3 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

853 Three sequence containers
vector - based on arrays deque - based on arrays list - robust linked list

854 21.2.1 vector Sequence Container
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 Has random access iterators

855 21.2.1 vector Sequence Container
Declarations std::vector <type> v; type: int, float, etc. Iterators std::vector<type>::const_iterator iterVar; const_iterator cannot modify elements 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

856 21.2.1 vector Sequence Container
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

857 21.2.1 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

858 21.2.1 vector Sequence 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

859 21.2.1 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

860 Create a vector of ints. Call member functions. fig21_14.cpp (1 of 3)
// Fig : fig21_14.cpp // Demonstrating standard library vector class template. #include <iostream> 4 using std::cout; using std::cin; using std::endl; 8 #include <vector> // vector class-template definition 10 11 // prototype for function template printVector 12 template < class T > 13 void printVector( const std::vector< T > &integers2 ); 14 15 int main() 16 { const int SIZE = 6; int array[ SIZE ] = { 1, 2, 3, 4, 5, 6 }; 19 std::vector< int > integers; 21 cout << "The initial size of integers is: " << integers.size() << "\nThe initial capacity of integers is: " << integers.capacity(); 26 fig21_14.cpp (1 of 3) Create a vector of ints. Call member functions.

861 Add elements to end of vector using push_back.
// function push_back is in every sequence collection integers.push_back( 2 ); integers.push_back( 3 ); integers.push_back( 4 ); 31 cout << "\nThe size of integers is: " << integers.size() << "\nThe capacity of integers is: " << integers.capacity(); 35 cout << "\n\nOutput array using pointer notation: "; 37 for ( int *ptr = array; ptr != array + SIZE; ++ptr ) cout << *ptr << ' '; 40 cout << "\nOutput vector using iterator notation: "; printVector( integers ); 43 cout << "\nReversed contents of vector integers: "; 45 Add elements to end of vector using push_back. fig21_14.cpp (2 of 3)

862 Walk through vector backwards using a reverse_iterator.
std::vector< int >::reverse_iterator reverseIterator; 47 for ( reverseIterator = integers.rbegin(); reverseIterator!= integers.rend(); reverseIterator ) cout << *reverseIterator << ' '; 52 cout << endl; 54 return 0; 56 57 } // end main 58 59 // function template for outputting vector elements 60 template < class T > 61 void printVector( const std::vector< T > &integers2 ) 62 { std::vector< T >::const_iterator constIterator; 64 for ( constIterator = integers2.begin(); constIterator != integers2.end(); constIterator++ ) cout << *constIterator << ' '; 69 70 } // end function printVector Walk through vector backwards using a reverse_iterator. fig21_14.cpp (3 of 3) Template function to walk through vector forwards.

863 fig21_14.cpp output (1 of 1) The initial size of v is: 0
The initial capacity of v is: 0 The size of v is: 3 The capacity of v is: 4 Contents of array a using pointer notation: Contents of vector v using iterator notation: 2 3 4 Reversed contents of vector v: 4 3 2 fig21_14.cpp output (1 of 1)

864 21.2.2 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;

865 21.2.2 list Sequence Container
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

866 21.2.2 list Sequence Container
list functions 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

867 Create two list objects.
// Fig : fig21_17.cpp // Standard library list class template test program. #include <iostream> 4 using std::cout; using std::endl; 7 #include <list> // list class-template definition #include <algorithm> // copy algorithm 10 11 // prototype for function template printList 12 template < class T > 13 void printList( const std::list< T > &listRef ); 14 15 int main() 16 { const int SIZE = 4; int array[ SIZE ] = { 2, 6, 4, 8 }; 19 std::list< int > values; std::list< int > otherValues; 22 // insert items in values values.push_front( 1 ); values.push_front( 2 ); values.push_back( 4 ); values.push_back( 3 ); fig21_17.cpp (1 of 5) Create two list objects.

868 Various list member functions.
28 cout << "values contains: "; printList( values ); 31 values.sort(); // sort values 33 cout << "\nvalues after sorting contains: "; printList( values ); 36 // insert elements of array into otherValues otherValues.insert( otherValues.begin(), array, array + SIZE ); 40 cout << "\nAfter insert, otherValues contains: "; printList( otherValues ); 43 // remove otherValues elements and insert at end of values values.splice( values.end(), otherValues ); 46 cout << "\nAfter splice, values contains: "; printList( values ); 49 values.sort(); // sort values 51 cout << "\nAfter sort, values contains: "; printList( values ); 54 Various list member functions. fig21_17.cpp (2 of 5)

869 fig21_17.cpp (3 of 5) 55 // insert elements of array into otherValues
otherValues.insert( otherValues.begin(), array, array + SIZE ); otherValues.sort(); 59 cout << "\nAfter insert, otherValues contains: "; printList( otherValues ); 62 // remove otherValues elements and insert into values // in sorted order values.merge( otherValues ); 66 cout << "\nAfter merge:\n values contains: "; printList( values ); cout << "\n otherValues contains: "; printList( otherValues ); 71 values.pop_front(); // remove element from front values.pop_back(); // remove element from back 74 cout << "\nAfter pop_front and pop_back:" << "\n values contains: "; printList( values ); 78 values.unique(); // remove duplicate elements 80 cout << "\nAfter unique, values contains: "; printList( values ); fig21_17.cpp (3 of 5)

870 fig21_17.cpp (4 of 5) 83 84 // swap elements of values and otherValues
values.swap( otherValues ); 86 cout << "\nAfter swap:\n values contains: "; printList( values ); cout << "\n otherValues contains: "; printList( otherValues ); 91 // replace contents of values with elements of otherValues values.assign( otherValues.begin(), otherValues.end() ); 94 cout << "\nAfter assign, values contains: "; printList( values ); 97 // remove otherValues elements and insert into values // in sorted order values.merge( otherValues ); 101 cout << "\nAfter merge, values contains: "; printList( values ); 104 values.remove( 4 ); // remove all 4s 106 cout << "\nAfter remove( 4 ), values contains: "; printList( values ); fig21_17.cpp (4 of 5)

871 fig21_17.cpp (5 of 5) 109 110 cout << endl; 111 112 return 0;
113 114 } // end main 115 116 // printList function template definition; uses 117 // ostream_iterator and copy algorithm to output list elements 118 template < class T > 119 void printList( const std::list< T > &listRef ) 120 { if ( listRef.empty() ) cout << "List is empty"; 123 else { std::ostream_iterator< T > output( cout, " " ); std::copy( listRef.begin(), listRef.end(), output ); 127 } // end else 129 130 } // end function printList fig21_17.cpp (5 of 5)

872 fig21_17.cpp output (1 of 1) values contains: 2 1 4 3
values after sorting contains: After insert, otherValues contains: After splice, values contains: After sort, values contains: After insert, otherValues contains: After merge: values contains: otherValues contains: List is empty After pop_front and pop_back: values contains: After unique, values contains: After swap: values contains: List is empty otherValues contains: After assign, values contains: After merge, values contains: After remove( 4 ), values contains: fig21_17.cpp output (1 of 1)

873 21.2.3 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)

874 Create a deque, use member functions.
// Fig : fig21_18.cpp // Standard library class deque test program. #include <iostream> 4 using std::cout; using std::endl; 7 #include <deque> // deque class-template definition #include <algorithm> // copy algorithm 10 11 int main() 12 { std::deque< double > values; std::ostream_iterator< double > output( cout, " " ); 15 // insert elements in values values.push_front( 2.2 ); values.push_front( 3.5 ); values.push_back( 1.1 ); 20 cout << "values contains: "; 22 // use subscript operator to obtain elements of values for ( int i = 0; i < values.size(); ++i ) cout << values[ i ] << ' '; 26 fig21_18.cpp (1 of 2) Create a deque, use member functions.

875 fig21_18.cpp (2 of 2) fig21_18.cpp output (1 of 1)
values.pop_front(); // remove first element 28 cout << "\nAfter pop_front, values contains: "; std::copy( values.begin(), values.end(), output ); 31 // use subscript operator to modify element at location 1 values[ 1 ] = 5.4; 34 cout << "\nAfter values[ 1 ] = 5.4, values contains: "; std::copy( values.begin(), values.end(), output ); 37 cout << endl; 39 return 0; 41 42 } // end main fig21_18.cpp (2 of 2) fig21_18.cpp output (1 of 1) values contains: After pop_front, values contains: After values[ 1 ] = 5.4, values contains:

876 21.3 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

877 21.3.1 multiset Associative Container
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

878 21.3.1 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

879 21.3.1 multiset Associative Container
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

880 // Fig : fig21_19.cpp // Testing Standard Library class multiset #include <iostream> 4 using std::cout; using std::endl; 7 #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 { const int SIZE = 10; int a[ SIZE ] = { 7, 22, 9, 1, 18, 30, 100, 22, 85, 13 }; 19 ims intMultiset; // ims is typedef for "integer multiset" std::ostream_iterator< int > output( cout, " " ); 22 cout << "There are currently " << intMultiset.count( 15 ) << " values of 15 in the multiset\n"; 25 fig21_19.cpp (1 of 3) typedefs help clarify program. This declares an integer multiset that stores values in ascending order.

881 Use member function find.
intMultiset.insert( 15 ); // insert 15 in intMultiset intMultiset.insert( 15 ); // insert 15 in intMultiset 28 cout << "After inserts, there are " << intMultiset.count( 15 ) << " values of 15 in the multiset\n\n"; 32 // iterator that cannot be used to change element values ims::const_iterator result; 35 // find 15 in intMultiset; find returns iterator result = intMultiset.find( 15 ); 38 if ( result != intMultiset.end() ) // if iterator not at end cout << "Found value 15\n"; // found search value 15 41 // find 20 in intMultiset; find returns iterator result = intMultiset.find( 20 ); 44 if ( result == intMultiset.end() ) // will be true hence cout << "Did not find value 20\n"; // did not find 20 47 // insert elements of array a into intMultiset intMultiset.insert( a, a + SIZE ); 50 cout << "\nAfter insert, intMultiset contains:\n"; std::copy( intMultiset.begin(), intMultiset.end(), output ); 53 fig21_19.cpp (2 of 3) Use member function find.

882 Use a pair object to get the lower and upper bound for 22.
// determine lower and upper bound of 22 in intMultiset cout << "\n\nLower bound of 22: " << *( intMultiset.lower_bound( 22 ) ); cout << "\nUpper bound of 22: " << *( intMultiset.upper_bound( 22 ) ); 59 // p represents pair of const_iterators std::pair< ims::const_iterator, ims::const_iterator > p; 62 // use equal_range to determine lower and upper bound // of 22 in intMultiset p = intMultiset.equal_range( 22 ); 66 cout << "\n\nequal_range of 22:" << "\n Lower bound: " << *( p.first ) << "\n Upper bound: " << *( p.second ); 70 cout << endl; 72 return 0; 74 75 } // end main fig21_19.cpp (3 of 3) Use a pair object to get the lower and upper bound for 22.

883 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: Lower bound of 22: 22 Upper bound of 22: 30 equal_range of 22: Lower bound: 22 Upper bound: 30 fig21_19.cpp output (1 of 1)

884 21.3.2 set Associative Container
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;

885 21.3.3 multimap Associative Container
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

886 21.3.3 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

887 Definition for a multimap that maps integer keys to double values.
// Fig : fig21_21.cpp // Standard library class multimap test program. #include <iostream> 4 using std::cout; using std::endl; 7 #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 { mmid pairs; 16 cout << "There are currently " << pairs.count( 15 ) << " pairs with key 15 in the multimap\n"; 19 // insert two value_type objects in pairs pairs.insert( mmid::value_type( 15, 2.7 ) ); pairs.insert( mmid::value_type( 15, 99.3 ) ); 23 cout << "After inserts, there are " << pairs.count( 15 ) << " pairs with key 15\n\n"; fig21_21.cpp (1 of 2) Definition for a multimap that maps integer keys to double values. Create multimap and insert key-value pairs.

888 Use iterator to print entire multimap.
27 // insert five value_type objects in pairs pairs.insert( mmid::value_type( 30, ) ); pairs.insert( mmid::value_type( 10, ) ); pairs.insert( mmid::value_type( 25, ) ); pairs.insert( mmid::value_type( 20, ) ); pairs.insert( mmid::value_type( 5, ) ); 34 cout << "Multimap pairs contains:\nKey\tValue\n"; 36 // use const_iterator to walk through elements of pairs for ( mmid::const_iterator iter = pairs.begin(); iter != pairs.end(); ++iter ) cout << iter->first << '\t' << iter->second << '\n'; 42 cout << endl; 44 return 0; 46 47 } // end main fig21_21.cpp (2 of 2) Use iterator to print entire multimap.

889 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 fig21_21.cpp output (1 of 1)

890 21.3.4 map Associative Container
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] = ; Sets the value of key 30 to If subscript not in map, creates new key/value pair Type declaration std::map< int, double, std::less< int > >;

891 Again, use typedefs to simplify declaration.
// Fig : fig21_22.cpp // Standard library class map test program. #include <iostream> 4 using std::cout; using std::endl; 7 #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 { mid pairs; 16 // insert eight value_type objects in pairs pairs.insert( mid::value_type( 15, 2.7 ) ); pairs.insert( mid::value_type( 30, ) ); pairs.insert( mid::value_type( 5, ) ); pairs.insert( mid::value_type( 10, ) ); pairs.insert( mid::value_type( 25, ) ); pairs.insert( mid::value_type( 5, ) ); // dupe ignored pairs.insert( mid::value_type( 20, ) ); pairs.insert( mid::value_type( 15, 99.3 ) ); // dupe ignored 26 fig21_22.cpp (1 of 2) Again, use typedefs to simplify declaration. Duplicate keys ignored.

892 Can use subscript operator to add or change key-value pairs.
cout << "pairs contains:\nKey\tValue\n"; 28 // use const_iterator to walk through elements of pairs for ( mid::const_iterator iter = pairs.begin(); iter != pairs.end(); ++iter ) cout << iter->first << '\t' << iter->second << '\n'; 34 // use subscript operator to change value for key 25 pairs[ 25 ] = ; 37 // use subscript operator insert value for key 40 pairs[ 40 ] = ; 40 cout << "\nAfter subscript operations, pairs contains:" << "\nKey\tValue\n"; 43 for ( mid::const_iterator iter2 = pairs.begin(); iter2 != pairs.end(); ++iter2 ) cout << iter2->first << '\t' << iter2->second << '\n'; 48 cout << endl; 50 return 0; 52 53 } // end main fig21_22.cpp (2 of 2) Can use subscript operator to add or change key-value pairs.

893 fig21_22.cpp output (1 of 1) pairs contains: Key Value 5 1010.1
After subscript operations, pairs contains: fig21_22.cpp output (1 of 1)

894 21.4 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

895 21.4.1 stack Adapter 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)

896 Create stacks with various implementations.
// Fig : fig21_23.cpp // Standard library adapter stack test program. #include <iostream> 4 using std::cout; using std::endl; 7 #include <stack> // stack adapter definition #include <vector> // vector class-template definition 10 #include <list> // list class-template definition 11 12 // popElements function-template prototype 13 template< class T > 14 void popElements( T &stackRef ); 15 16 int main() 17 { // stack with default underlying deque std::stack< int > intDequeStack; 20 // stack with underlying vector std::stack< int, std::vector< int > > intVectorStack; 23 // stack with underlying list std::stack< int, std::list< int > > intListStack; 26 fig21_23.cpp (1 of 3) Create stacks with various implementations.

897 Use member function push.
// push the values 0-9 onto each stack for ( int i = 0; i < 10; ++i ) { intDequeStack.push( i ); intVectorStack.push( i ); intListStack.push( i ); 32 } // end for 34 // display and remove elements from each stack cout << "Popping from intDequeStack: "; popElements( intDequeStack ); cout << "\nPopping from intVectorStack: "; popElements( intVectorStack ); cout << "\nPopping from intListStack: "; popElements( intListStack ); 42 cout << endl; 44 return 0; 46 47 } // end main 48 Use member function push. fig21_23.cpp (2 of 3)

898 fig21_23.cpp (3 of 3) fig21_23.cpp output (1 of 1)
49 // pop elements from stack object to which stackRef refers 50 template< class T > 51 void popElements( T &stackRef ) 52 { while ( !stackRef.empty() ) { cout << stackRef.top() << ' '; // view top element stackRef.pop(); // remove top element 56 } // end while 58 59 } // end function popElements fig21_23.cpp (3 of 3) fig21_23.cpp output (1 of 1) Popping from intDequeStack: Popping from intVectorStack: Popping from intListStack:

899 21.4.2 queue Adapter queue Functions Header <queue>
Insertions at back, deletions at front First-in-first-out (FIFO) data structure Implemented with list or deque (default) std::queue<double> values; Functions push( element ) Same as push_back, add to end pop( element ) Implemented with pop_front, remove from front empty() size()

900 Create queue, add values using push.
// Fig : fig21_24.cpp // Standard library adapter queue test program. #include <iostream> 4 using std::cout; using std::endl; 7 #include <queue> // queue adapter definition 9 10 int main() 11 { std::queue< double > values; 13 // push elements onto queue values values.push( 3.2 ); values.push( 9.8 ); values.push( 5.4 ); 18 cout << "Popping from values: "; 20 while ( !values.empty() ) { cout << values.front() << ' '; // view front element values.pop(); // remove element 24 } // end while 26 fig21_24.cpp (1 of 2) Create queue, add values using push.

901 fig21_24.cpp (2 of 2) fig21_24.cpp output (1 of 1)
cout << endl; 28 return 0; 30 31 } // end main fig21_24.cpp (2 of 2) fig21_24.cpp output (1 of 1) Popping from values:

902 STL separates containers and 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>

903 21.5.6 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

904 fig21_31.cpp (1 of 4) 1 // Fig. 21.31: fig21_31.cpp
// Standard library search and sort algorithms. #include <iostream> 4 using std::cout; using std::endl; 7 #include <algorithm> // algorithm definitions #include <vector> // vector class-template definition 10 11 bool greater10( int value ); // prototype 12 13 int main() 14 { const int SIZE = 10; int a[ SIZE ] = { 10, 2, 17, 5, 16, 8, 13, 11, 20, 7 }; 17 std::vector< int > v( a, a + SIZE ); std::ostream_iterator< int > output( cout, " " ); 20 cout << "Vector v contains: "; std::copy( v.begin(), v.end(), output ); 23 // locate first occurrence of 16 in v std::vector< int >::iterator location; location = std::find( v.begin(), v.end(), 16 ); fig21_31.cpp (1 of 4)

905 fig21_31.cpp (2 of 4) 27 28 if ( location != v.end() )
cout << "\n\nFound 16 at location " << ( location - v.begin() ); else cout << "\n\n16 not found"; 33 // locate first occurrence of 100 in v location = std::find( v.begin(), v.end(), 100 ); 36 if ( location != v.end() ) cout << "\nFound 100 at location " << ( location - v.begin() ); else cout << "\n100 not found"; 42 // locate first occurrence of value greater than 10 in v location = std::find_if( v.begin(), v.end(), greater10 ); 45 if ( location != v.end() ) cout << "\n\nThe first value greater than 10 is " << *location << "\nfound at location " << ( location - v.begin() ); else cout << "\n\nNo values greater than 10 were found"; 52 fig21_31.cpp (2 of 4)

906 fig21_31.cpp (3 of 4) 53 // sort elements of v
std::sort( v.begin(), v.end() ); 55 cout << "\n\nVector v after sort: "; std::copy( v.begin(), v.end(), output ); 58 // use binary_search to locate 13 in v if ( std::binary_search( v.begin(), v.end(), 13 ) ) cout << "\n\n13 was found in v"; else cout << "\n\n13 was not found in v"; 64 // use binary_search to locate 100 in v if ( std::binary_search( v.begin(), v.end(), 100 ) ) cout << "\n100 was found in v"; else cout << "\n100 was not found in v"; 70 cout << endl; 72 return 0; 74 75 } // end main 76 fig21_31.cpp (3 of 4)

907 fig21_31.cpp (4 of 4) fig21_31.cpp output (1 of 1)
77 // determine whether argument is greater than 10 78 bool greater10( int value ) 79 { return value > 10; 81 82 } // end function greater10 fig21_31.cpp (4 of 4) fig21_31.cpp output (1 of 1) Vector v contains: Found 16 at location 4 100 not found The first value greater than 10 is 17 found at location 2 Vector v after sort: 13 was found in v 100 was not found in v

908 Function objects (<functional>)
Contain functions invoked using operator()

909 Create a function to be used with accumulate.
// Fig : fig21_42.cpp // Demonstrating function objects. #include <iostream> 4 using std::cout; using std::endl; 7 #include <vector> // vector class-template definition #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 { return total + value * value; 18 19 } // end function sumSquares 20 fig21_42.cpp (1 of 4) Create a function to be used with accumulate.

910 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 // add square of value to total and return result const T operator()( const T &total, const T &value ) { return total + value * value; 33 } // end function operator() 35 36 }; // end class SumSquaresClass 37 fig21_42.cpp (2 of 4) Create a function object (it can also encapsulate data). Overload operator().

911 38 int main() 39 { const int SIZE = 10; int array[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 }; 42 std::vector< int > integers( array, array + SIZE ); 44 std::ostream_iterator< int > output( cout, " " ); 46 int result = 0; 48 cout << "vector v contains:\n"; std::copy( integers.begin(), integers.end(), output ); 51 // calculate sum of squares of elements of vector integers // using binary function sumSquares result = std::accumulate( integers.begin(), integers.end(), , sumSquares ); 56 cout << "\n\nSum of squares of elements in integers using " << "binary\nfunction sumSquares: " << result; 59 fig21_42.cpp (3 of 4) 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.

912 fig21_42.cpp (4 of 4) fig21_42.cpp output (1 of 1)
// calculate sum of squares of elements of vector integers // using binary-function object result = std::accumulate( integers.begin(), integers.end(), , SumSquaresClass< int >() ); 64 cout << "\n\nSum of squares of elements in integers using " << "binary\nfunction object of type " << "SumSquaresClass< int >: " << result << endl; 68 return 0; 70 71 } // end main fig21_42.cpp (4 of 4) fig21_42.cpp output (1 of 1) Use accumulate with a function object. vector v contains: Sum of squares of elements in integers using binary function sumSquares: 385 function object of type SumSquaresClass< int >: 385


Download ppt "IS Program Design and Software Tools Introduction to C++ Programming"

Similar presentations


Ads by Google