Professional Documents
Culture Documents
SL-240
Sun Microsystems, Inc. MS BRM01-209 500 Eldorado Boulevard Broomeld, Colorado 80021 U.S.A.
Copyright 1999 Sun Microsystems, Inc., 901 San Antonio Road, Palo Alto, California 94303, U.S.A. All rights reserved. This product or document is protected by copyright and distributed under licenses restricting its use, copying, distribution, and decompilation. No part of this product or document may be reproduced in any form by any means without prior written authorization of Sun and its licensors, if any. Third-party software, including font technology, is copyrighted and licensed from Sun suppliers. Sun, Sun Microsystems, the Sun Logo, Sun Visual Workshop, Sun C++, OpenWindows, Java, and Solaris are trademarks or registered trademarks of Sun Microsystems, Inc. in the U.S. and other countries. All SPARC trademarks are used under license and are trademarks or registered trademarks of SPARC International, Inc. in the U.S. and other countries. Products bearing SPARC trademarks are based upon an architecture developed by Sun Microsystems, Inc. UNIX is a registered trademark in the U.S. and other countries, exclusively licensed through X/Open Company, Ltd. The OPEN LOOK and Sun Graphical User Interface was developed by Sun Microsystems, Inc. for its users and licensees. Sun acknowledges the pioneering efforts of Xerox in researching and developing the concept of visual or graphical user interfaces for the computer industry. Sun holds a non-exclusive license from Xerox to the Xerox Graphical User Interface, which license also covers Suns licensees who implement OPEN LOOK GUIs and otherwise comply with Suns written license agreements. U.S. Government approval required when exporting the product. RESTRICTED RIGHTS: Use, duplication, or disclosure by the U.S. Government is subject to restrictions of FAR 52.227-14(g) (2)(6/87) and FAR 52.227-19(6/87), or DFAR 252.227-7015 (b)(6/95) and DFAR 227.7202-3(a). DOCUMENTATION IS PROVIDED "AS IS" AND ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS, AND WARRANTIES, INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE DISCLAIMED, EXCEPT TO THE EXTENT THAT SUCH DISCLAIMERS ARE HELD TO BE LEGALLY INVALID.
Please Recycle
Contents
About This Course .......................................................................................ix Course Goal ......................................................................................... ix Course Overview ................................................................................. x Course Map.......................................................................................... xi Module-by-Module Overview ......................................................... xii Course Objectives.............................................................................. xiv Skills Gained by Module................................................................... xv Guidelines for Module Pacing ........................................................ xvi Topics Not Covered........................................................................ xvii How Prepared Are You?............................................................... xviii Introductions ..................................................................................... xix How to Use Course Materials .......................................................... xx Course Icons and Typographical Conventions ........................... xxii Icons ...........................................................................................xxii Typographical Conventions ................................................. xxiii Notes to the Instructor................................................................... xxiv Object-Oriented Software Engineering .................................................1-1 Objectives ........................................................................................... 1-1 Relevance............................................................................................ 1-2 Additional Resources ....................................................................... 1-3 Handling Software Complexity ...................................................... 1-5 Assembly Languages................................................................1-6 Primitive High-Level Languages............................................1-7 Block-Structured Languages ...................................................1-8 Object-Oriented Languages...................................................1-10 Object-Oriented Programming ..................................................... 1-11 Definition..................................................................................1-11 Classes and Objects......................................................................... 1-12 Encapsulation and Information Hiding....................................... 1-15 An Objective Clock ......................................................................... 1-16 Abstraction...............................................................................1-17 Information Hiding.................................................................1-17 Encapsulation ..........................................................................1-17
iii
Copyright 1999 Sun Microsystems, Inc. All Rights Reserved. Enterprise Services Nov. 1999, Revision H
A Simple Library ............................................................................. 1-18 Talking to Objects ...................................................................1-18 Object Interactions ..................................................................1-19 Object Relationships ....................................................................... 1-20 Association...............................................................................1-20 Composition.............................................................................1-21 Which Relationship?...............................................................1-22 Reuse.........................................................................................1-22 Class Relationships ......................................................................... 1-23 Class Inheritance .....................................................................1-23 Generalization .........................................................................1-24 Specialization...........................................................................1-24 Multiple Inheritance ....................................................................... 1-25 Multiple Inheritance Debate..................................................1-25 Dynamic (Late) Binding ................................................................. 1-27 Polymorphic Operations........................................................1-27 Dynamic (Late) Binding .........................................................1-28 Parametric Types............................................................................. 1-29 Template Functions ................................................................1-30 Template Classes.....................................................................1-30 Reuse.........................................................................................1-30 Object-Oriented Development ...................................................... 1-31 Object-Oriented Analysis.......................................................1-31 Object-Oriented Design..........................................................1-32 Implementation .......................................................................1-32 The Structure of C++ Programs .................................................... 1-33 Defining Classes and Objects ........................................................ 1-34 Benefits of Using C++..................................................................... 1-35 Check Your Progress ...................................................................... 1-36 Think Beyond .................................................................................. 1-37 Introduction to the Basics of Sun C++ ...................................................2-1 Objectives ........................................................................................... 2-1 Relevance............................................................................................ 2-2 The History of C++ ........................................................................... 2-3 Components of C++ Compilation .................................................. 2-4 Sun Visual WorkShop C++.......................................................... 2-5 Using Sun C++ .................................................................................. 2-6 Setting Up the User Environment ..........................................2-6 Recognized File Name Extensions..........................................2-7 Command-Line Syntax ............................................................2-7 Command-Line Examples .......................................................2-8 C++ Keywords...........................................................................2-9 C++ Basics ........................................................................................ 2-10 Function Prototypes................................................................2-10 Variable Declarations Not at the Top of Blocks..................2-11
iv
Declarations of Parameters in the Parentheses...................2-11 The void Data Type in the Function Interface ...................2-11 End-of-line Comments // ..................................................2-13 The cout Object and endl Functions...................................2-13 Inline Functions.......................................................................2-14 Tagnames as Data Types........................................................2-16 Using the cin Object...............................................................2-16 Dynamic Allocation Operators (new and delete) .............2-17 Function Overloading and a Word on Mangling...............2-19 Constants..................................................................................2-22 Pointers to Constants..............................................................2-22 Constant Pointers ....................................................................2-23 Constant Pointers to Constants.............................................2-23 Constant Parameters...............................................................2-23 References ................................................................................2-25 Default Parameter Values ......................................................2-28 Void Pointers ...........................................................................2-30 Functional Type Casting ........................................................2-32 Exercises ........................................................................................... 2-34 Check Your Progress ...................................................................... 2-36 Think Beyond .................................................................................. 2-37 Introduction to Classes .............................................................................3-1 Objectives ........................................................................................... 3-1 Relevance............................................................................................ 3-2 Structures and Classes...................................................................... 3-3 Declaration and Definition .............................................................. 3-4 Access Regions (Encapsulation) ..................................................... 3-7 Access Region Syntax ...............................................................3-8 Default Access ...........................................................................3-8 Implicit Inline Functions ................................................................ 3-10 Member Functions Outside the Class Definition ....................... 3-12 Object Storage .................................................................................. 3-14 The this Pointer ............................................................................. 3-17 Constructors..................................................................................... 3-20 Overloading Constructors .....................................................3-22 Default Parameter Values ......................................................3-24 Initializing Arrays of Objects ................................................3-26 Destructors ....................................................................................... 3-29 ~tagname() ...............................................................................3-30 No Overloading.......................................................................3-30 No Return Type.......................................................................3-30 No Default................................................................................3-30 An Example and a Problem...................................................3-32 Exercises ........................................................................................... 3-35 Check Your Progress ...................................................................... 3-37
v
Copyright 1999 Sun Microsystems, Inc. All Rights Reserved. Enterprise Services Nov. 1999, Revision H
Think Beyond .................................................................................. 3-38 Advanced Use of Classes ..........................................................................4-1 Objectives ........................................................................................... 4-1 Relevance............................................................................................ 4-2 Default Copy Constructor ............................................................... 4-3 Writing a Copy Constructor ............................................................ 4-5 Friend Functions ............................................................................... 4-8 Constructors Initialization and Assignment ............................ 4-11 Composition Objects as Data Members.................................... 4-13 Constant and Reference Data Members ...................................... 4-15 Constant Data Members ........................................................4-15 Reference Data Members .......................................................4-15 Static Members ................................................................................ 4-17 Static Data Members (Class Variables) ................................4-17 Static Member Functions .......................................................4-19 Constant Objects and Member Functions ................................... 4-21 Scope Rules in C++ ......................................................................... 4-23 C Scope Rules Blocks and Files ..........................................4-23 C++ Scope Rules......................................................................4-24 :: Scope Operator .................................................................4-24 Exercises ........................................................................................... 4-26 Check Your Progress ...................................................................... 4-28 Think Beyond .................................................................................. 4-29 Operator Overloading and Type Conversions .....................................5-1 Objectives ........................................................................................... 5-1 Relevance............................................................................................ 5-2 Overloading Operators .................................................................... 5-3 When to Overload Operators ..................................................5-4 Two Default Operators Provided ...........................................5-4 Some Rules for Overloading Operators.................................5-5 Special Function operator<operator>() ......................5-5 Overloading Binary Operators........................................................ 5-6 Using Member Functions to Overload ..................................5-6 Using Friend Functions to Overload......................................5-8 Overloading Unary Operators ...................................................... 5-10 Overloading the Postfix Operator ........................................5-10 Operator Overloading Restrictions .............................................. 5-14 Overloading Operator []............................................................... 5-15 Using the Default Assignment Operator (=) ............................... 5-17 Overloading the Assignment Operator (=) ................................. 5-19 Type Conversions ........................................................................... 5-21 operator type()Function Conversions............................5-21 Conversion Constructors .......................................................5-23 Implicit and Explicit Casting......................................................... 5-24 Getting the Most Out of Few Functions ...................................... 5-26
vi C++ and Object-Oriented Programming
Copyright 1999 Sun Microsystems, Inc. All Rights Reserved. Enterprise Services Nov. 1999, Revision H
Exercises ........................................................................................... 5-28 Check Your Progress ...................................................................... 5-30 Think Beyond .................................................................................. 5-31 Single Inheritance and Virtual Functions .............................................6-1 Objectives ........................................................................................... 6-1 Relevance............................................................................................ 6-2 Single Inheritance.............................................................................. 6-3 Inheritance Syntax ....................................................................6-4 Access Regions Revisited................................................................. 6-7 Constructors and Inheritance........................................................ 6-10 Base Takes Care of Base; Derived Takes Care of Derived ....................................................................6-10 Deriving From Base Classes .......................................................... 6-13 Public Base Class .....................................................................6-13 Private Base Class ...................................................................6-13 Protected Base Class ...............................................................6-14 Private As Compared toPublic Base Classes ......................6-15 Private Base Classes................................................................6-16 Composition Instead of Private Inheritance .......................6-17 Conversions Between Derived and Public Base Classes ..........................................................................6-18 Virtual Functions............................................................................. 6-20 Polymorphism .........................................................................6-20 Virtual Functions.....................................................................6-20 Using Virtual Functions .........................................................6-21 Virtual Function Syntax .........................................................6-21 Without Using Virtual Functions .........................................6-24 Using Virtual Functions .........................................................6-26 Overloading and Virtual Functions ............................................. 6-28 Pure Virtual Functions ................................................................... 6-31 Exercises ........................................................................................... 6-34 Check Your Progress ...................................................................... 6-36 Think Beyond .................................................................................. 6-37 Multiple Inheritance and Virtual Base Classes ...................................7-1 Objectives ........................................................................................... 7-1 Relevance............................................................................................ 7-2 Multiple Inheritance ......................................................................... 7-3 Syntax .........................................................................................7-4 Derived Object of Multiple Inheritance ......................................... 7-5 Providing Values to Base Class Constructors............................... 7-9 Resolving Conflicts From Multiple Inheritance ......................... 7-12 Identifier Scope........................................................................7-13 Using the Scope Operator .............................................................. 7-15 Identifier Ambiguity Error ....................................................7-17
vii
Copyright 1999 Sun Microsystems, Inc. All Rights Reserved. Enterprise Services Nov. 1999, Revision H
Resolving the Ambiguity Error With the Scope Operator .....................................................................7-19 Using Functions to Invoke Specific Classes ........................7-20 Using namespace to Resolve Duplicate Identifiers ...........7-23 Using Virtual Base Classes ............................................................ 7-28 Constructor Conflicts...................................................................... 7-31 Resolving Constructor Conflicts Two Options................7-34 Virtual Base Classes and Overloaded Functions........................ 7-36 Exercises ........................................................................................... 7-39 Check Your Progress ...................................................................... 7-41 Think Beyond .................................................................................. 7-42 Templates, Exception Handling, and Tools.h++ ................................8-1 Objectives ........................................................................................... 8-1 Relevance............................................................................................ 8-2 Templates ........................................................................................... 8-3 Template Functions .......................................................................... 8-4 Syntax .........................................................................................8-4 Rules............................................................................................8-5 Template Classes............................................................................... 8-7 Using a Template for a Stack Class ........................................8-8 Exception Handling ........................................................................ 8-10 Traditional Methods ...............................................................8-10 Exception Handling Mechanism ..........................................8-11 Tools.h++........................................................................................ 8-14 Tools.h++ String and Date Example ..................................8-15 Tools.h++ Collection Classes....................................................... 8-16 Template-Based Classes .........................................................8-17 Generic-Based Classes ............................................................8-17 Smalltalk-Like Classes............................................................8-17 Exercises ........................................................................................... 8-20 Check Your Progress ...................................................................... 8-22 Think Beyond .................................................................................. 8-23 Standard Template Library (STL) ...........................................................9-1 Objectives ........................................................................................... 9-1 Relevance............................................................................................ 9-2 Standard Template Library ............................................................. 9-3 Container Classes......................................................................9-4 Iterators.......................................................................................9-6 Generic Algorithms ..................................................................9-8 vector Class ..............................................................................9-10 List Class...................................................................................9-12 Stack Class................................................................................9-14 Exercise ............................................................................................. 9-16 Check Your Progress ...................................................................... 9-18 Think Beyond .................................................................................. 9-19
viii C++ and Object-Oriented Programming
Copyright 1999 Sun Microsystems, Inc. All Rights Reserved. Enterprise Services Nov. 1999, Revision H
iostream Library .....................................................................................10-1 Objectives ......................................................................................... 10-1 Relevance.......................................................................................... 10-2 The iostream Library .................................................................... 10-3 Predefined Objects (in <iostream.h>)................................10-4 Significant iostream Classes ................................................10-5 Useful Member Functions......................................................10-6 Stream Format Functions.......................................................10-8 Features of the ios Class ............................................................... 10-9 Manipulators ................................................................................. 10-11 Non-parameterized Manipulators......................................10-12 Parameterized Manipulators...............................................10-12 Manipulator Header File <iomanip.h> .........................10-13 Manipulators Example .........................................................10-14 Writing a Non-Parameterized Manipulator .....................10-16 Writing a Parameterized Manipulator...............................10-17 Features of the ostream Class..................................................... 10-18 Features of the istream Class..................................................... 10-19 Using istream and ostream Functions .................................... 10-21 Overloading Insertion (<<) and Extraction (>>) Operators............................................................................. 10-23 Overloading as Friend and Member Functions................10-23 Return Value ..........................................................................10-24 File I/O Classes ............................................................................. 10-27 Creating File I/O Objects.....................................................10-28 Testing for Error on File Opening ......................................10-29 Useful Member Functions....................................................10-30 Sample Output for Code 10-8..............................................10-32 String Stream I/O ......................................................................... 10-33 Another File I/O Example........................................................... 10-35 Exercise ........................................................................................... 10-37 Check Your Progress .................................................................... 10-39 Think Beyond ................................................................................ 10-40 Solution to trace.cc................................................................................A-1 Glossary ......................................................................................... Glossary-1
ix
Copyright 1999 Sun Microsystems, Inc. All Rights Reserved. Enterprise Services Nov. 1999, Revision H
Use this module to get the students excited about this course. With regard to the overheads: To avoid confusion among the students, it is very important to tell them that the page numbers on the overheads have no relation to the page numbers in their course materials. They should use the title of each overhead as a reference. The strategy provided by the About This Course is to introduce students to the course before they introduce themselves to you and one another. By familiarizing them with the content of the course first, their introductions have more meaning in relation to the course prerequisites and objectives. Use this introduction to the course to determine how well students are equipped with the prerequisite knowledge and skills. The pacing chart on page xvi enables you to determine what adjustments you need to make in order to accommodate the learning needs of students.
ix
Copyright 1999 Sun Microsystems, Inc. All Rights Reserved. Enterprise Services Nov. 1999, Revision H
Course Overview
Object-orientation is a programming methodology developed to solve many programming problems. The object-oriented (OO) paradigm is composed of a number of concepts relatively new to the programming world, including managing complexity through dividing programs into manageable modules, reducing complexity through abstraction, and leveraging existing development and testing effort through reuse. C++ takes full advantage of the benets of OO. To code C++ programs effectively, you must gain a rm understanding of OO. Some programming languages, such as Fortran or COBOL, are not objectoriented. If you do not have experience creating object-oriented programs, you need the background provided by this course before taking more advanced OO analysis and design courses offered by Sun Educational Service. Basic OO concepts are presented rst. You then learn how to implement those concepts in C++.
Course Map
The following course map enables you to see what you have accomplished and where you are going in reference to the course goal.
Introduction
About This Course Object-Oriented Software Engineering Introduction to the Basics of Sun C++
Using Classes
Introduction to Classes Advanced Use of Classes
Advanced C++
Operator Overloading and Type Conversions Single Inheritance and Virtual Functions Multiple Inheritance and Virtual Base Classes
iostream Library
xi
Module-by-Module Overview
This course contains the following modules:
G
Module 1, Object-Oriented Software Engineering, presents the basic concepts of object-oriented (OO) programming. Module 2, Introduction to the Basics of Sun C++, provides a brief history of C++ and introduces basic C++ features. Module 3, Introduction to Classes, explains the concept, purpose, syntax, and basic use of classes. Module 4, Advanced Use of Classes, describes the advanced uses of classes. Module 5, Operator Overloading and Type Conversions, describes how objects (user-dened data types) can be converted and used in different ways.
xii
Module 6, Single Inheritance and Virtual Functions, describes how to use, or inherit, existing classes to create new classes and objects. Module 7, Multiple Inheritance and Virtual Base Classes, explains how to avoid conicts arising from multiple class inheritance. Module 8, Templates, Exception Handling, and Tools.h++, describes how to write template functions and classes, handle and throw exceptions, and write applications using the tools.h++ class library. Module 9, Standard Template Library (STL), describes how to access and use the C++ Standard Template Library (STL). Module 10, iostream Library, explains how to access and use the C++ iostream library for input and output (I/O).
xiii
Course Objectives
Upon completion of this course, you should be able to:
G G G G G G G G G
Write, compile, and execute C++ programs Write inline and overloaded functions Use constant reference data types Employ new and delete operators for dynamic memory allocation Dene classes Use public, private, and protected access levels Write constructors and destructors Understand and use the "this" pointer Write friend, type conversion, static, and constant member functions Overload operators Dene new classes using both single and multiple inheritance Write virtual functions for polymorphic operations Compose template functions and template classes Write applications that use the Tools.h++ class library and exception handling Prevent identier naming conicts Understand and use the Standard Template Library (STL) Use the iostream library
G G G G G
G G G
Ask the students how many signed up for this course because of the information in the Sun Educational Services course catalog, what their knowledge and expectations of the objectives stated there are, and use this information as a tool to manage your time in covering the material in this course.
xiv
2 3 4 5 6 7 8 9 10
Refer students to this matrix as you progress through the course to show them the progress they are making in learning the skills advertised for this course.
xv
xvi
Object-Oriented Analysis and Design Covered in OO-120: Object-Oriented Design and Analysis and SL-226: Object-Oriented Application Analysis and Design for Java Technology (UML).
Refer to the Sun Educational Services catalog for specic information and registration.
xvii
Can you write correct C programs? The material in this course was developed with the assumption that students would be competent C programmers. Can you create and edit text les using vi or the OpenWindows Text Editor? You use these editors to work on the course exercises. Can you use basic Solaris commands? You will be working on a Solaris system. Can you compile and link programs that consist of multiple source les? The nature of object-oriented programming in C++ includes using multiple source les. Familiarity with compiling and linking them is essential for success in the course.
If any students indicate they cannot do these requirements, meet with them at the first break to decide how to proceed with the class. Do they want to take the class at a later date? Is there some way to get the extra help needed during the week? It might be appropriate here to recommend resources from the Sun Educational Services catalog that provide training for topics not covered in this course.
C++ and Object-Oriented Programming
Copyright 1999 Sun Microsystems, Inc. All Rights Reserved. Enterprise Services Nov. 1999, Revision H
xviii
Introductions
Now that you have been introduced to the course, introduce yourself to each other and the instructor, addressing the items shown on the above overhead.
xix
Course map An overview of the course content appears in the "About This Course" module so you can see how each module ts into the overall course goal. Objectives - The objectives section of each module lists what you should be able to accomplish after completing the module. Relevance This section, which appears in every module, provides scenarios or questions that introduce you to the information contained in the module and provoke you to think about how the module content relates to C++ and Object-Oriented Programming. Overhead image Reduced overhead images for the course are included in the course materials to help you easily follow where the instructor is at any point in time. Overheads do not appear on every page.
xx
Lecture The instructor will present information specic to the topic of the module. This information will help you learn the knowledge and skills necessary to succeed with the exercises. Exercise Lab exercises will give you the opportunity to practice your skills and apply the concepts presented in the lecture. Check your progress Module objectives are restated, sometimes in question format, so that before moving on to the next module you are sure that you can accomplish the objectives of the current module. Think beyond Thought-provoking questions are posed to help you apply the content of the module or predict the content in the next module.
xxi
Icons
Additional resources Indicates additional reference materials are available.
Discussion Indicates a small-group or class discussion on the current topic is recommended at this time.
Exercise objective Indicates the objective for the lab exercises that follow. The exercises are appropriate for the material being discussed.
xxii
Typographical Conventions
Courier is used for the names of commands, les, and directories, as well as on-screen computer output. For example: Use ls -al to list all les. system% You have mail. It is also used to represent parts of the Java programming language such as class names, methods, and keywords. For example: The getServletInfo method is used to... The java.awt.Dialog class contains Dialog (Frame parent) Courier bold is used for characters and numbers that you type. For example: system% su Password: It is also used for each code line that will be referenced in text. For example: 1. #include <string.h> 2. #include <iostream.h> 3. template <class type>
Courier italic is used for variables and command-line placeholders that are replaced with a real name or value. For example:
To delete a le, type rm filename. Palatino italics is used for book titles, new words or terms, or words that are emphasized. For example: Read Chapter 6 in Users Guide. These are called class options. You must be root to do this.
xxiii
To allow the instructor exibility and give time for meaningful discussions during the lectures and the small-group discussions, a timing table is included in the Course Tools section.
Course Tools
To enable you to follow this structure, the following supplementary materials are provided with this course:
G
Relevance These questions or scenarios set the context of the module. It is suggested that the instructor ask these questions and discuss the answers. The answers are provided only in the instructors guide.
Course map The course map allows the students to get a visual picture of the course. It also helps students know where they have been, where they are, and where they are going. The course map is presented in the About This Course in the students guide.
xxiv
Lecture overheads Overheads for the course are provided in two formats: The paper-based format can be copied onto standard transparencies and used on a standard overhead projector. These overheads are also provided in the students guide. The Web browserbased format is in HTML and can be projected using a projection system which displays from a workstation. This format gives the instructor the ability to allow the students to view the overhead information on individual workstations. It also allows better random access to the overheads.
Exercises Summary: small-group discussion After the lab exercises, it is a good idea to debrief the students. Gather them back into the classroom and have them discuss their discoveries, problems, and issues in programming the solution to the problem in small groups of four or ve, one-on-one, or one-onmany.
General timing recommendations Each module contains a Relevance section. This section may present a scenario relating to the content presented in the module, or it may present questions that stimulate students to think about the content that will be presented. Engage the students in relating experiences or posing possible answers to the questions. Spend no more that 1015 minutes on this section.
xxv
Module "About This Course" "Object-Oriented Software Engineering" "Introduction to the Basics of Sun C++" "Introduction to Classes" "Advanced Use of Classes" "Operator Overloading and Type Conversions" "Single Inheritance and Virtual Functions" "Multiple Inheritance and Virtual Base Classes" "Templates, Exception Handling, and Tools.h++" "Standard Template Library (STL)" "iostream Library"
G
Lecture (Minutes)
Lab (Minutes)
Module self-check Each module contains a checklist for students in the Check Your Progress section. Give them a little time to read through this checklist before going on to the next lecture. Ask them to see you for items they do not feel comfortable checking off.
xxvi
Course Files
All of the course les for this course are available from the education.central server. You can use ftp or the education.central Web site, http://education.central/Released.html, to download the les from education.central. Either of these methods requires you to know the user ID and password for FTP access. See your manager for these if you have not done this before.
Course Components
This course consists of the following components:
G
Instructor guide The SL240_IG directory contains the FrameMaker les for the instructors guide (students guide with instructor notes). The ART directory is required for printing this guide.
Student guide The SL240_SG directory contains the FrameMaker les for the students guide. The ART directory is required for printing this guide.
Art The SL240_ART directory contains the supporting images and artwork for the students and instructors guides. This directory is required for the printing of the students and instructors guides and should be located in the same directory as SL240_IG and SL240_SG.
Instructor notes The SL240_IN directory contains the text le SL240_revH_setup.txt, which provides setup instructions for the class.
xxvii
Overheads The SL240_OH directory contains the instructor overheads. There are both HTML and FrameMaker versions of the overheads.
Lab les The SL240_LF directory contains the lab les for this course. It also contains an Examples folder with soft copies of the full code examples shown in the Instructor/Student guides.
xxviii
Discuss the limitations of structured programming List three main goals of object-orientation Dene object and class and discuss their relationship Discuss the principles of classication and behavioral modeling of real-world and abstract entities List the three simple denitions of class inheritance, composition, and association List the stages of object-oriented development Identify the features of the Sun C++ programming language that support object-oriented programming
G G
1-1
Copyright 1999 Sun Microsystems, Inc. All Rights Reserved. Enterprise Services Nov. 1999, Revision H
1
Relevance
Present the following questions to stimulate the students and get them thinking about the issues and topics presented in this module. While they are not expected to know the answers to these questions, the answers should be of interest to them and inspire them to learn the material presented in this module.
Discussion Why was object-oriented programming developed? What concepts separate object-oriented programming from other programming methodologies?
1-2
1
Additional Resources
Additional resources The following references can provide additional details on the topics discussed in this course:
G
The following books are part of the Sun Visual Workshop C++ 5.0 documentation package: C++ Programming Guide, C++ Library Reference, C++ Migration Guide, Tools.h++ Users Guide, Tools.h++ Class Library Reference, C++ Standard Library 2.0 Users Guide, C++ Standard Library Class Reference, Sun WorkShop Memory Monitor Users Guide. Stroustrup, Bjarne, 1997. The C++ Programming Language, 3rd Ed. Reading, MA: Addison-Wesley. Stroustrup, Bjarne, 1998. C++ Solutions: Companion to the C++ Programming Language. Reading, MA: Addison-Wesley. Lippman, Stanley B., Jose Lajoie, 1998. A C++ Primer, 3rd Ed. Reading, MA: Addison-Wesley Tondo, Clovis L., Bruce Leung, 1998. C++ Primer Answer Book. Reading, MA: Addison-Wesley Ellis, Margaret A., Bjarne Stroustrup, 1994. The Design and Evolution of C++. Reading, MA: Addison-Wesley Pohl, Ira, 1998. C++ for C Programmers, 3rd Ed. Reading, MA: Addison-Wesley Austern, Matthew H., 1998. Generic Programming and the STL. Reading, MA: Addison-Wesley. Meyers, Scott, 1995. More Effective C++: 35 New Ways to Improve Your Programs and Designs. Reading, MA: Addison-Wesley. Winder, Russell, 1993. Developing C++ Software, 2nd Ed. New York: Wiley, John & Sons. Henricson, Mats, Erik Nyquist, 1995. Industrial Strength C++: Rules and Recommendations. Englewood Cliffs, NJ: Prentice Hall. Booch, Grady, 1993. Object-Oriented Anaylsis and Design with Applications, 2nd Ed. Reading, MA: Addison-Wesley Koenig, Andrew, Barbara Moo. 1997. Ruminations on C++. Reading, MA: Addison-Wesley.
1-3
1
G
Deitel, Harvey M., Paul J. Deitel, 1997. C++ How to Program, 2nd Ed. Englewood Cliffs, NJ: Prentice Hall.
Also mention the following reference periodicals and web sites: C++ Report, Component Strategies (formerly Object Magazine), Dr. Dobbs Journal, Journal of Object-Oriented Programming (JOOP), Association of C and C++ Users (www.accu.org), and About.com (http://cplus.miningco.com).
1-4
1-5
Assembly Languages
Assembly languages usually map directly to machine code instructions and are highly machine oriented. They tend to give little or no support for modularization and involve the manipulation of data and registers accessible in a global scope. In addition, low-level languages tend to provide only the building blocks for programming constructs (such as looping and conditional statements). Such languages are suitable for relatively small programming tasks that require direct access to hardware.
1-6
1-7
Block-Structured Languages
Modern block-structured languages, such as C and Pascal enable you to modularize software with regard to both functions and data. Powerful scoping models encapsulate local state and operations, and restrict module dependencies to well-dened interfaces. Programming in this style is reected by the coupling and cohesion of the program modules. Good software should exhibit a high degree of modular cohesion (keeping relevant parts of the code together), and a low degree of inter-module coupling (reducing interdependencies). The notion of abstract data types is important to many programming methodologies. This concept embodies the ideas of encapsulation (in which associated data and operations are grouped together) and information hiding (where only public parts of an abstract type are made visible to client code). There is an obvious relationship between cohesion and encapsulation, and between coupling and information hiding.
1-8
1
The problem with most conventional programming languages is that they do not actually support abstract data types. You can group data within records or structures, and "suggest" that the data be accessed through a collection of functions, but this is not enforced by the language.
1-9
Object-Oriented Languages
Object-oriented languages are based on the construction of complex types that encapsulate both operations and data. Variables of these types maintain the state and exhibit the behavior of the type of object they represent. float in C, for example, is a data type in which variables hold the state for an exponent and mantissa, and allow numerical operations. Object-oriented languages enable users to dene abstract data types, so that complex objects can also be modeled. Object-oriented languages also enable you to reuse modules through inheritance and polymorphism. You can dene new type might be dened in terms of existing types.
1-10
Object-Oriented Programming
A programmer on the way to work enters a coffee shop, orders coffee, sits down and drinks it, and continues on. There are several possible objects in the coffee shop: the building itself, the coffee, the table, and so on. Each object has various characteristics that describe it: the shop is open or closed; the coffee is small, medium, or large and has a specic price; tables are available or unavailable.
Denition
Object orientation is a technique for system modeling, system being a software system or a system in a more general context, such as the coffee shop mentioned previously. Object orientation describes, or models, the system as a number of related, independent objects that interact. Object orientation is similar to the way people view their environment.
1-11
1-12
Cup class size shape material color volume handle Espresso Cup object size = small shape = tapered material = porcelain color = white volume = 4 oz. handle = true
Espresso Cup is an object created from the Cup class. Espresso Cup uses attributes defined in the Cup class. You can create multiple cup objects using the same attributes with different values.
Figure 1-1
Class denitions typically contain actions (functions) as well as attributes. Figure 1-2 shows how you could build an employee class for the coffee shop that contains generic functions such as talking to customers, taking money, and washing dishes. From the employee class you could create individual employee objects (cashier, coffee maker, busboy) that perform one or more of the functions dened in the class.
Employee class gender takesMoney(); makesCoffee(); washesDishes(); Cashier Employee object gender = female takesMoney();
The Cashier object, created from the Employee class, performs the takesMoney function defined in the Employee class. You can create multiple employees who perform different functions, because the functions are defined in the Employee class.
Figure 1-2
1-13
1
Compared with conventional programming, classes are similar to structures except that they include functions in addition to attributes. Object-oriented programming is based on nding suitable classes to model the problem being solved. The real job for object- oriented programmers is to dene class libraries (effectively, tool kits) rather than actually applying them to solve the given problem. Objectoriented language is described in terms of the interaction of its component objects. An object-oriented programming language provides features that allow a more direct mapping from the real world into the programming language, which in turn provides a better correspondence between the programs design and implementation.
1-14
1-15
An Objective Clock
Object-oriented software engineering focuses on using objects collectively to model the problem that the program seeks to solve. Program objects often represent real world items, for example, a clock, a radio, or a light. Just as these items are abstractions of switches and dials and electrical wires, objects are also abstractions. Moving from the coffee shop to another example, the following sections illustrate the considerations involved in developing a clock object.
1-16
1
Abstraction
Abstraction is the process used to help determine what is being modeled. Discussion How would you use abstraction to model a clock object?
Information Hiding
After you model a problem through abstraction, determine which elements within the model will be hidden from direct user access.
Encapsulation
What is the public interface? To the user, the clock has only one operation: it tells the time. However, to tell the time it might have several hidden attributes, internal cogs in a mechanical watch, which are irrelevant to the user of the watch. The public interface contains only What is the time? All other operations and state are hidden behind the encapsulation barrier.
1-17
A Simple Library
After you create objects, you have to make them interact. The library example illustrates object interaction. Three objects are presented belonging to three different classes: Person, Library, and Book. The Person object Me sends a message to the Library object (My City) asking to borrow a Book. The message contains the operation and a parameter. The Library responds by sending a Book object back to the Person.
Talking to Objects
Objects encapsulate the behavior and state of data. Given an object of a particular type (or class), the application can request that the object perform an operation by sending it a message. When a message is sent to an object, the message contains the method (or operation) to be carried out, together with any required parameters. The operation is part of the objects public interface.
1-18
1
Object Interactions
In response to messages, objects can perform operations on their state values or return values or both that are otherwise hidden behind their encapsulation barrier. Often, they cooperate with other objects and create new messages in response to the one they are processing. Object-oriented programs are characterized by the interactions of the objects used to model the problem. Conceptually, you can ask a single question of a single object (through some interface that sends it a message), which can result in many interactions between the objects in the program.
1-19
Object Relationships
Two objects are related in one of two ways: One object either uses the other object, or an object contains (or is contained in) another object. These two relationships are called association and composition.
Association
Two or more objects are associated when one object uses the operations of another during the course of a computation. In this relationship, one object is the client (requesting a public service), the other is the provider (making the service available). Association does not imply any special relationship between the objects taking part. In particular, the client does not gain special access to those hidden parts of the provider. In the clock example, a clock can use the calendar to report the date. Clock and calendar objects have a relationship of association.
1-20
Composition
Composition describes the "has-a" or "part-of" relationship. It occurs when an object has other objects contained within itself. Composition is also know as aggregation. Composition occurs in conventional programming languages through nested data structures. However, because only data and not operations are dened, this is less powerful. In the library example, a library object contains or has books. Library and book objects have a relationship of composition.
1-21
1
Which Relationship?
A central idea behind object-oriented programming is to model the real (or abstract) world in a way that is appropriate to the object being modeled. In the physical world some items are best represented by composition, others by association. This is more than a semantic difference. The type of relationships an object has determines how it is written in code, so accurately determining object relationships in the analysis and design phase is important for the development effort.
Reuse
Another central idea behind object-oriented programming is reuse: the ability to use existing software components in new (and perhaps radically different) situations. Both composition and association support the notion of reuse, becuase one object is making use of others to fulll some requirement.
1-22
Class Relationships
Like objects, classes also have relationships with each other.
Class Inheritance
The ability to support software reuse is the distinguishing feature of all object-oriented languages. This ability, called inheritance is an efcient mechanism in which new classes can be constructed from existing classes. Inheritance exploits the "is-a" or "kind-of" relationship. For example, both cars and planes are kinds of Vehicles objects. The signicance of the relationship is that common behavior and attributes are generalized and written once in the base class. Subsequent classes build on the base class, by adding or rening the behavior for the particular type they represent.
1-23
Generalization
An important aspect of object-oriented analysis is identifying the objects that model the problem being solved. Once analysis is complete, a process of generalization is undertaken to identify the common parts. These parts are then generalized into a single class that is inherited by other classes that need the base functionality. This technique reduces redundancy in the program code. Generalization also helps focus attention on the real behaviors that make up the problem.
Specialization
Specialization is a process of renement of the classes that make up the application. First, a new class is dened in terms of an existing class. This new class inherits both the operations and attributes of the parent, and can extend, suppress, or redene these characteristics.
1-24
Multiple Inheritance
Multiple inheritance is a technique used to create classes from multiple base classes. It is useful when modeling objects that need to combine the behavior of two or more other objects. In a windowing application, for example, windows can combine the behavior of general window controls, such as scrollbars, buttons, and menus. Having dened classes for each of the controls, the window class could be derived from all of them.
1-25
1
Ambiguities are introduced when a class is derived from multiple base classes that share the same member identiers. This apparent scope conict is soluble, but tends to complicate programs. The problem is somewhat more acute when the base classes themselves are derived from some other common base. Data members in the common base appear twice in the multiplied derived children. This is sometimes referred to as fork-and-join inheritance. Another major concern about using multiple inheritance is whether it is a necessary programming technique. Most relationships modeled with multiple inheritance can be tackled with object composition or association. However, some relationships, especially those in which two distinct types are combined to produce a new type, are more accurately modeled with multiple inheritance.
1-26
Polymorphic Operations
Polymorphism is a central idea in object orientation. A collection of objects that are derived from the same base class can have the same operation in common, but the way each object performs the operation can be different, depending on the type of the object.
1-27
1
For example, the shape types circle, rectangle, and triangle are derived from a common base shape. Each provides a draw operation so that the behavior of draw is dependent on the type of the object being drawn. draw is said to be polymorphic because it is dened for multiple types.
1-28
Parametric Types
The C++ template functionality lets you use a single code segment to specify a range of related functions. This is made possible through parametric types. A parametric type is a variable that is dened at usage on its type (int, float, Book) instead of at compile time. For example: template<class T> //declaring parametric type T int func(T x, int y); In this example, T is a parametric type, therefore the variable x is of that type; which means that x could be any type that function func is declared to be. In this example, func is an int, therefore x is an int. Discussion In the slide above, what kind of data does Queue manage?
1-29
1
Template Functions
Functions dened with parametric types are generic and describe an operation that is type-free. The denition of a generic function introduces a family of functions that can be applied to objects of any type. For example, a function max may compare two objects of type <T>, and return the greater. Rather than having to dene individual versions of max for integers, oats, and characters, you need to make only one denition of the function.
Template Classes
A template class denes a family of classes that differ only in the types of their members. Such classes are often used to contain a collection of other objects and are consequently called container classes. For example, a Queue class denes the abstract notion of a queue. This can provide operations to insert and delete elements, but the actual types of these elements is irrelevant. Using template classes, the actual type of the elements being contained is not dened until particular objects of the class are instantiated. For example, objects can dene a queue of oats, a list of integers, or a shelf of books.
Reuse
The idea of dening functions and classes with parametric type information supports software reuse. An existing function or class can be applied to any type, even to types not yet invented.
1-30
Object-Oriented Development
Object-oriented development involves three phases: analysis, design, and implementation.
Object-Oriented Analysis
The analysis stage of development is concerned with gaining a complete understanding of the problem domain. Specically:
G G G G
What are the objects that make up the system? What are their characteristics? What are the relationships between them? What are their interactions?
Various conventional development techniques can be applied to object-oriented analysis (OOA) to analyze a system completely. Topdown analysis requires the system to be initially divided into a few parts, which can themselves be further divided.
1-31
1
Object-Oriented Design
The object-oriented design (OOD) stage of development is used to rene the object specication created in the analysis stage by:
G G G
Forming abstractions (dening classes) Encapsulating (dening interfaces) Structuring (dening object and class relationships through composition, association, and inheritance)
Implementation
There are two parts to this process.
G
Implement the class structures that model the application (the class libraries). Write a program that uses the libraries.
1-32
1-33
1-34
1-35
1
Check Your Progress
Before continuing on to the next module, check that you are able to accomplish or answer the following: K K K K K K K Discuss the limitations of structured programming List three main goals of object-orientation Dene object and class and discuss their relationship Discuss the principles of classication and behavioral modeling of real-world and abstract entities List the three simple denitions of class inheritance, composition, and association List the stages of object-oriented development Identify the features of the Sun C++ programming language that support object-oriented programming
1-36
1
Think Beyond
What functionality does C++ add to C?
1-37
Discuss the history and evolution of C++ Locate the Sun C++ software les that are provided Write the command-line syntax and use the C++ compiler with some of its more useful options Explain the basic features of the C++ language Use the basic C++ features in lab exercises
G G
The Sun C++ programming language is an extension of the C programming language. This module gives you a brief history of C++ and describes its basic features.
2-1
Copyright 1999 Sun Microsystems, Inc. All Rights Reserved. Enterprise Services, Nov. 1999, Revision H
2
Relevance
Present the following questions to stimulate the students and get them thinking about the issues and topics presented in this module. While they are not expected to know the answers to these questions, the answers should be of interest to them and inspire them to learn the material presented in this module.
Discussion What features make C++ more powerful than C? How do the new features contribute to software reuse and easier maintenance?
2-2
2-3
ccfe Performs preprocessing and compilation cg Performs code generation tdb_link Performs template instantiation on out-of-date templates and invokes the linker ld Performs link editing
2-4
Editing and browsing (including a graphical class viewer for displaying class denitions, relationships, and hierarchical inheritance) Building on one or more machines over a network Debugging Runtime error checking Performance analysis Multithreading development Visual GUI building Source conguration management
G G G G G G G
2-5
Set the search path to include the directory where C++ has been installed. This is usually /opt/SUNWspro/bin in the SunOS 5.x operating system. setenv PATH /opt/SUNWspro/bin:$PATH
Set the MANPATH variable to reference the correct man pages. /opt/SUNWspro/man for SunOS 5.x operating system. setenv MANPATH /opt/SUNWspro/man:/usr/man
2-6
Command-Line Syntax
The options for the CC command to compile programs are much the same as those for the cc command. The arguments to the CC command are the le names that should be compiled, assembled, and linked together.
2-7
2
The following are some command-line options. Table 2-1: Command-line options +d -g -help -o +p Does not expand inline functions inline. Produces symbol table information for the debugger. Displays helpful information about CC. Precedes an output le name, for example -o myfile. Does not allow anachronistic constructs (statements in the C++ source code that are normally allowed but are not encouraged). If you do not use the +p option, warnings are given about the code but compilation does not fail. If you use the +p option, the same statements cause the compilation to fail. Prints template information verbosely. Generates extra symbol table information for the SourceBrowser. Prints verbosely each command invoked by the CC driver. Warns you about constructs that are likely to be mistakes, non-portable, or inefcient. Tells you if an inline request was not honored. Builds archive libraries and is also useful with templates.
-ptv -sb -v +w
-xar
Command-Line Examples
The following are valid command-line compiling examples. % CC source1.cc other.o -o output % CC -o outputfile source1.cc source2.cc -Llibdir -llibname
2-8
2
C++ Keywords
Bold keywords are the C++ additions to C, which were created to increase functionality and make C++ an object-oriented programming language. asm auto bool break case catch char class const const_cast continue default delete do double dynamic_cast else enum explicit extern false float for friend goto if inline int long mutable namespace new operator private protected public register reinterpret_cast return short signed sizeof static static_cast struct switch template this throw true try typedef typeid typename union unsigned using virtual void volatile wchart_t while
2-9
C++ Basics
The following sections explain some fundamental C++ programming concepts and techniques.
Function Prototypes
A function prototype consists of the return type, the identier of the function, and the types of parameters that the function expects. This allows type checking at compile and link time. In C++, you must dene or prototype every function before it is used. To inform the compiler that you are invoking a C function instead of a C++ function, the function prototype must use the extern linkage directive.You specify the linkage directive at le scope as follows: extern "C" int myCfunc(char *a1, char * a2); If the function takes a variable number of arguments, the ellipsis points (...) are used in the argument list and the varargs function is used to process the variable number of arguments.
2-10
2
Variable Declarations Not at the Top of Blocks
In C++, you can declare variables anywhere before they are rst used in the program. The scope of such variables is after their declaration, within the block of their declaration.
2-11
2
The following code example illustrates function prototypes, declarations, and the void data type. 1 #include <stdio.h> 2 3 main() { 4 void display(int); 5 6 int x = 1; 7 display(x); 8 9 for(int i = 0; i < 3; i++) { 10 int y = x + i; 11 display(y); 12 } 13 return 0; 14 } 15 16 17 void display(int num) { 18 printf("Value in display = %d\n", num); 19 }
Output
Value Value Value Value in in in in display display display display = = = = 1 1 2 3
Code 2-1
2-12
End-of-line Comments //
You can insert comments into a program line, or comment out program lines, by using two forward slashes (//). Everything to the right of the // characters is ignored by the preprocessor. You can also place end-of-line comments within a block-style comment, letting you nest comments. (Block-style comments cannot be nested within blockstyle comments.)
2-13
2
Inline Functions
Inline functions are what C++ uses instead of #define macros. Write the macro as a function (with return type, declared parameters, and code within the opening and closing curly braces). Place the inline keyword at the front of the denition. The inline function:
G G G G
Saves function call overhead but increases code size Is intended for small, frequently called functions Provides full type checking of arguments Is normally placed in header les
The inline function is a hint to the compiler. The function might not actually get expanded inline. Use the +w compiler option to check.
2-14
2
The following code example includes the iostream library (using #include <iostream.h>), allowing access to the cout and endl library calls. The example also shows end-of-line comments and an inline function. 1 /* program to illustrate difference between macros and inline 2 ** functions. 3 */ 4 5 #include <iostream.h> 6 7 inline int MAX(int a, int b) { return a > b ? a : b; } 8 #define min(a, b) a < b ? a : b 9 10 main() { 11 int x = 10, y = 20; // give x and y initial values 12 13 cout << "x = " << x << " y = " << y << endl; 14 cout << "Inline max: MAX(x,y) = " << MAX(x++, y++) << endl; 15 cout << "After max x = " << x << " y = " << y << endl; 16 17 x = 10; y = 20; // reinitalize x and y 18 cout << "x = " << x << " y = " << y << endl; 19 cout << "Macro min: min(x,y) = " << (min(x++, y++)) << endl; 20 cout << "After min x = " << x << " y = " << y << endl; 21 return 0; 22 }
Output
x = 10 y = 20 Inline max: MAX(x,y) = 20 After max x = 11 y = 21 x = 10 y = 20 Macro min: min(x,y) = 11 After min x = 12 y = 21
Code 2-2
2-15
2-16
2
If the data type in the input stream does not match the data type requested, the cin object is placed in an error state and data is not transferred. Error handling is described in Module 8, Templates, Exception Handling, and Tools.h++. Note In Code 2-3, there is no address operator (&). Unlike the scanf function, you do not have to use the address operator.
2-17
2
The following code example illustrates tagnames as data types, the cin object, and the new and delete operators. 1 #include <iostream.h>// for cin and cout 2 #include <string.h>// for strlen() and strcpy() 3 4 struct Employee { 5 int number; 6 char *name; 7 }; 8 9 main() { 10 Employee emp;// all user-defined data 11 // types may use the tagname 12 // as a typename after definition 13 14 cout << "Enter employee number: "; 15 cin >> emp.number; 16 17 char buf[80]; 18 cout << "Enter employees last name: "; 19 cin >> buf; 20 21 // allocate memory for employee name 22 emp.name = new char[strlen(buf) + 1]; 23 strcpy(emp.name, buf); 24 25 cout << emp.name << "s number is: "; 26 cout << emp.number << endl; 27 28 delete [] emp.name;// release allocated memory 29 return 0; 30 }
Output
Enter employee number: 28 Enter employee's last name: Taylor Taylor's number is: 28
Code 2-3
2-18
2-19
2
To resolve a call to an overloaded function, there is a set of matching rules that are applied to the call. The resolution can result in an exact match, no match, or an ambiguous match. An ambiguous match or no match is a compile time error. The following are simplied argument matching rules:
G G G
Actual argument must match exactly. If there is no exact match, try promotion: char -> short -> int. If there is no match through promotion, try the standard conversion: int -> double, float -> int (both widening and narrowing)
2-20
2
The following code example illustrates function overloading. 1 #include <iostream.h> 2 3 main() { 4 void display(int, double);//function #1 5 void display(int);//function #2 6 void display(double, int);//function #3 7 8 display(1, 2.5);//invokes function #1 9 display(2);//invokes function #2 10 display(2.5, 1);//invokes function #3 11 display(2.5);//invokes function #2 with 12 //warning 13 //display(1,2);//which function is invoked? 14 return 0; 15 } 16 17 void display(int a, double b) { 18 cout << "function #1 called: " << a << " " << b << endl; 19 } 20 21 void display(int a) { 22 cout << "function #2 called: " << a << endl; 23 } 24 25 void display(double a, int b) { 26 cout << "function #3 called: " << a << " " << b << endl; 27 }
Output
function function function function #1 #2 #3 #2 called: called: called: called: 1 2.5 2 2.5 1 2
Code 2-4
Function overloading
2-21
Constants
You can declare any data type a constant with the const keyword. You must initialize constants upon declaration, and you can never change a constant. A constant data type is preferred to using preprocessor denes.
Pointers to Constants
You can declare pointers to constant data. The data referenced by this pointer cannot be changed through this pointer, although you can set the pointer itself to point to a different memory location. The address of constant data can be assigned only to a pointer-to-constant data type.
2-22
2
Constant Pointers
You can declare a constant pointer. The data referenced through the pointer can change, but the pointer always points to the same memory location. This is like declaring an array in the C programming language.
Constant Parameters
If a parameter is declared to be const in the parameter list, it cannot be changed within the function that receives it. The state of being constant is in effect only during the execution of the function. The value that is passed in might be constant in another scope.
2-23
2
The following code example illustrates the use of constants. 1 #include <iostream.h> 2 3 main() { 4 const int ASIZE = 20; 5 6 char title[] = "C++ Programming"; 7 void display(const char *, int); 8 9 //ASIZE = 10;// error 10 11 const char *pc = "hello";// ptr to constant data 12 //pc[0] = A;// error 13 pc = title; 14 15 char *const cp = title;// constant ptr 16 cp[0] = D; 17 //cp = "Smalltalk";// error 18 19 const char *const cpc = title;// constant ptr to 20 // constant data 21 //cpc[0] = A;// error 22 //cpc = "Lisp";// error 23 24 25 display(title, 3); 26 return 0; 27 } 28 29 void display(const char *str, int count) { 30 for(int i = 0; i < count; i++) 31 cout << str[i] << endl; 32 33 //str[0] = A;// error 34 }
Output
D + +
Code 2-5
Constants
2-24
References
A variable declaration allocates memory and associates a name with the memory. For example, the declaration int i; allocates space for an integer and gives it the name i. Using a reference is a way to create a new name for an existing piece of data. For example, the declaration int &j = i; creates j as a second name for the integer i. You do not have to have two names for one variable in one function, so references are commonly used as function parameters and return values. If a parameter is passed to a function as a reference data type, then anything that the function does to the parameter affects the argument that is passed into the function. C simulates a call by reference with pointers. void function1(int); // receives only a copy of the // integer void function2(int &); // receives a reference to the // integer and can make // changes to the integer that // is passed in
2-25
2
Both functions can be called in exactly the same way. int x = 41; function1(x); // passes the value of x function2(x); // passes a reference to x You can use a reference to avoid making a copy of data (if that data is large, such as a large structure). It is as efcient as passing a pointer but the syntax is simpler. Calls to functions that take reference parameters look just like functions that take parameters by value. A function can have the efciency of a reference parameter and ensure that it does not change the data that is referenced by also declaring the parameter as a const.
2-26
2
The following code example illustrates references. 1 #include <iostream.h> 2 3 void swap1(int a, int b) { 4 int temp; temp = a; a = b; 5 } 6 7 void swap2(int *a, int *b) { 8 int temp; temp = *a; *a = *b; 9 } 10 11 void swap3(int &a, int &b) { 12 int temp; temp = a; a = b; 13 } 14 15 main() { 16 17 int x = 5, y = 10; 18 19 cout << "Initial values: " << x << 20 swap1(x, y); 21 cout << "After swap 1: " << x << " 22 swap2(&x, &y); 23 cout << "After swap 2: " << x << " 24 swap3(x, y); 25 cout << "After swap 3: " << x << " 26 return 0; 27 }
b = temp;
*b = temp;
b = temp;
" " << y << endl; " << y << endl; " << y << endl; " << y << endl;
Output
Initial values: 5 10 After swap 1: 5 10 After swap 2: 10 5 After swap 3: 5 10
Code 2-6
References
2-27
2-28
2
The following code example illustrates a function with default parameter values. 1 #include <iostream.h> 2 3 main() { 4 void print_ch(const char*, int = 0); 5 void setSize(int = 24, int = 80); 6 7 setSize(10, 40); 8 setSize(); 9 print_ch("hello", 3); 10 print_ch("Sun"); 11 } 12 13 void print_ch(const char*word, int index) { 14 cout << "word = " << word << " index = " << index 15 << " char = " << word[index] << endl; 16 } 17 18 void setSize(int height, int width) { 19 cout << "height = " << height << " width = " << width << endl; 20 }SL240_LF
Output
height height word = word = = 10 width = 40 = 24 width = 80 hello index = 3 char = l Sun index = 0 char = S
Code 2-7
2-29
Void Pointers
Void pointers are pointers that can point to any data type. However, they cannot be de-referenced or assigned to a pointer of another data type without an explicit type cast.
2-30
2
The following code example illustrates void pointers. 1 #include <iostream.h> 2 main() { 3 int x = 5; 4 float y = 32.8; 5 6 void *v_ptr; 7 int *i_ptr; 8 float *f_ptr; 9 10 f_ptr = &y; // OK 11 i_ptr = &x; // OK 12 13 // f_ptr = &x; Error 14 // i_ptr = &y; Error 15 16 v_ptr = &x; // OK 17 v_ptr = &y; // OK 18 19 cout << *f_ptr << \n << *i_ptr << endl; 20 21 // cout << *v_ptr << endl; Error 22 23 cout << *(float *)v_ptr << endl; 24 25 v_ptr = i_ptr; // OK 26 v_ptr = f_ptr; // OK 27 28 float *other_ptr; 29 // other_ptr = v_ptr; Error 30 31 other_ptr = (float *)v_ptr; 32 return 0; 33 }
Output
32.8 5 32.8
Code 2-8
Void pointers
2-31
2-32
2
The following code example illustrates functional type casting. 1 #include <iostream.h> 2 3 main() { 4 5 int x=3, y=10; 6 float result; 7 8 result = y / x; 9 cout << result << endl; 10 11 result = (float)y / x; 12 cout << result << endl; 13 14 result = float(y) / x; 15 cout << result << endl; 16 return 0; 17 }
Output
3 3.33333 3.33333
Code 2-9
2-33
2
Exercises
Exercise objectives In the exercises for this module, which are located in the Module2 folder online, you will:
G G
Familiarize yourself with the C++ environment. Compile a program using correct C++ command-line arguments. Convert a program from C to C++, compile, and successfully troubleshoot. Overload functions and pass parameters by reference. Anticipate compiler errors for a program that tries to modify a constant. Modify a C program so that it will compile with the C++ compiler.
G G
2-34
2
Exercises Summary
Discussion Take a few minutes to discuss what experiences, issues, or discoveries you had during the lab exercises.
Manage the discussion here based on the time allowed for this module, which was given in the About This Course module. If you find you do not have time to spend on discussion, highlight just the key concepts students should have learned from the lab exercise.
G
Experiences
Ask students what their overall experiences with this exercise have been. Go over any trouble spots or especially confusing areas at this time.
G
Interpretations
Ask students to interpret what they observed during any aspects of this exercise.
G
Conclusions
Have students articulate any conclusions they reached as a result of this exercise experience.
G
Applications
Explore with students how they might apply what they learned in this exercise to situations at their workplace.
2-35
2
Check Your Progress
Before continuing on to the next module, check that you are able to accomplish or answer the following: K K K K K Discuss the history and evolution of C++ Locate the Sun C++ software les that are provided Write the command-line syntax and use the C++ compiler with some of its more useful options Explain the basic features of the C++ language Use the basic C++ features in lab exercises
2-36
2
Think Beyond
How do you create classes and objects in C++?
2-37
Introduction to Classes
Objectives
Upon completion of this module, you will be able to:
G G G G G G G
Dene the concept, purpose, and syntax of a class Declare functions as members of a struct or class Protect class members with access regions Dene member functions Explain how objects are stored in memory Use the this pointer Dene constructors and destructors
3-1
Copyright 1999 Sun Microsystems, Inc. All Rights Reserved. Enterprise Services Nov. 1999, Revision H
3
Relevance
Present the following questions to stimulate the students and get them thinking about the issues and topics presented in this module. While they are not expected to know the answers to these questions, the answers should be of interest to them and inspire them to learn the material presented in this module.
Discussion How do you build a class in C++? How do you store objects in and remove them from memory?
3-2
Introduction to Classes
Copyright 1999 Sun Microsystems, Inc. All Rights Reserved. Enterprise Services Nov. 1999, Revision H
3-3
3-4
3
The following code examples show implementations of struct. 1 #include <iostream.h> 2 3 struct Date { 4 int month; 5 int day; 6 void display(void) { cout << month << "/" << day << endl; } 7 }; 8 9 main() { 10 11 Date today; 12 13 today.month = 6; 14 today.day = 3; 15 today.display(); 16 17 Date *holiday = new Date; 18 19 holiday->month = 1; 20 holiday->day = 1; 21 holiday->display(); 22 23 delete holiday; 24 return 0; 25 }
Output
6/3 1/1
Code 3-1
Introduction to Classes
Copyright 1999 Sun Microsystems, Inc. All Rights Reserved. Enterprise Services Nov. 1999, Revision H
3-5
3
1 #include <iostream.h> 2 3 struct Date { 4 int day; 5 int month; 6 void display(void) { 7 cout << month << "/" << day << endl; 8 } 9 void setDate(int m, int d) { month = m; day = d; } 10 int get_month(void) { return month; } 11 int get_day(void) { return day; } 12 13 }; 14 15 main() { 16 Date hiredate; 17 18 hiredate.setDate(2, 24); 19 hiredate.display(); 20 21 hiredate.month = 10; // this is still allowed 22 hiredate.day = 1; // this is still allowed 23 24 cout << "hire date month is " << hiredate.get_month() 25 << "\nhire date day is " << hiredate.get_day() 26 << endl; 27 return 0; 28 }
Output
2/24 hire date month is 10 hire date day is 1
Code 3-2
3-6
Introduction to Classes
Copyright 1999 Sun Microsystems, Inc. All Rights Reserved. Enterprise Services Nov. 1999, Revision H
3-7
3
Access Region Syntax
To assign access regions to members, use the name of the access region in the class denition followed by a colon (a label). Following are examples for struct and class denitions. struct A { public: // this is optional since public is default public members here private: private members here };
class A { private: // this is optional since private is default private members here public: public members here };
Default Access
If you do not specify an access keyword for a member or group of members, the following rules apply.
G G
Class members default to private. Structure and union members default to public.
3-8
3
The following code example shows private and public access regions in a class denition. 1 #include <iostream.h> 2 3 class Date { 4 private: 5 int day; 6 int month; 7 public: 8 void display(void) { cout << month << "/" << day << endl; } 9 void setDate(int m, int d) { month = m; day = d; } 10 int get_month(void) { return month; } 11 int get_day(void) { return day; } 12 13 }; 14 15 main() { 16 Date hiredate; 17 18 hiredate.setDate(2, 24); 19 hiredate.display(); 20 /* 21 hiredate.month = 10; // error 22 hiredate.day = 1; // error 23 */ 24 cout << "hire date month is " << hiredate.get_month() 25 << "\nhire date day is " << hiredate.get_day() 26 << endl; 27 return 0; 28 }
Output
2/24 hire date month is 2 hire date day is 24
Code 3-3
Introduction to Classes
Copyright 1999 Sun Microsystems, Inc. All Rights Reserved. Enterprise Services Nov. 1999, Revision H
3-9
3-10
3
The following code example shows implicit inline functions. Code 3-5 shows the more common method of dening member functions outside of the class denition. 1 #include <iostream.h> 2 3 class Date { 4 int month; 5 int day; 6 7 // private helper functions 8 void print_day(void) { cout << day; } 9 void print_month(void) { cout << month; } 10 11 public: 12 void set_month(int m) { month = m; } 13 void set_day(int d) { day = d; } 14 void display(void) { 15 print_month(); cout << "/"; print_day(); cout << endl; 16 } 17 }; 18 19 main() { 20 21 Date payday; 22 23 payday.set_month(5); 24 payday.set_day(1); 25 26 payday.display(); 27 return 0; 28 29 }
Output
5/1
Code 3-4
Implicit inline
Introduction to Classes
Copyright 1999 Sun Microsystems, Inc. All Rights Reserved. Enterprise Services Nov. 1999, Revision H
3-11
Class denitions in a .h le Member function denitions in a .cc le Header guards are in the .h le to prevent multiple inclusions
You typically provide the users of your class with the header les (.h) and the object code for the member functions. The object code is usually packaged into a library to separate the implementation from the interface.
3-12
3
The following code examples show member functions dened outside the class denition.
Date.h
1 2 3 4 5 6 7 8 9 10 #ifndef DATE_H #define DATE_H class Date { int day; int month; public: void display(void); void setDate(int, int); }; #endif
Date.cc
1 2 3 4 5 6 7 8 9 10 #include <iostream.h> #include "Date.h" void Date::display(void) { cout << month << "/" << day << endl; } void Date::setDate(int m, int d) { month = m; day = d; }
MyAppl.cc
1 2 3 4 5 6 7 8 9 10 #include <iostream.h> #include "Date.h" main() { Date hiredate; hiredate.setDate(2, 24); hiredate.display(); return 0; } Member Functions Outside the Class Denition
Code 3-5
Introduction to Classes
Copyright 1999 Sun Microsystems, Inc. All Rights Reserved. Enterprise Services Nov. 1999, Revision H
3-13
Object Storage
All member functions are stored in the text segment of memory (one copy only). Data members for each object are stored in one of the following:
G G G
Stack Local objects Data Segment Static and global objects Heap Dynamically allocated objects
3-14
3
Stack frames
month day Data Segment payday month day Text Segment Date::display Date::setDate
Introduction to Classes
Copyright 1999 Sun Microsystems, Inc. All Rights Reserved. Enterprise Services Nov. 1999, Revision H
3-15
3
The following code example shows memory storage locations. 1 #include <iostream.h> 2 class Date { 3 int month; 4 int day; 5 public: 6 void setDate(int m, int d) { month = m; day = d; } 7 void display(void) { cout << month << "/" << day << endl; } 8 }; 9 10 Date payday; // in Data Segment 11 12 main() { 13 Date holiday; // in Stack 14 Date *today = new Date; // in Heap 15 16 cout << "& of static object: (payday)" << (void *)&payday << endl; 17 cout << "& of local object: (holiday)" << (void *)&holiday << endl; 18 cout << "& of dynamic object: (today)" << (void *)today << endl; 19 20 }
Output
& of static object: (payday) & of local object: (holiday) & of dynamic object: (today) 67adc effff464 69020
Code 3-6
Object storage
3-16
Introduction to Classes
Copyright 1999 Sun Microsystems, Inc. All Rights Reserved. Enterprise Services Nov. 1999, Revision H
3-17
3
and: Date day; day.display(); becomes: Date day; Date::display(&day); Note this is a reserved keyword in C++.
3-18
3
Sometimes it is necessary to use the this pointer explicitly within a member function. The following code example illustrates this. 1 #include <iostream.h> 2 3 class Date { 4 int month; 5 int day; 6 public: 7 void setDate(int m, int d) { month = m; day = d; } 8 void display(void) { cout << month << "/" << day << endl; } 9 void which_day(void); 10 }; 11 12 void Date::which_day(void) { 13 int day = 10; 14 cout << "(local block) " << day << endl; 15 cout << "(class member) " << this->day << endl; 16 } 17 18 main() { 19 20 Date today; 21 22 today.setDate(1, 5); 23 today.which_day(); 24 return 0; 25 }
Compiler Result
example7.cc, line 13: Warning: day hides Date::day.
Output
(local block) 10 (class member) 5
Code 3-7
Introduction to Classes
Copyright 1999 Sun Microsystems, Inc. All Rights Reserved. Enterprise Services Nov. 1999, Revision H
3-19
Constructors
Constructors are special member functions that are called automatically when an object is created. Constructors are used to initialize the data members of the object. Constructors may not be called explicitly through an object. The standard abbreviation for a constructor is ctor. Constructor characteristics are:
G G
A constructors identier is the same as the classs tagname. Constructors can not return a value or declare any return type, not even void. If only one constructor is declared and it takes two arguments, you must provide two values when declaring an object of that type. If a constructor exists, it invoked when an object is declared.
3-20
3
The following code example shows a constructor. 1 #include <iostream.h> 2 class Fraction { 3 int numer; 4 int denom; 5 public: 6 Fraction(int, int); // constructor 7 void display(void) { cout << numer << "/" << denom << endl; } 8 }; 9 Fraction::Fraction(int n, int d) { 10 numer = n; 11 denom = d; 12 } 13 14 main() { 15 Fraction x(1, 2); // constructor called 16 x.display(); 17 return 0; 18 }
Output
1/2
Code 3-8
Constructor
Introduction to Classes
Copyright 1999 Sun Microsystems, Inc. All Rights Reserved. Enterprise Services Nov. 1999, Revision H
3-21
Overloading Constructors
C++ lets you create multiple constructors with the same name as long as they have different sets of parameters. This is called overloading constructors. It is a useful technique to initialize class objects in a variety of ways.
3-22
3
The following code example shows overloaded constructors. 1 #include <iostream.h> 2 3 class Fraction { 4 int numer; 5 int denom; 6 public: 7 Fraction(void); 8 Fraction(int); 9 Fraction(int, int); 10 void display(void) { cout << numer << "/" << denom << endl; } 11 }; 12 Fraction::Fraction(void) { numer = 0; denom = 1; } 13 Fraction::Fraction(int n) { numer = n; denom = 1; } 14 Fraction::Fraction(int n, int d) { numer = n; denom = d; } 15 16 main() { 17 Fraction f1(3,5); // automatically initializes f1 to 3/5 18 Fraction f2; // same as f2(0) or f2(0, 1) 19 Fraction f3(4); // same as f3(4) or f3(4,1) or f3 = 4 20 Fraction f4(f2); // make a copy of f2 21 Fraction f5(); // f5 is a function 22 23 f1.display(); 24 f2.display(); 25 f3.display(); 26 f4.display(); 27 }
Output
3/5 0/1 4/1 0/1 Code 3-9 Overloading constructors
Introduction to Classes
Copyright 1999 Sun Microsystems, Inc. All Rights Reserved. Enterprise Services Nov. 1999, Revision H
3-23
3-24
3
The following code example shows default values set for a constructor. 1 #include <iostream.h> 2 3 class Fraction { 4 int numer; 5 int denom; 6 public: 7 Fraction(int n=0, int d=1) { numer = n; denom = d; } 8 void display(void) { cout << numer << "/" << denom << endl; } 9 }; 10 11 main() { 12 Fraction f1; // numer=0, denom=1 13 Fraction f2(3); // numer=3, denom=1 14 Fraction f3(5, 2); // numer=5, denom=2 15 16 cout << "f1: "; f1.display(); 17 cout << "f2: "; f2.display(); 18 cout << "f3: "; f3.display(); 19 return 0; 20 }
Output
f1: f2: f3: Code 3-10 0/1 3/1 5/2
Introduction to Classes
Copyright 1999 Sun Microsystems, Inc. All Rights Reserved. Enterprise Services Nov. 1999, Revision H
3-25
For statically declared objects, use a comma-separated list of values in braces in the array declaration. You must use the same number of values as there are array elements (objects). If the array is dynamically allocated, no constructor values can be provided (new cannot initialize arrays of any type) and there must be a constructor that takes zero arguments or all defaults.
3-26
3
The following code example shows an array of constructors being initialized. 1 #include <iostream.h> 2 class Fraction { 3 int numer; 4 int denom; 5 public: 6 Fraction(int n = 0, int d = 1) { numer = n; denom = d; } 7 void setFract(int n, int d) { numer = n; denom = d; } 8 void display(void) { cout << numer << "/" << denom << endl; } 9 }; 10 11 main() { 12 const int SIZE = 3; 13 Fraction a[SIZE] = { 14 Fraction(3,5), 15 Fraction(6), 16 Fraction(2,9) 17 }; 18 Fraction *ptr; 19 20 ptr = new Fraction[SIZE]; 21 ptr[0].setFract(32, 35); 22 ptr[2].setFract(72, 71); 23 24 for (int i=0; i<SIZE; i++) 25 a[i].display(); 26 cout << endl; 27 for (int i=0; i<SIZE; i++) 28 ptr[i].display(); 29 30 delete [] ptr; 31 } 32
Introduction to Classes
Copyright 1999 Sun Microsystems, Inc. All Rights Reserved. Enterprise Services Nov. 1999, Revision H
3-27
3
Output
3/5 0/1 2/9 32/35 0/1 72/71 Code 3-11 Initializing Arrays of Objects
3-28
Destructors
Destructors are special member functions that are used to clean up when an object of that type goes out of scope. Cleaning up can involve releasing memory allocated to an object, ushing input/output (I/O) buffers, or closing les. The standard abbreviation for a destructor is dtor.
G
Destructors are called automatically when an object of the class goes out of scope. Destructors can be called explicitly, which can be useful for reinitialization. Destructors are invoked in the reverse order of constructors.
Introduction to Classes
Copyright 1999 Sun Microsystems, Inc. All Rights Reserved. Enterprise Services Nov. 1999, Revision H
3-29
3
~tagname()
Destructors are member functions whose identier is the same as the class tagname preceded by a tilde (~).
No Overloading
Destructors cannot take any arguments. Therefore, destructors cannot be overloaded.
No Return Type
Like constructors, destructors cannot return any value or specify any return type.
No Default
There is no default destructor. You must provide a destructor to free any memory or perform other cleanup for the object.
3-30
3
The following code example shows how a destructor is used. 1 #include <iostream.h> 2 #include <string.h> 3 4 class String { 5 int len; 6 char *string; 7 public: 8 String(const char *); 9 ~String(void); 10 void display(void) { cout << string << endl; } 11 }; 12 13 String::String(const char *s) { 14 len = strlen(s); 15 string = new char[len+1]; 16 strcpy(string, s); 17 } 18 19 String::~String(void) { 20 delete [] string; 21 cout << "destructor called" << endl; 22 } 23 24 main() { 25 26 String lang("English"); 27 lang.display(); 28 cout << "end of main" << endl; 29 30 } // object goes out of scope, destructor is called
Output
English end of main destructor called
Code 3-12
Destructor
Introduction to Classes
Copyright 1999 Sun Microsystems, Inc. All Rights Reserved. Enterprise Services Nov. 1999, Revision H
3-31
3
An Example and a Problem
Destructors for objects allocated using new are not called unless the objects are explicitly freed using the delete operator. The syntax for this is delete ptr;. To indicate to the delete operator that the pointer addresses an array, the following syntax is required: String *words = new String[3]; ... delete [] words; This ensures that the destructor is invoked once for each element of the array.
3-32
3
The following code example shows an incorrect use of a destructor. 1 #include <iostream.h> 2 #include <string.h> 3 4 class String { 5 int len; 6 char *string; 7 public: 8 String(char * = "default"); 9 ~String(void); 10 }; 11 12 String::String(char *s) { 13 string = new char[len = strlen(s) + 1]; 14 strcpy(string, s); 15 } 16 String::~String(void) { 17 cout << "destructor called with " << string << endl; 18 delete [] string; 19 } 20 21 main() { 22 String a("first string"); 23 String *ptr = new String("pointer"); 24 String numbers[] = { "one", "two" }; 25 String *words = new String[3]; 26 27 delete ptr; 28 delete words; 29 }
Initial Output
destructor destructor destructor destructor called called called called with with with with default two one first string
Introduction to Classes
Copyright 1999 Sun Microsystems, Inc. All Rights Reserved. Enterprise Services Nov. 1999, Revision H
3-33
3
After making corrections, the initial output changes to:
Code 3-13
3-34
3
Exercises
Exercise objectives In the exercises for this module, which are located in the Module3 folder online, you will:
G
Use encapsulation to dene a private access area in a program, initialize an object using a constructor, and create a function that can access and output the private data. Dene classes with necessary members. Initialize an array of objects, provide necessary output, and use destructors to free memory.
Introduction to Classes
Copyright 1999 Sun Microsystems, Inc. All Rights Reserved. Enterprise Services Nov. 1999, Revision H
3-35
3
Exercises Summary
Discussion Take a few minutes to discuss what experiences, issues, or discoveries you had during the lab exercises.
Manage the discussion here based on the time allowed for this module, which was given in the About This Course module. If you find you do not have time to spend on discussion, then just highlight the key concepts students should have learned from the lab exercise.
G
Experiences
Ask students what their overall experiences with this exercise have been. You may want to go over any trouble spots or especially confusing areas at this time.
G
Interpretations
Ask students to interpret what they observed during any aspects of this exercise.
G
Conclusions
Have students articulate any conclusions they reached as a result of this exercise experience.
G
Applications
Explore with students how they might apply what they learned in this exercise to situations at their workplace.
3-36
3
Check Your Progress
Before continuing on to the next module, check that you are able to accomplish or answer the following: K K K K K K K Dene the concept, purpose, and syntax of a class Declare functions as members of a struct or class Protect class members with access regions Dene member functions Explain how objects are stored in memory Use the this pointer Dene constructors and destructors
Introduction to Classes
Copyright 1999 Sun Microsystems, Inc. All Rights Reserved. Enterprise Services Nov. 1999, Revision H
3-37
3
Think Beyond
How do classes interact with each other?
3-38
Write a copy constructor Write friend functions Write classes with special types of members Enclose objects as data members Dene static, constant, and reference data members Dene static and constant member functions Declare constant objects Discuss C++ scoping rules
4-1
Copyright 1999 Sun Microsystems, Inc. All Rights Reserved. Enterprise Services Nov. 1999, Revision H
4
Relevance
Present the following questions to stimulate the students and get them thinking about the issues and topics presented in this module. While they are not expected to know the answers to these questions, the answers should be of interest to them and inspire them to learn the material presented in this module.
Discussion How do you construct classes and have them interact so that they maintain the types of relationships you defined in the analysis phase of development? What object-oriented techniques can you use to ensure software reuse and ease of maintenance?
4-2
An object is declared and initialized with the contents of an existing object. An object is passed as a parameter to a function by value. It is copied onto the stack. An object is returned from a function by value. It is copied onto the stack.
The default copy constructor provides memberwise copying, also called a shallow-copy." If the object being copied contains pointers, it is the pointer that is copied and not the data being pointed to. You can override the default copy constructor. For example, using the String class and the default copy constructor: String a("C++ Program");// calls (char *) constructor String *b = new String(a); // calls copy constructor
4-3
4
The following code example shows the use of a default copy constructor. 1 #include <iostream.h> 2 #include <string.h> 3 4 class String { 5 int len; 6 char *string; 7 public: 8 String(char *s = "") { 9 len = strlen(s) + 1; 10 string = new char[len]; strcpy(string, s); 11 cout << "Memory for (" << string << ") allocated at " 12 << (void *) string << endl; 13 } 14 ~String(void) { 15 cout << "Memory for (" << string << ") freed at " 16 << (void *) string << endl; 17 strcpy(string, "deleted"); 18 delete [] string; 19 } 20 void display(void) { cout << string << endl; } 21 }; 22 main() { 23 String a("C++ Program"); // constructor (char *) 24 cout << "Displaying 'a': "; a.display(); 25 String *b = new String(a); // copy constructor 26 delete b; 27 cout << "Displaying 'a' after copy: "; a.display(); 28 cout << "End of main\n"; 29 }
Output
Memory for (C++ Program) allocated at 0x20f30 Displaying 'a': C++ Program Memory for (C++ Program) freed at 0x20f30 Displaying 'a' after copy: deleted End of main Memory for (deleted) freed at 0x20f30
Code 4-1
4-4
4-5
4
The following code examples shows an explicitly written copy constructor. 1 #include <iostream.h> 2 #include <string.h> 3 4 class String { 5 int len; 6 char *string; 7 void init(const char *, int); 8 public: 9 String(char *s = "") { init(s, strlen(s) + 1); } 10 String(const String &s) { init(s.string, s.len); } 11 ~String(void) { 12 cout << "Memory for (" << string << ") freed at " 13 << (void *) string << endl; 14 strcpy(string, "deleted"); 15 delete [] string; 16 17 void display(void) { cout << string << endl; } 18 }; 19 20 void String::init(const char *s, int size) { 21 len = size; 22 string = new char[len]; 23 strcpy(string, s); 24 cout << "Memory for (" << string << ") allocated at " 25 << (void *) string << endl; 26 } 27 28 main(){ 29 String a("C++ Program"); // constructor (char *) 30 cout << "Displaying 'a': "; a.display(); 31 String *b = new String(a); // copy constructor 32 delete b; 33 cout << "Displaying 'a' after copy: "; a.display(); 34 cout << "End of main\n"; 35 }
4-6
4
Output
Memory for (C++ Program) allocated at 0x20f70 Displaying 'a': C++ Program Memory for (C++ Program) allocated at 0x20f88 Memory for (C++ Program) freed at 0x20f88 Displaying 'a' after copy: C++ Program End of main Memory for (C++ Program) freed at 0x20f70 Code 4-2 Writing a Copy Constructor
4-7
Friend Functions
Friend functions enable non-member functions to access the private parts of a class. Friend functions are commonly used with operator overloading, or when a function needs to access objects in two classes. (Operator overloading is discussed in Module 5, Operator Overloading and Type Conversions.) A class species the friendship relationship by placing the function prototype of the friend in the class, preceding the prototype with the friend keyword. Friend functions do not get a this pointer because they are not members of the class and they are invoked like normal functions. To access the private elements, a class object must be a parameter of the friend function.
4-8
4
A class can also be a friend to another class. All the functions in the friend class can access the private elements of another class. This is useful when class objects are managed by another class. Following is a friend function declaration: class Otherclass { ... public: void function(Data &) { ... } }; class Data { int x; float y; public: friend void display(const Data &); friend void Otherclass::function(Data &); }; You can also declare an entire class as a friend by making the following declaration in the class: friend class Otherclass; // all member functions in // Otherclass are friends
4-9
4
The following code example illustrates the use of the friend function. 1 #include <iostream.h> 2 3 class Fraction { 4 int numer; 5 int denom; 6 public: 7 Fraction(int n=0, int d=1) { numer = n; denom = d; } 8 void display(void); 9 // add is a friend for the notational convenience 10 friend Fraction add(Fraction &, Fraction &); 11 }; 12 13 void Fraction::display(void) {// member function 14 cout << numer << "/" << denom << endl; 15 } 16 Fraction add(Fraction &f1, Fraction &f2) {// friend function 17 return Fraction(f1.numer * f2.denom + f2.numer * f1.denom, 18 f1.denom * f2.denom); 19 } 20 21 main() { 22 Fraction a(3,8), b(3,4), c; 23 24 cout << "a: "; a.display(); 25 cout << "b: "; b.display(); 26 c = add(a, b);// notation more natural than c = a.add(b) 27 cout << "a + b = "; 28 c.display(); 29 return 0; 30 }
Output
a: 3/8 b: 3/4 a + b = 36/32
Code 4-3
Friend functions
4-10
Constant data type Reference data type Another class object that has a constructor, and either the constructor requires parameters or you want to override the default values
The initialization list syntax is used in the function denition and not in the function declaration.
4-11
4
The following code example illustrates the initialization and assignment phases. 1 #include <iostream.h> 2 3 class Fraction { 4 int numer; 5 int denom; 6 public: 7 Fraction(int n=0, int d=1) :numer(n), denom(d) { } 8 void display(void) { cout << numer << "/" << denom << endl; } 9 }; 10 11 main() { 12 Fraction f1;// numer=0, denom=1 13 Fraction f2(3);// numer=3, denom=1 14 Fraction f3(5,2);// numer=5, denom=2 15 16 cout << "f1: "; f1.display(); 17 cout << "f2: "; f2.display(); 18 cout << "f3: "; f3.display(); 19 return 0; 20 } 21
Output
f1: 0/1 f2: 3/1 f3: 5/2
Code 4-4
4-12
If the inner class objects constructor requires parameters, the initialization syntax must be used in the outer classs constructor. The outer class has no special access to the inner class object. You can place the class denition of an inner class within the class denition of the outer class. This is useful when the inner class is used only by the outer class. When a class contains other objects as data members, the inner object constructors are invoked rst, in the order of declaration, followed by the outer object constructors. Destructors are called in the exact reverse order of the constructor calls.
G G
4-13
4
The following code example illustrates a compositional relationship between classes. 1 #include <iostream.h> 2 3 class Inner { 4 int data; 5 public: 6 char id; 7 void set(int x) { data = x; } 8 Inner(int x){ data = x; } 9 }; 10 11 class Outer { 12 Inner room; 13 public: 14 float total; 15 Outer(int, char); 16 void set(int i, char id) { 17 room.set(i); // can not do room.data = i 18 room.id = id; 19 } 20 }; 21 22 Outer::Outer(int i, char id): room(i) { 23 room.id = id; 24 } 25 26 main() { 27 Outer collect(10, A); 28 29 collect.set(10, B); // can not do collect.room.id = B 30 collect.total = 0.0; // no problem with this 31 } Code 4-5 Composition Objects as data members
4-14
4-15
4
You must initialize constants and reference data members using the constructor initialization list. The following code example shows constant and reference data members. 1 #include <iostream.h> 2 3 class Data { 4 int x; 5 const float y;// must be initialized by constructor 6 int &z; // must be initialized by constructor 7 public: 8 Data(int a, float b, int &num): x(a), y(b), z(num) {} 9 void display(void) {cout << x << " " << y << " " << z << endl;} 10 void increment(void); 11 }; 12 13 void Data::increment(void) { 14 x++; 15 //y++; // Error 16 z++; // OK 17 } 18 19 main() { 20 int num = 99; 21 Data val(3, 9.5, num); 22 23 val.display(); 24 val.increment(); 25 val.display(); 26 27 cout << "num is: " << num << endl; 28 return 0; 29 }
Output
3 9.5 99 4 9.5 100 num is: 100
Code 4-6
4-16
Static Members
When you want objects of a class to share global data members or member functions, make those members static using the static keyword.
Static data members are stored in the data segment (one copy per class) but have class scope. All objects operate on the same copy of the data member. A member function accesses the static data member as it would other data members.
G G
4-17
4
G
To reference the data member from outside a member function, use the class qualier (Class::) followed by the identier in the following situations:
M M M
For the one-time denition of the data member If the member is public From inside a friend function
The following code example illustrates the use of static data members. 1 #include <iostream.h> 2 class Data { 3 int x; 4 static int count; 5 public: 6 Data(int a) { x=a; count++;} 7 ~Data(void) {count--;} 8 int get_count(void); 9 }; 10 11 int Data::get_count(void) { 12 return count; 13 } 14 int Data::count = 0; // definition (allocate space) 15 16 main() { 17 Data item1(10), item2(20), item3(30); 18 19 cout << "Number of items is " << item1.get_count() << endl; 20 Data item4(40); 21 cout << "Number of items is " << item2.get_count() << endl; 22 return 0; 23 }
Output
Number of Number of items is 3 items is 4
Code 4-7
4-18
4
Static Member Functions
The following points apply to static member functions.
G
If a member function needs to access only the static data members of a class, you can dene it as a static member function. Static member functions do not receive a this pointer. Therefore, they cannot access other non-static data members of an object unless that object is passed as an explicit parameter. Static member functions cannot call non-static member functions because they have no this pointer. Non-static member functions require the this pointer to know which object to access. You can invoke static member functions:
M M
4-19
4
The following code example illustrates the use of static member functions. 1 #include <iostream.h> 2 3 class Data { 4 int x; 5 static int count; 6 public: 7 Data(int a) { x=a; count++;} 8 ~Data(void) {count--;} 9 void display(void) { cout << "x = " << x << endl; } 10 static int get_count(void); 11 }; 12 13 /* get_count is a static member function. It can`t call the 14 ** display function because it doesn't have a this pointer 15 ** or an object through which to invoke the function. 16 */ 17 int Data::get_count(void) { 18 return count;// or return Data::count 19 } 20 21 int Data::count = 0;// definition (allocate space) 22 23 main() { 24 Data item1(10), item2(20), item3(30); 25 26 cout << "Number of Data items is " << Data::get_count() 27 << endl; 28 Data item4(40); 29 cout << "Number of Data items is " << item1.get_count() 30 << endl; 31 return 0; 32 }
Output
Number of Number of items is 3 items is 4
Code 4-8
4-20
A compiler error occurs if you attempt to modify a constant object. Constant member functions generate a compiler error if an attempt is made to modify the value of any data members. Member functions that are invoked through a constant object must be identied so that the compiler can determine which functions can be safely invoked. Constant member functions are identied by placing const after the argument list and before the code body.
4-21
4
The following code example illustrates the use of constant objects and constant member functions. 1 #include <iostream.h> 2 3 class Fraction { 4 int numer; 5 int denom; 6 public: 7 Fraction(int n=0, int d=1) :numer(n), denom(d) { } 8 void display(void) const; 9 void invert(void) { 10 int t = numer; numer = denom; denom = t; 11 } 12 }; 13 14 void Fraction::display(void) const { 15 cout << numer << "/" << denom << endl; 16 } 17 18 main() { 19 const Fraction pi(22,7); 20 Fraction radius(5, 2); 21 22 cout << "pi: "; pi.display(); 23 cout << "radius: "; radius.display(); 24 25 //pi.invert();// Error 26 radius.invert(); 27 return 0; 28 }
Output
pi: 22/7 radius: 5/2 Code 4-9 Constant objects and member functions
4-22
The current block is searched rst. If the identier cannot be found, the enclosing block is searched. Each enclosing block is searched until le scope is reached.
4-23
4
C++ Scope Rules
Following are the steps the compiler takes to determine scope for member and non-member functions in C++.
Member Functions
G G G G
The current block is searched rst. If the identier cannot be found, the enclosing block is searched. The members of the class (using the this pointer) are searched. If the identier is not a member of the class, then le scope is searched.
Non-Member Functions
The scope rules are the same as in C (blocks and les):
G G G
The current block is searched rst. If the identier cannot be found, the enclosing block is searched. Each enclosing block is searched until le scope is reached.
:: Scope Operator
Following is the syntax for using the scope operator (::) in the class and le scopes.
4-24
4
The following code example illustrates a function with class scope. 1 #include <iostream.h> 2 3 int x = 42;// file scope 4 5 class Data { 6 int x; 7 public: 8 Data(int a=0) : x(a) {} 9 void scope(void); 10 }; 11 12 void Data::scope(void) { 13 int x = 62; 14 cout << "IN Data::scope()" << endl; 15 cout << "\tx is: " << x << endl; 16 cout << "\tthis->x is: " << this->x << endl; 17 cout << "\t::x is: " << ::x << endl; 18 } 19 20 main() { 21 int x = 33; 22 Data d(9); 23 24 cout << "x is: " << x << endl;// use C scope rules 25 cout << "::x is: "<< ::x << endl;// file scope 26 d.scope(); 27 return 0; 28 }
Compiler Result
example10.cc, line 13: Warning: x hides Data::x.
Output
x is: 33 ::x is: 42 IN Data::scope() x is: 62 this->x is: 9 ::x is: 42 Code 4-10 Function with class scope
4-25
4
Exercises
Exercise objectives In the exercises for this module, which are located in the Module4 folder online, you will:
G G G
Troubleshoot a program while maintaining access rights. Write correct constructors and friend functions. Initialize member variables and display data members.
4-26
4
Exercises Summary
Discussion Take a few minutes to discuss what experiences, issues, or discoveries you had during the lab exercises.
Manage the discussion here based on the time allowed for this module, which was given in the About This Course module. If you find you do not have time to spend on discussion, then just highlight the key concepts students should have learned from the lab exercise.
G
Experiences
Ask students what their overall experiences with this exercise have been. You may want to go over any trouble spots or especially confusing areas at this time.
G
Interpretations
Ask students to interpret what they observed during any aspects of this exercise.
G
Conclusions
Have students articulate any conclusions they reached as a result of this exercise experience.
G
Applications
Explore with students how they might apply what they learned in this exercise to situations at their workplace.
4-27
4
Check Your Progress
Before continuing on to the next module, check that you are able to accomplish or answer the following: K K K K K K K K Write a copy constructor Write friend functions Write classes with special types of members Enclose objects as data members Dene static, constant, and reference data members Dene static and constant member functions Declare constant objects Discuss C++ scoping rules
4-28
4
Think Beyond
How can you use objects to take object orientation a step further?
4-29
Explain the purpose of overloaded operators Identify which operators can and cannot be overloaded Overload operators for user-dened data types using member and friend functions Explain the purpose of type conversions for user-dened data types Use constructors to explicitly and implicitly convert any data type to a user-dened data type Write conversion functions to convert (implicitly or explicitly) a user-dened data type to any other data type
5-1
Copyright 1999 Sun Microsystems, Inc. All Rights Reserved. Enterprise Services Nov. 1999, Revision H
5
Relevance
Present the following question to stimulate the students and get them thinking about the issues and topics presented in this module. While they are not expected to know the answer to this question, the answer should be of interest to them and inspire them to learn the material presented in this module.
Discussion How does C++ let you reuse objects in different ways?
5-2
Overloading Operators
C++ contains a rich library of operators, such as +, -, <<, &, and =. An operator can serve different purposes in code depending on the context in which it is used. For example, you can use the << operator can be used as a left-shift operator or a stream-insertion operator. Multiple uses of operators is called operator overloading. Operators work with the built-in data types. For example, you can the + (addition operator)with built-in data types, such as float, int, or double. For example: int x = 5; int y = 6; int z; z = x + y; // This works.
5-3
5
There is no predened way to add objects of a user-dened data type. Fraction a(4,3); Fraction b(1,2); Fraction c; c = a + b; // Does this work? You can overload both binary and unary operators so that user-dened objects are as easy to use as the built-in data types.
The & operator is overloaded for any data type. The = operator is overloaded for any user-dened data type object that is assigned to another object of the same type. Type_A = Type_A;
For example: Fraction one(6,4), two(3,2); one = two; // This works using memberwise copy // Memberwise copy may not be // desirable when class // data members are pointers since // it does a shallow-copy
5-4
5
Some Rules for Overloading Operators
The following rules apply for overloading operators.
G
You can overload all C++ operators can be overloaded except: . .* :: ?: Structure member operator Pointer to member operator (not covered in this course) Scope qualifying operator Conditional expression operator
G G
You can not dene new operators. You cannot change the way the operators work on the built-in data types. You cannot change the precedence or associativity of operators. You can overload the operator functions. That is, you can dene more that one function for a given operator.
G G
Overloading the addition operator(+) and the assignment operator(=) does not automatically make the operator(+=) work. The overloaded function can be either a member or a friend.
5-5
Member functions receive a this pointer as the rst argument. The this pointer represents the left operand of a binary operator or the only operand of a unary operator. The left operand for a binary operator or the only operand for a unary operator must be an object of the class. Following are the prototypes for operator overloading with member functions: return_type operator<bin_op>(right_operand_type); return_type operator<un_op>(void);
5-6
5
The following code example illustrates overloaded binary operators using member functions. 1 class Fraction { 2 int numer; 3 int denom; 4 public: 5 Fraction(int n = 0, int d = 1):numer(n), denom(d){} 6 Fraction operator+(const Fraction &); 7 Fraction operator+(const int &); 8 }; 9 10 Fraction Fraction::operator+(const Fraction &right) { 11 return Fraction((numer * right.denom + right.numer * denom), 12 denom * right.denom); 13 } 14 15 Fraction Fraction::operator+(const int &right) { 16 return Fraction((denom * right + numer), denom); 17 } 18 19 main() { 20 Fraction f1(5,2), f2(1,2), result; 21 result = f1 + f2; 22 result = f2 + 1; 23 //result = 1 + f1;// error - why? 24 return 0; 25 } Code 5-1 Overloading binary operators with member functions
G
When a member function is used, the call of the function: result = f1 + f2; is translated to: result = f1.operator+(f2); which is syntactically correct.
What can be done to make the following statement work? result = 1 + f1;
5-7
5
Using Friend Functions to Overload
Use the following guidelines when overloading binary operators with friend functions:
G G
At least one operand must be a user-dened object. Friend functions are useful for symmetric binary operators such as (+) because the left operand is not required to be a user-dened object as it is with a member function. The prototypes for overloading operators using friend functions are:
return_type operator<bin_op>(left_operand,right_operand); return_type operator<un_op>(only_operand); The following code example illustrates overloaded binary operators using friend functions.
1 class Fraction { 2 int numer; 3 int denom; 4 public: 5 Fraction(int n = 0, int d = 1):numer(n), denom(d){} 6 friend Fraction operator+ 7 (const Fraction &left,const Fraction &right); 8 }; 9 10 Fraction operator+ 11 (const Fraction &left, const Fraction &right) { 12 return Fraction((left.numer * right.denom + 13 right.numer * left.denom), 14 left.denom * right.denom); 15 } 16 17 main() { 18 Fraction f1(5,2), f2(1,2), result; 19 result = f1 + f2;// still works 20 result = f2 + 1;// why does this work? 21 result = 1 + f1;// now this works 22 return 0; 23 } Code 5-2 Overloading binary operators with friend functions
5-8
5
G
When a friend function is used, the function call: result = f1 + f2; is translated to: result = operator+(f1,f2);
When a friend function is used, the function call: result = 1 + f1; is translated to: result = operator+(Fraction(1),f1);
5-9
If a reference is not used, a copy of the object is passed into the function. Any changes that are made are local to the operator() function. If a reference is used, any changes that are made within the function affect the object that was passed in.
When overloading the (++) or (--), the signature of the postx function must be different from the prex function.
5-10
5
G
The postx operator is dened by specifying a second argument of type integer that can be ignored in the function. This additional argument is transparent to the users of the postx operator.
5-11
5
The following code example illustrates overloading unary operators. 1 #include <iostream.h> 2 class Fraction { 3 int numer; 4 int denom; 5 public: 6 Fraction(int n = 0, int d = 1):numer(n), denom(d) {} 7 Fraction & operator++(void);// prefix operator 8 Fraction operator++(int);// postfix operator 9 void display(void) { 10 cout << numer << "/" << denom << endl; 11 } 12 // defined as friend to show syntax 13 friend Fraction operator--(Fraction &); 14 friend Fraction operator--(Fraction &,int); 15 }; 16 Fraction & Fraction::operator++(void) { 17 // return incremented value 18 numer += denom; 19 return *this; 20 } 21 Fraction Fraction::operator++(int) { 22 // copy for return value before increment 23 Fraction result(*this); 24 numer += denom; 25 return result; 26 } 27 Fraction operator--(Fraction & operand) { 28 operand.numer -= operand.denom; 29 return operand; 30 } 31 Fraction operator--(Fraction & operand, int) { 32 Fraction result(operand); 33 operand.numer -= operand.denom; 34 return result; 35 } 36 37 main() { 38 Fraction f1(5,2), f2(2,3); 39
5-12
5
40 41 42 43 44 45 } (++f1).display(); (f2++).display(); f2.display(); (--f1).display(); (f1--).display();
Output
7/2 2/3 5/3 5/2 5/2
Code 5-3
5-13
Most operator functions can be either a member function or a friend function. The following exceptions must be member functions: = (assignment), [] (subscript), () (function call), and -> (pointer)
A member function requires the left operand to be an object of the class. A friend function requires only that at least one operand be a user-dened object. Friend functions provide more exibility for overloaded operators. When using friend functions, you might need appropriate constructor functions to handle operands of different types.
5-14
Overloading Operator []
Using an overloaded subscript operator [] to return a reference allows the object to be the target of an assignment (lvalue), as illustrated in the following code example.
5-15
5
1 #include <stdlib.h> 2 #include <iostream.h> 3 #include <string.h> 4 5 class String { 6 char *str; 7 public: 8 String(const char* = ""); 9 ~String(void) { delete [] str; } 10 void display(void) { cout << str << endl; } 11 char& operator[](int); 12 }; 13 14 String::String(const char* s) { 15 str = new char[strlen(s) + 1]; 16 strcpy(str, s); 17 } 18 19 char& String::operator[] (int index) { 20 if (index < 0 || index > strlen(str)) { 21 cout << "index out of bounds" << index << endl; 22 exit(1); 23 } 24 return str[index]; 25 } 26 27 main() { 28 String one("Sun Microsystems"); 29 30 cout << one[0] << one[4] << endl; 31 32 one[0] = F; // can be an lvalue because of char& return type 33 one.display(); 34 }
Output
SM Fun Microsystems
Code 5-4
5-16
5-17
5
1 #include <iostream.h> 2 #include <string.h> 3 4 class String { 5 char *string; 6 int length; 7 public: 8 String (const char* = "" ); 9 ~String (void); 10 }; 11 12 String::String(const char* str) { 13 string = new char[length = strlen(str) + 1]; 14 strcpy(string, str); 15 cout << (void*)string << " memory allocated" << endl; 16 } 17 18 String::~String(void) { 19 cout << (void*)string << " memory released" << endl; 20 delete [] string; 21 } 22 23 main() { 24 String one("Sun Microsystems"); 25 26 { 27 String two; 28 two = one; 29 } 30 31 return 0; 32 }
Output
0x22c78 0x230a0 0x22c78 0x22c78 memory memory memory memory allocated allocated released released
Code 5-5
5-18
5-19
5
You should provide a copy constructor because the default copy constructor does memberwise copying. The following example illustrates this. String::String(const String &s) { length = s.length; string = new char[length]; strcpy(string, s.string); }
5-20
Type Conversions
The C++ compiler often has to convert data from one type to another. For example, the compiler might need to convert a short to a double because of a value passed to a function. The compiler knows how to convert built-in types, but you have to tell the compiler how to convert user-dened types. C++ provides two ways to convert user-dened types: the operator type()functions and conversion constructors.
They are always a member function. They have no declared return type. They must return a value of the data type indicated in the function name.
5-21
5
The following code example implements operator type()functions. 1 #include <iostream.h> 2 #include <string.h> 3 4 class String { 5 char * string; 6 int length; 7 public: 8 String(const char * = ""); 9 ~String() { delete [] string; } 10 void display(void) { cout << string << endl; } 11 operator const char*(void); 12 operator int(void) { return length; } 13 }; 14 String::String(const char *str) { 15 string = new char[length = strlen(str)+ 1]; 16 strcpy(string, str); 17 } 18 String::operator const char*(void) { 19 return string; 20 } 21 main() { 22 String topic("Programming"); 23 int x; 24 const char *p; 25 26 p = topic;// convert topic to a const char * 27 x = topic;// convert topic to an int 28 29 cout << p << " is " << x << " characters long" << endl; 30 }
Output
Programming is 12 characters long
Code 5-6
5-22
5
Conversion Constructors
A conversion constructor is any constructor that has been dened for the class that takes at least one parameter. It converts the parameter(s) into an object of the user-dened type. The following guidelines apply to using conversion constructors:
G
Implicit conversions occur when the constructor takes a single parameter. Explicit conversions are allowed for any constructor.
The following code example illustrates the use of a conversion constructor. 1 #include <iostream.h> 2 #include <string.h> 3 4 class String { 5 char *string; 6 int length; 7 public: 8 String(const char* = ""); // converts a char * to a String 9 ~String() { delete [] string; } 10 }; 11 12 String::String(const char *str) { 13 string = new char[length = strlen(str)+ 1]; 14 strcpy(string, str); 15 } 16 17 main() { 18 String topic; 19 20 topic = "C++ Programming"; 21 // This creates a temporary String object by invoking 22 // the (char *) constructor. Then the default assignment 23 // operator (=) makes the assignment from the temporary 24 // String object to the named String object (topic). 25 26 } 27 Code 5-7 Conversion constructors
5-23
5-24
5
The following code example illustrates implicit and explicit casting. 1 class Fraction { 2 int numer; 3 int denom; 4 public: 5 Fraction(int n = 0, int d = 1):numer(n), denom(d){} 6 friend Fraction operator+ 7 (const Fraction &left,const Fraction &right); 8 }; 9 10 Fraction operator+ 11 (const Fraction &left, const Fraction &right) { 12 return Fraction((left.numer * right.denom + 13 right.numer * left.denom), 14 left.denom * right.denom); 15 } 16 17 main() { 18 Fraction f1(5,2), f2(1,2), result; 19 result = f1 + f2; 20 21 // 1 is implicitly converted to a Fraction 22 result = f2 + 1; 23 result = 1 + f1; 24 25 // must use an explicit cast here 26 result = Fraction(1,2) + f2; 27 return 0; 28 } Code 5-8 Implicit and explicit casting
5-25
5-26
5
1 #include <iostream.h> 2 class Number { 3 int x; 4 public: 5 Number (int a = 0) {x=a;} 6 operator int(void) {return x;} 7 }; 8 9 main() { 10 11 Number first(5), second(2); 12 Number third; 13 14 third = first + int(second); 15 16 cout << third << endl; 17 18 return 0; 19 } Code 5-9 Getting the most out of few functions Discussion In Code 5-9:
G G G G
What are the data types of the values being added? How is the value assigned to "third" in the addition statement? How does the cout object print the Number-type object? How many conversions take place?
5-27
5
Exercises
Exercise objectives In the exercises for this module, which are located in the Module5 folder online, you will:
G G
Write functions to overload operators. Determine the order of constructor and operator calls and make improvements. Overload operators and convert data types. Create a small program that reuses objects.
G G
5-28
5
Exercises Summary
Discussion Take a few minutes to discuss what experiences, issues, or discoveries you had during the lab exercises.
Manage the discussion here based on the time allowed for this module, which was given in the About This Course module. If you find you do not have time to spend on discussion, then just highlight the key concepts students should have learned from the lab exercise.
G
Experiences
Ask students what their overall experiences with this exercise have been. You may want to go over any trouble spots or especially confusing areas at this time.
G
Interpretations
Ask students to interpret what they observed during any aspects of this exercise.
G
Conclusions
Have students articulate any conclusions they reached as a result of this exercise experience.
G
Applications
Explore with students how they might apply what they learned in this exercise to situations at their workplace.
5-29
5
Check Your Progress
Before continuing on to the next module, check that you are able to accomplish or answer the following: K K K K K K Explain the purpose of overloaded operators Identify which operators can and cannot be overloaded Overload operators for user-dened data types using member and friend functions Explain the purpose of type conversions for user-dened data types Use constructors to explicitly and implicitly convert any data type to a user-dened data type Write conversion functions to convert (implicitly or explicitly) a user-dened data type to any other data type
5-30
5
Think Beyond
How does C++ let you reuse classes?
5-31
Dene a class derived from another class Create an object of the derived type Use the protected access region Discuss the relationship between base and derived class constructors and how to pass values to base constructors Explain the differences between public base classes and private base classes Illustrate conversions between base and derived classes Explain the purpose of virtual functions and how to create them Identify what makes a pure virtual function and an abstract class and explain when they might be useful
G G G
6-1
Copyright 1999 Sun Microsystems, Inc. All Rights Reserved. Enterprise Services Nov. 1999, Revision H
6
Relevance
Present the following questions to stimulate the students and get them thinking about the issues and topics presented in this module. While they are not expected to know the answers to these questions, the answers should be of interest to them and inspire them to learn the material presented in this module.
Discussion How can one class use the characteristics of another class? How does C++ let you implement the object-oriented concept of polymorphism?
6-2
Single Inheritance
Inheritance is the mechanism for creating a new class that incorporates the features of another class. The denition of the new class (called the derived class) contains all the same data members and member functions as the original class (called the base class). Inheritance is used to model the Is-a relationship where the derived class is a subtype of the base class. This technique allows for code reuse of the shared characteristics. Additional data and functions can be added to the derived class and inherited functions can be redened in the derived class. The derived class inherits all the functions of the base class except for constructors, destructors, and the assignment operator (=). It is not necessary to have the source code of the base class to inherit its characteristics. In single inheritance, the derived class has only one immediate base class. Multiple inheritance is discussed in Module 7, "Multiple Inheritance and Virtual Base Classes.
6-3
6
Inheritance Syntax
Following is the syntax for single inheritance. class Employee { // base class char * name; int id; float salary; public: Employee(/* parameters for Employee constructor*/); void print(void); }; class Manager : public Employee { // inheritance short count; Employee *team[25]; public: Manager(/* parameters for Manager constructor */); void add_employee(Employee *); void print(void); };
6-4
6
The following code example illustrates single inheritance. 1 #include <iostream.h> 2 #include <string.h> 3 4 class Space_body { // Base Class 5 int diameter; 6 public: 7 Space_body(int size = 0) { diameter = size; } 8 void display(void) { 9 cout << diameter << " miles in diameter" << endl; 10 } 11 int get_diameter(void) { return diameter; } 12 }; 13 class Planet : public Space_body { // Derived Class 14 int pos_from_sun; 15 char *name; 16 public: 17 Planet(int num, const char *id) { 18 pos_from_sun = num; 19 name = new char[strlen(id) + 1]; 20 strcpy(name, id); 21 } 22 ~Planet(void) { delete [] name; } 23 void display(void) { 24 cout << name << " is planet # " << pos_from_sun << ", "; 25 Space_body::display(); 26 } 27 }; 28 29 main() { 30 Planet earth(3, "Earth"); 31 Space_body comet(34); 32 33 earth.display(); 34 cout << "Earths diameter is " << earth.get_diameter() << endl; 35 36 cout << "Comet is "; 37 comet.display(); 38 cout << "Comets diameter is " << comet.get_diameter() << endl; 39 }
6-5
6
Output
Earth is planet # 3, 0 miles in diameter Earth's diameter is 0 Comet is 34 miles in diameter Comet's diameter is 34
Code 6-1
Single inheritance
6-6
6-7
6
The following code example implements access regions. 1 #include <iostream.h> 2 #include <string.h> 3 4 class Space_body {// Base Class 5 protected: 6 int diameter; // accessible to derived classes 7 public: 8 Space_body(int size = 0) { diameter = size; } 9 void display(void) { 10 cout << diameter << " miles in diameter" << endl; 11 } 12 int get_diameter(void) { return diameter; } 13 }; 14 class Planet : public Space_body {// Derived Class 15 int pos_from_sun; 16 char *name; 17 public: 18 Planet(int num, const char *id, int size) { 19 pos_from_sun = num; 20 name = new char[strlen(id) + 1]; strcpy(name, id); 21 diameter = size;// assign diameter -- OK, protected 22 } 23 ~Planet(void) { delete [] name; } 24 void display(void) { 25 cout << name << " is planet # " << pos_from_sun << ", "; 26 Space_body::display(); 27 } 28 }; 29 30 main() { 31 Planet earth(3, "Earth", 7926); 32 Space_body comet(34); 33 34 earth.display(); 35 cout << "Earths diameter is " << earth.get_diameter() << endl; 36 37 cout << "Comet is "; 38 comet.display(); 39 cout << "Comets diameter is " << comet.get_diameter() << endl; 40 }
6-8
6
Output
Earth is planet # 3, 7926 miles in diameter Earth's diameter is 7926 Comet is 34 miles in diameter Comet's diameter is 34
Code 6-2
Access regions
6-9
6-10
6
If any of the inherited base class constructors require parameters, the derived class constructors must provide the necessary values using the following initialization list syntax: Derived::Derived(parameter list) : Base(values) { assignments } The formal parameters to the derived constructor can be referenced outside the code block only in the initialization list.
6-11
6
The following code example uses constructors with inheritance. 1 #include <iostream.h> 2 #include <string.h> 3 class Space_body { 4 int diameter; 5 public: 6 Space_body(int size) { diameter = size; } // requires an int 7 void display(void) { 8 cout << diameter << " miles in diameter" << endl; } 9 int get_diameter(void) { return diameter; } 10 }; 11 class Planet : public Space_body { 12 int pos_from_sun; 13 char *name; 14 public: 15 Planet(int num, char *id, int size) : Space_body(size) { 16 pos_from_sun = num; 17 name = new char[strlen(id) + 1]; strcpy(name, id); 18 } 19 ~Planet(void) { delete [] name; } 20 void display(void) { 21 cout << name << " is planet # " << pos_from_sun << ", "; 22 Space_body::display(); 23 } 24 }; 25 main() { 26 Planet earth(3, "Earth", 7926); 27 Space_body comet(34); 28 29 earth.display(); 30 cout << "Earth's diameter is " << 31 earth.get_diameter() << endl; 32 33 cout << "Comet is "; comet.display(); 34 cout << "Comet's diameter is " << 35 comet.get_diameter() << endl; 36 return 0; 37 } Code 6-3 Constructors with inheritance
6-12
6-13
6
Protected Base Class
If the base class is declared protected, the protected and public members of the base class are protected in the derived class. Type of Derivation Access of Base Class Members Public in base Protected in base Private in base
Private inheritance uses the implementation of the base class without allowing users of the derived class access to that implementation.
6-14
6
Private As Compared toPublic Base Classes
class A { int x; protected: int y; public: int z; }; Template for A Class x -- private to A (A::f()) y -- protected (A::f()) z -- public
class B : public A { int a; protected: int b; public: int c; }; Template for B Class x -- no access y -- protected ( B::f()) z -- public a -- private to B (B::f()) b -- protected (B::f()) c -- public class BB : public B { int d; protected: int e; public: int f; }; Template for BB Class x -- no access y -- protected ( BB::f()) z -- public a -- no access b -- protected (BB::f()) c -- public d -- private to BB (BB::f()) e -- protected (BB::f()) f -- public
class C : private A { int m; protected: int n; public: int o; }; Template for C Class x -- no access y -- private to C ( C::f()) z -- private to C (C::f()) m -- private to C (C::f()) n -- protected (C::f()) o -- public class CC : public C { int p; protected: int q; public: int r; }; Template for CC Class x -- no access y -- no access z -- no access m -- no access n -- protected (CC::f()) o -- public p -- private to CC (CC::f()) q -- protected (CC::f()) r -- public
6-15
6
Private Base Classes
The Array class in the following code example provides an integer array. This lets you specify both the upper and lower bounds. The SafeArray class uses the Array class and adds bounds checking. Users of a SafeArray cannot directly use the Array implementation. 1 #include <iostream.h> 2 #include <stdlib.h> 3 class Array { 4 int * data; 5 public: 6 int ubound, lbound; 7 Array(int upper, int lower = 0):ubound(upper),lbound(lower) { 8 data = new int[ubound - lbound + 1]; 9 } 10 ~Array(void) { delete [] data; } 11 int & operator[](int index) { return data[index-lbound]; } 12 }; 13 class SafeArray : private Array { 14 public: 15 SafeArray(int upper, int lower = 0) :Array(upper, lower) {} 16 int & operator[](int index) { 17 if(index < lbound || index > ubound) { 18 cout << "Index " << index << " out of bounds" << endl; 19 exit(1); 20 } 21 return Array::operator[](index); 22 } 23 }; 24 main() { 25 Array a(10); 26 SafeArray s(10); 27 28 if(a.ubound <= 10)// must do own bound checking 29 a[10] = 5; 30 31 s[10] = 5;// cant check if(s.ubound <= 10), why? 32 return 0; 33 } Code 6-4 Private base classes
6-16
6
Composition Instead of Private Inheritance
Inheritance represents the Is-a relationship. However, you can also implement the SafeArray using composition that represents the has-a relationship, as the following code example illustrates. 1 #include <iostream.h> 2 #include <stdlib.h> 3 class Array { 4 int * data; 5 public: 6 int ubound, lbound; 7 Array(int upper, int lower = 0):ubound(upper),lbound(lower) { 8 data = new int[ubound - lbound + 1]; 9 } 10 ~Array(void) { delete [] data; } 11 int & operator[](int index) { return data[index-lbound]; } 12 }; 13 class SafeArray { 14 Array data; 15 public: 16 SafeArray(int upper, int lower = 0) :data(upper, lower) {} 17 int & operator[](int index) { 18 if(index < data.lbound || index > data.ubound) { 19 cout << "Index " << index << " out of bounds" << endl; 20 exit(1); 21 } 22 return data[index]; 23 } 24 }; 25 26 main() { 27 Array a(10); 28 SafeArray s(10); 29 30 if(a.ubound <= 10)// must do own bound checking 31 a[10] = 5; 32 33 s[10] = 5;// still cant access ubound, why? 34 return 0; 35 } Code 6-5 Using composition instead of private inheritance
6-17
6
Conversions Between Derived and Public Base Classes
There are standard conversions dened that are applied between a derived class and its public base class. A derived class object, reference, or pointer is be implicitly converted to a base class object, reference, or pointer. A derived object always contains the base part and can be treated as an object of its base class. A function that is expecting a base object can be given any of its derived objects. The following code example illustrates conversion between derived and public base classes. 1 #include <iostream.h> 2 #include <string.h> 3 4 class Space_body { 5 int diameter; 6 public: 7 Space_body(int size) : diameter(size) {} 8 void display(void) { 9 cout << diameter << " miles in diameter" << endl; 10 } 11 int get_diameter(void) { return diameter; } 12 }; 13 14 class Planet : public Space_body { 15 int pos_from_sun; 16 char *name; 17 public: 18 Planet(int num, const char* id, int size) : Space_body(size) { 19 pos_from_sun = num; 20 name = new char[strlen(id) + 1]; 21 strcpy(name, id); 22 } 23 ~Planet(void) { delete [] name; } 24 void display(void) { 25 cout << name << " is planet # " << pos_from_sun << ", "; 26 Space_body::display(); 27 } 28 }; 29 30 main() { 31 Space_body moon(2160);
6-18
6
32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 } Planet earth(3, "Earth", 7926); cout << "Moon -- "; moon.display(); moon = earth; // earth is converted to a Space_body object // and then assigned to moon using the // default Space_body operator=()
cout << "After moon = earth -- "; moon.display(); // earth = moon; error-no implicit conversion for base // to derived object. Planet *planet_ptr; Space_body *space_ptr; planet_ptr = &earth; cout << "earth thru a planet ptr --\n"; planet_ptr->display();// Planet::display() space_ptr = &earth; // Planet address converts // to Space_body address cout << "earth thru a space_body ptr --\n"; space_ptr->display();// Space_body::display()
Output
Moon -- 2160 miles in diameter After moon = earth -- 7926 miles in diameter earth thru a planet ptr -Earth is planet # 3, 7926 miles in diameter earth thru a space_body ptr -7926 miles in diameter Code 6-6 Conversions between derived and public base classes
6-19
Virtual Functions
C++ implements polymorphism with virtual functions.
Polymorphism
Derived classes are subtypes of the base class. The same function might apply not only to a base class object but to the derived class objects. However, while logically the function performs the same task, the implementation can be different. Polymorphism lets related objects perform common operations in different ways.
Virtual Functions
Virtual functions provide dynamic binding, which defers the decision of which function to execute until runtime. They also dene type- or class-dependent operations within an inheritance hierarchy. This helps eliminate switch statements that can make code difcult to maintain and extend.
6-20
6
Using Virtual Functions
The following guidelines apply to using virtual functions:
G
Base and derived types have a member function with the same prototype. The name of the function, all parameter types and order, and return type must be identical. The function prototype is preceded with the keyword virtual. A base class reference or pointer invokes a virtual function. The decision of which function to invoke is based on the type of the object that is being pointed to or referenced rather than on the type of the reference or pointer. When a base type reference or pointer is used to invoke a function and the base and derived classes have the same member function declared, and virtual functions are not used, only the base classs function is accessible. The decision is made at compile time and is based on the pointer or reference type. Destructors can be virtual functions.
G G
6-21
6
The following code example implements virtual functions. 1 #include <iostream.h> 2 #include <string.h> 3 4 class Shape { 5 public: 6 virtual void draw(void) { cout << "Shape" << endl;} 7 }; 8 9 class Sphere : public Shape { 10 double radius; 11 public: 12 Sphere (double rad) : radius(rad) { } 13 void draw(void) { 14 cout << "Sphere with radius " << radius << endl; 15 } 16 }; 17 18 class Oval : public Shape { 19 double major_radius, minor_radius; 20 public: 21 Oval (double dim1, double dim2): major_radius(dim1), 22 minor_radius(dim2) {} 23 void draw(void) { 24 cout << Oval with major radius " << 25 major_radius << " minor radius " << minor_radius << 26 endl; 27 } 28 }; 29 30 class Square : public Shape { 31 double side; 32 public: 33 Square(double s) : side(s) {} 34 void draw(void) { 35 cout << "Square with side " << side << endl; 36 } 37 }; 38 main() { 39 40 Sphere earth(23.34), 41 moon(12.1), 42 comet(9.48); 43 Oval earth_orbit(12.3, 12.5), 44 moon_orbit(9.3, 9.99);
6-22
6
45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 } Square room(33), den(44);
Shape *array[7]; array[0] array[1] array[2] array[3] array[4] array[5] array[6] = = = = = = = &earth; &earth_orbit; &moon; &moon_orbit; &comet; &room; &den;
Output
Sphere with radius 23.34 Oval with major radius 12.3 minor radius 12.5 Sphere with radius 12.1 Oval with major radius 9.3 minor radius 9.99 Sphere with radius 9.48 Square with side 33 Square with side 44
Code 6-7
Virtual functions
6-23
6
Without Using Virtual Functions
The following code example does not use virtual functions. 1 #include <iostream.h> 2 #include <string.h> 3 4 class Space_body { 5 int diameter; 6 char *type_of_body; 7 public: 8 Space_body(int size, const char* type) { 9 diameter=size; 10 type_of_body = new char[strlen(type) + 1]; 11 strcpy(type_of_body, type); 12 } 13 void display(void) { 14 cout << diameter << " miles in diameter" << endl; 15 } 16 int get_diameter(void) { return diameter; } 17 ~Space_body(void) { 18 delete [] type_of_body; 19 cout << "Space_body destructor" << endl; 20 } 21 }; 22 23 class Planet : public Space_body { 24 int pos_from_sun; 25 char *name; 26 public: 27 Planet(int num, const char* id, int size, const char* type) : 28 Space_body(size,type){ 29 pos_from_sun = num; 30 name = new char[strlen(id) + 1]; 31 strcpy(name, id); 32 } 33 ~Planet(void) { 34 delete [] name; cout << "Planet destructor" << endl; 35 } 36 void display(void) { 37 cout << name << " is planet # " << pos_from_sun << ", "; 38 Space_body::display(); 39 } 40 }; 41 42 main() {
6-24
6
43 44 45 46 47 48 49 50 51 52 53 54 55 56 } Planet earth(3, "Earth", 7926, "planet"); Space_body comet(54, "comet"); Space_body *sp_ptr; Planet *pl_ptr; sp_ptr = new Space_body(89, "meteor"); delete sp_ptr; pl_ptr = new Planet(4, "Mars", 4216, "planet"); delete pl_ptr; sp_ptr = new Planet(2, "Venus", 7521, "planet"); sp_ptr->display(); // calls Space_body::display() only!! delete sp_ptr; cout << "end of main" << endl;
Output
Meteor Mars Venus Comet Earth Space_body destructor Planet destructor Space_body destructor 7521 miles in diameter Space_body destructor end of main Space_body destructor Planet destructor Space_body destructor Should have called the Planet::display function
Code 6-8
6-25
6
Using Virtual Functions
The following code example uses the same programming scenario as Code 6-8 but with virtual functions. 1 #include <iostream.h> 2 #include <string.h> 3 4 class Space_body { 5 int diameter; 6 char *type_of_body; 7 public: 8 Space_body(int size, const char* type) { 9 diameter=size; 10 type_of_body = new char[strlen(type) + 1]; 11 strcpy(type_of_body, type); 12 } 13 virtual void display(void) { 14 cout << diameter << " miles in diameter" << endl; 15 } 16 int get_diameter(void) { return diameter; } 17 virtual ~Space_body(void) { 18 delete [] type_of_body; 19 cout << "Space_body destructor" << endl; 20 } 21 }; 22 23 class Planet : public Space_body { 24 int pos_from_sun; 25 char *name; 26 public: 27 Planet(int num, const char* id, int size, const char* type) :Space_body(size,type){ 28 pos_from_sun = num; 29 name = new char[strlen(id) + 1]; 30 strcpy(name, id); 31 } 32 ~Planet(void) { 33 delete [] name; cout << "Planet destructor" << endl; 34 } 35 void display(void) { 36 cout << name << " is planet # " << pos_from_sun << ", "; 37 Space_body::display(); 38 } 39 }; 40
6-26
6
41 main() { 42 Planet earth(3, "Earth", 7926, "planet"); 43 Space_body comet(54, "comet"); 44 Space_body *sp_ptr; 45 Planet *pl_ptr; 46 47 sp_ptr = new Space_body(89, "meteor"); 48 delete sp_ptr; 49 pl_ptr = new Planet(4, "Mars", 4216, "planet"); 50 delete pl_ptr; 51 sp_ptr = new Planet(2, "Venus", 7521, "planet"); 52 sp_ptr->display(); // calls Planet::display() now!! 53 delete sp_ptr; 54 cout << "end of main" << endl; 55 }
Output
Meteor Mars Space_body destructor Planet destructor Space_body destructor Venus is planet # 2, 7521 miles in diameter Planet destructor Space_body destructor end of main Space_body destructor Planet destructor Space_body destructor
Code 6-9
6-27
6-28
6
You could use a scope modier to reference the base-class version: b.A::set(5) This is not safe from a maintenance viewpoint, since if you later add a B::set(int)it will not be called by this code. You could instead cast the B object to an A reference or pointer: ((A&)b).set(5) ((A*)&b)->set(5) This puts the call into an A context. The latter solution ensures the appropriate virtual version is always called, no matter how the class denitions are changed. The best solution is usually to provide a derived class version of all the overloaded base class virtual functions, or to provide none of them. A derived-class version can just call the base class version if appropriate.
6-29
6
The following code example illustrates overloading and virtual functions. 1 #include <iostream.h> 2 3 class A { 4 public: 5 virtual void set() { cout << "set no args" << endl; } 6 virtual void set(const char *) { cout << "set char * arg" << endl; } 7 virtual void set(int) { cout << "set int arg" << endl; } 8 }; 9 10 class B: public A { 11 public: 12 void set() { cout << "B: set no args" << endl; } 13 }; 14 15 main() { 16 B *bp = new B; 17 bp->set("Hello"); 18 19 B b; 20 b.set(10); 21 22 b.A::set("World"); 23 24 ((A*)bp)->set(20); 25 }
Compiler Result
"code6-10.cc", "code6-10.cc", "code6-10.cc", "code6-10.cc", line line line line 13: 13: 17: 20: Warning: B::set Warning: B::set Error: Too many Error: Too many hides the hides the arguments arguments virtual virtual in call in call function A::set(int). function A::set(const char*) to void(*)(). to B::set().
Code 6-10
6-30
6-31
6
The following code example illustrates pure virtual functions. 1 #include <iostream.h> 2 #include <string.h> 3 class Space_body { 4 int diameter; 5 public: 6 Space_body(int size) { diameter=size; } 7 int get_diameter(void) { return diameter; } 8 virtual void display(void) = 0; 9 }; 10 class Planet : public Space_body { 11 int pos_from_sun; 12 char *name; 13 public: 14 Planet(int num, const char* id, int size) : Space_body(size) { 15 pos_from_sun = num; 16 name = new char[strlen(id) + 1]; 17 strcpy(name, id); 18 } 19 void display(void) { 20 cout << name << " is planet number " << 21 pos_from_sun << endl << "and is " << 22 get_diameter() << " miles in diameter." << endl; 23 } 24 }; 25 26 main() { 27 // Space_body comet(65); error -- abstract class 28 29 Planet earth(3, "Earth", 7926); 30 earth.display(); 31 32 Space_body *base_ptr = &earth; 33 base_ptr->display(); 34 35 }
6-32
6
Output
Earth is planet number 3 and is 7926 miles in diameter. Earth is planet number 3 and is 7926 miles in diameter.
Code 6-11
6-33
6
Exercises
Exercise objectives In the exercises for this module, which are located in the Module6 folder online, you will:
G
Write a class that inherits from another class. Create an application that tests your implementation. Write a virtual function and implement it correctly. Write and implement constructors, overloaded operators, and virtual functions for a derived class.
G G
6-34
6
Exercises Summary
Discussion Take a few minutes to discuss what experiences, issues, or discoveries you had during the lab exercises.
Manage the discussion here based on the time allowed for this module, which was given in the About This Course module. If you find you do not have time to spend on discussion, then just highlight the key concepts students should have learned from the lab exercise.
G
Experiences
Ask students what their overall experiences with this exercise have been. You may want to go over any trouble spots or especially confusing areas at this time.
G
Interpretations
Ask students to interpret what they observed during any aspects of this exercise.
G
Conclusions
Have students articulate any conclusions they reached as a result of this exercise experience.
G
Applications
Explore with students how they might apply what they learned in this exercise to situations at their workplace.
6-35
6
Check Your Progress
Before continuing on to the next module, check that you are able to accomplish or answer the following: K K K K K K K K Dene a class derived from another class Create an object of the derived type Use the protected access region Discuss the relationship between base and derived class constructors and how to pass values to base constructors Explain the differences between public base classes and private base classes Illustrate conversions between base and derived classes Explain the purpose of virtual functions and how to create them Identify what makes a pure virtual function and an abstract class and explain when they might be useful
6-36
6
Think Beyond
How do you inherit the characteristics of more than one class?
6-37
Write derived classes that have multiple base classes Use the scope operator (::), functions, and namespace to resolve member identier conicts that can arise in multiple inheritance Use virtual base classes to avoid duplication of data members Resolve the conict of multiple constructors trying to initialize a single virtual base class
G G
7-1
Copyright 1999 Sun Microsystems, Inc. All Rights Reserved. Enterprise Services Nov. 1999, Revision H
7
Relevance
Present the following questions to stimulate the students and get them thinking about the issues and topics presented in this module. While they are not expected to know the answers to these questions, the answers should be of interest to them and inspire them to learn the material presented in this module.
Discussion How can you create a class from many base classes? How do you resolve potential conicts arising from inheriting multiple classes?
7-2
Multiple Inheritance
Multiple inheritance, which is used to derive a class from more than one base class, handles complicated relationships between classes. The derived class can be thought of as being a subtype of each of its base classes. Multiple inheritance denes a relationship between independent class types. It also introduces the possibility of conict among data and member function names.
7-3
7
Syntax
Following is the syntax for implementing multiple inheritance: class base1 { class members }; class base2 { class members }; class derived : public base1, public base2 { additional class members }; Following are rules for implementing multiple inheritance:
G
To derive from more than one base class, list the base classes (after the colon) separated by commas. Each base class needs its own access specication: public, protected or private, as in single inheritance. The derived class may add as many new data members and member functions (or friend function specications) as necessary. It may also replace (mask) as many of the inherited members as desired.
Note Before the derived class constructor is executed, each base class constructor is invoked in the order that the base classes are declared in the derivation list. The destructors are invoked in the reverse order of the constructors.
7-4
7-5
7
1 #include <string.h> 2 #include <iostream.h> 3 4 class A { 5 protected: 6 int x; 7 public: 8 A(void) { x = 0; } 9 }; 10 11 class B { 12 protected: 13 char c; 14 public: 15 B(char a = ?) { c = a; } 16 }; 17 18 class C { 19 protected: 20 float f; 21 public: 22 C(float num = 7.06) { f = num; } 23 }; 24 25 class Derived : public A, public B, public C { 26 protected: 27 char name[40]; 28 public: 29 Derived(const char *string = "hello") { strcpy(name, string); } 30 void display(void) { 31 cout << x << endl << c << endl; 32 cout << f << endl << name << endl; 33 } 34 }; 35 36 main() { 37 Derivedd; 38 39 d.display(); 40 }
7-6
7
Output
0 ? 7.06 hello
Code 7-1
7-7
7
The following diagram shows the stack segment and text segment as a result of the code in Code 7-1.
A::x
B::c
d
C::f
name
Stack segment Text segment The text segment contains code for all functions, including: A::A(void) B::B(char) C::C(float) Derived::Derived(char*) Derived::display(void)
7-8
7-9
7
1 #include <string.h> 2 #include <iostream.h> 3 4 class A { 5 protected: 6 int x; 7 public: 8 A(int a) { x=a; } 9 }; 10 11 class B { 12 protected: 13 char c; 14 public: 15 B(char a) { c=a; } 16 }; 17 18 class Derived : public A, public B { 19 protected: 20 char name[40]; 21 public: 22 Derived(int, char, const char *); 23 void display(void) { 24 cout << x << endl << c << endl; 25 cout << name << endl; 26 } 27 }; 28 29 Derived::Derived(int a, char b, const char *string) : A(a), B(b) { 30 strcpy(name, string); 31 } 32 33 main() { 34 Derived d(3, c, "Sun"); 35 36 d.display(); 37 }
7-10
7
Output
3 c Sun
Code 7-2
7-11
Using the scope operator (::) Using functions to invoke specic classes Using namespace
7-12
7
Identier Scope
The following code example illustrates the issues associated with identical identiers in multiple base classes. This program compiles and runs, but it produces a compiler warning. 1 #include <string.h> 2 #include <iostream.h> 3 class A { 4 protected: 5 int x; 6 public: 7 A(int x) { x=0; } 8 }; 9 10 class B { 11 protected: 12 char c; 13 public: 14 B(char a) { c=a; } 15 }; 16 17 class C { 18 protected: 19 float f; 20 public: 21 C(float num) { f=num; } 22 }; 23 24 class Derived : public A, public B, public C { 25 protected: 26 int x; // conflicts with A::x 27 float f;// conflicts with C::f 28 char name[40];
7-13
7
29 public: 30 Derived(int, char, float, const char *); 31 void display(void) { 32 cout << x << \n << c << \n << f << \n << name << endl; 33 } 34 }; 35 36 Derived::Derived(int a, char b, float c, const char *string) 37 : A(a), B(b), C(c) { 38 strcpy(name, string); 39 x=4; Which x and f ? 40 f=2.1; 41 } 42 43 main() { 44 Derived d(3, c, 4.2, "Sun"); 45 d.display(); 46 } 47
Compiler Result
code7-3.cc, line 8: Warning: x hides A::x.
Output
4 c 2.1 Sun
Code 7-3
Identier scope
7-14
7
Using the Scope Operator
The following code example illustrates the proper use of the scope operator to explicitly identify variable identiers in multiple inheritance situations. 1 #include <string.h> 2 #include <iostream.h 3 class A { 4 protected: 5 int x; 6 public: 7 A(int a) { x=a; } 8 }; 9 10 class B { 11 protected: 12 char c; 13 public: 14 B(char a) { c=a; } 15 }; 16 17 class C { 18 protected: 19 float f; 20 public: 21 C(float num) { f=num; } 22 }; 23 24 class Derived : public A, public B, public C { 25 protected: 26 int x; 27 float f; Use the scope operator 28 char name[40]; 29 public: 30 Derived(int, char, float, const char *); 31 void display(void) { 32 cout << A::x << \n << c << \n << C::f; 33 cout << \n << name << \n << x << \n << f << endl; 34 } 35 }; 36 37 Derived::Derived(int a, char b, float c, const char *string) 38 : A(a), B(b), C(c) { 39 strcpy(name, string);
7-15
7
40 x=4; 41 f=2.1; 42 } 43 44 main() { 45 Derived d(3, c, 4.2, "Sun"); 46 d.display(); 47 }
Output
3 c 4.2 Sun 4 2.1
Code 7-4
7-16
7
Identier Ambiguity Error
The following program does not compile. There is an error in the Derived::display()function. The member x is ambiguous. Because both class B and class C inherit from class A (and received an x at equal levels), the compiler does not know which of the inherited xs is to be printed. 1 #include <string.h> 2 #include <iostream.h> 3 4 class A { 5 protected: 6 int x; 7 public: 8 A(int a = 0) { x = a; } 9 }; 10 11 class B : public A { 12 protected: 13 char c; 14 public: 15 16 B(char a = ?) { c = a; } 17 }; 18 19 class C : public A { 20 protected: 21 float f; 22 public: 23 C(float num = 3.6) { f = num; } 24 }; 25 26 class Derived : public B, public C { 27 protected: 28 char name[40]; 29 public: 30 Derived(const char *string = "hello") { strcpy(name, string); } 31 void display(void) { 32 cout << x << c << \n << f << \n << name << endl; 33 } 34 }; 35
7-17
7
36 main() { 37 Derived d; 38 d.display(); 39 } 40
Compiler Result
code7-5.cc, line 32: Error: For A::x, the base class A is ambiguous in Derive d.
Code 7-5
7-18
7
Resolving the Ambiguity Error With the Scope Operator
You can x the compiler error in Code 7-5 by using the class name and scope operator (class::) to identify explicitly which variable x to use, as shown in the following code example. 1 #include <string.h> 2 #include <iostream.h> 3 class A { 4 protected: 5 int x; 6 public: 7 A(int a=0) { x = a; } 8 }; 9 10 class B : public A { 11 protected: 12 char c; 13 public: 14 B(char a = ?) { c = a; } 15 }; 16 17 class C : public A { 18 protected: 19 float f; 20 public: 21 C(float num = 3.6) { f = num; } 22 }; 23 24 class Derived : public B, public C { 25 protected: 26 char name[40]; 27 public: 28 Derived(const char *string = "hello") { strcpy(name, string); } 29 void display(void) { 30 cout << B::x << \n << C::x << \n; 31 cout << c << \n; 32 cout << f << \n << name << endl; 33 } 34 }; Precede the variable with 35 the class name and scope 36 main() { operator. 37 Derived d; 38 d.display(); 39 }
7-19
7
Output
0 0 ? 3.6 hello
Code 7-6
7-20
7
1 #include <string.h> 2 #include <iostream.h> 3 class A { 4 protected: 5 int x; 6 public: 7 A(int a=0) { x = a; } 8 virtual void func(void) { cout << "func in A" << endl; } 9 }; 10 11 class B : public A { 12 protected: 13 char c; 14 public: 15 B(char a = ?) { c = a; } 16 virtual void func(void) { cout << "func in B" << endl; } 17 }; 18 19 class C : public A { 20 protected: 21 float f; 22 public: 23 C(float num = 3.6) { f = num; } 24 }; 25 26 class Derived : public B, public C { 27 protected: 28 char name[40]; 29 public: 30 Derived(const char *string = "hello") { strcpy(name, string); } 31 }; 32 33 main() { 34 Derived *dp = new Derived; 35 36 dp->func(); 37 }
7-21
7
Compiler Result
code7-7.cc, line 36: Error: The name func is ambiguous in Derived: B::func() and A::func().
Code 7-7
7-22
7
Using namespace to Resolve Duplicate Identiers
Namespace lets you avoid identier collisions that result from multiple inheritance. If you are creating a library, you can designate a wrapper (namespace) around identiers to make them unique compared to identiers in other libraries. For example, if you develop your own array class, you could use the name of your software company as a namespace: namespace YourSoftwareCompany_Array Programmers could then access your array class specically in their programs in a couple of ways: On a Class-by-Class Basis YourSoftwareCompany::Array a; This declaration syntax means the program uses the YourSoftwareCompany array class for only Array a. At a Global Level using namespace YourSoftwareCompany; Array a; This declaration syntax means that you want to use all classes that are tagged with the namespace YourSoftwareCompany. Whenever the user references a YourSoftwareCompany class, the program uses it (along with all the functions in the class). In this example (Array a;), because you used the namespace to identify your own array class (YourSoftwareCompany_Array), any array the user declares uses the YourSoftwareCompany_Array class and not collide with the array class in the C++ library. The rst statement tells the program to look for any references to the namespace YourSoftwareCompany. The program checks any statements against your library rst to see if the statement has the namespace. If the program nds a namespace match, it uses the namespace class.
7-23
7
You can dene a new namespace for each class or set of functions. The following code example illustrates this. 1 #include <iostream.h> 2 3 namespace Window { 4 void move(int x, int y); 5 void resize(int x, int y); 6 7 void move(int x,int y) { 8 if (x < 0 || x > 40) 9 return; 10 if (y < 0 || y > 40) 11 return; 12 cout << "X is moved to " << x << endl; 13 cout << "Y is moved to " << y << endl; 14 } 15 } 16 17 void Window::resize(int x, int y) { 18 if (x < 0 || x > 40) 19 return; 20 if (y < 0 || y > 40) 21 return; 22 cout << "X is resized to " << x << endl; 23 cout << "Y is resized to " << y << endl; 24 } 25 26 main () { 27 Window::move(5,6); 28 29 Window::resize(50,20); 30 Window::resize(10,20); 31 }
Output
X Y X Y is is is is moved to 5 moved to 6 resized to 10 resized to 20
Code 7-8
7-24
7
Another option is to delcare what namespace you are using, then you can simplify your code. 1 #include <iostream.h> 2 3 namespace Window { 4 void move(int x, int y); 5 void resize(int x, int y); 6 7 void move(int x,int y) { 8 if (x < 0 || x > 40) 9 return; 10 if (y < 0 || y > 40) 11 return; 12 cout << "X is moved to " << x << endl; 13 cout << "Y is moved to " << y << endl; 14 } 15 } 16 17 void Window::resize(int x, int y) { 18 if (x < 0 || x > 40) 19 return; 20 if (y < 0 || y > 40) 21 return; 22 cout << "X is resized to " << x << endl; 23 cout << "Y is resized to " << y << endl; 24 } 25 26 using namespace Window; 27 28 main () { 29 move(5,6); 30 31 resize(50,20); 32 Window::resize(10,20); 33 }
Output
X Y X Y Code 7-9 is is is is moved to 5 moved to 6 resized to 10 resized to 20
7-25
7
Sometimes, using namespace, the code can look like a class nested within another class. For example: 1 #include <iostream.h> 2 3 namespace Window { 4 class Pane{ 5 int xvalue,yvalue; 6 public: 7 void resize(int x, int y); 8 9 void move(int x,int y) { 10 if (x < 0 || x > 40) 11 return; 12 if (y < 0 || y > 40) 13 return; 14 cout << "X is moved to " << x << endl; 15 cout << "Y is moved to " << y << endl; 16 xvalue = x; 17 yvalue = y; 18 } 19 20 void show() { 21 cout << "X value is " << xvalue << endl; 22 cout << "Y value is " << yvalue << endl << endl; 23 } 24 }; 25 } 26 27 void Window::Pane::resize(int x, int y) { 28 if (x < 0 || x > 40) 29 return; 30 if (y < 0 || y > 40) 31 return; 32 cout << "X is resized to " << x << endl; 33 cout << "Y is resized to " << y << endl; 34 xvalue = x; 35 yvalue = y; 36 } 37 38 using namespace Window; 39 40 main () { 41 Pane p; 42 43 p.move(5,6);
7-26
7
44 45 46 47 48 49 } p.show(); p.resize(50,20); p.resize(10,20); p.show();
Output
X Y X Y X Y X Y Code 7-10 is moved to 5 is moved to 6 value is 5 value is 6 is resized to 10 is resized to 20 value is 10 value is 20 Using namespace with a nested class
You can also use "unnamed" namespaces, but the namespace is only valid for the le containing the "unnamed" namespace. For example: //file: one.cc namespace { int value; char p(char *c); // ... } //file: two.cc namespace { int value; char p(char *c); // ... } int main() { char c = p(ptr); } In this example, the main()program in le two.cc does not see the p()in le one.cc. It sees only the p()in its own le.
7-27
7
Using Virtual Base Classes
Base classes can appear multiple times in a derivation hierarchy. Virtual base classes allow for the specication of shared base classes, as shown in Code 7-11 and illustrated by the following gure.
A part
A part
A part
int x
char name[40] Figure 7-1 Classes derived with and without a virtual base
7-28
7
The following code example implements virtual base classes. 1 #include <string.h> 2 #include <iostream.h> 3 class A { 4 protected: 5 int x; 6 public: 7 A(int a=0) { x = a; } 8 }; 9 10 class B : virtual public A { 11 protected: 12 char c; 13 public: 14 B(char a = ?) { c = a; } 15 void display(void) { cout << x << " " << c << endl; } 16 }; 17 18 class C : virtual public A { 19 protected: 20 float f; 21 public: 22 C(float num = 3.6) { f = num; } 23 void display(void) { cout << x << " " << f << endl; } 24 }; 25 26 class Derived : public B, public C { 27 protected: 28 char name[40]; 29 public: 30 Derived(const char *string = "hello") { strcpy(name, string); } 31 void display(void) { 32 cout << x << " " << c << " "<< f << " " << name << endl; 33 } 34 }; 35 36 main() { 37 B b; 38 C c; 39 Derivedd; 40
7-29
7
41 cout << "b: 42 cout << "c: 43 cout << "d: 44 45 } "; b.display(); "; c.display(); "; d.display();
Output
b: c: d: 0 0 0 ? 3.6 ? 3.6
hello
Code 7-11
7-30
Constructor Conicts
Usually a derived class can explicitly initialize its immediate base class. With the virtual base class in Code 7-12, there are two paths back to the base constructor. Which one is used? Is the base part initialized twice? With virtual base classes, it is the responsibility of the most derived class to provide values for the shared base class. Virtual base classes are constructed before non-virtual base classes.
7-31
7
The following code example does not compile because of constructor conicts. 1 #include <string.h> 2 #include <iostream.h> 3 class A { 4 protected: 5 int x; 6 public: 7 A(int a) { x = a; } 8 }; 9 10 class B : virtual public A { 11 protected: 12 char c; 13 public: 14 B(int a, char b) : A(a) { c = b; } 15 }; 16 17 class C : virtual public A { 18 protected: 19 float f; 20 public: 21 C(int a, float num ) : A(a) { f = num; } 22 }; 23 24 class Derived : public B, public C { 25 protected: 26 char name[40]; 27 public: 28 Derived(int, char, float, const char *); 29 Derived(char, float, const char *); 30 void display(void) { 31 cout << x << " " << c << " "; 32 cout << f << " " << name << endl; 33 } 34 }; 35 36 Derived::Derived(int a, char b, float c, const char *string) 37 : B(a, b), C(a,c) { strcpy(name, string); } 38 39 Derived::Derived(char b, float c, const char *string) 40 : B(42, b), C(16, c) { strcpy(name, string); } 41
7-32
7
42 main() { 43 Derived d(4, z, 23.4, "Sun"); 44 } 45
Compiler Result
code7-12.cc, line 37: Error: Could not find A::A() to initialize base class. code7-12.cc, line 40: Error: Could not find A::A() to initialize base class.
Code 7-12
Constructor conicts
7-33
7
Resolving Constructor Conicts Two Options
The following code example provides two options for resolving constructor conicts. 1 #include <string.h> 2 #include <iostream.h> 3 4 class A { 5 protected: 6 int x; 7 public: 2 8 A(int a) { x = a; } 9 A(void) { x = 0; }// takes no parameters 10 }; 11 12 class B : virtual public A { 13 protected: 14 char c; 15 public: 16 B(int a, char b) : A(a) { c = b; } 17 }; 18 19 class C : virtual public A { 20 protected: 21 float f; 22 public: 23 C(int a, float num ) : A(a) { f = num; } 24 }; 25 26 class Derived : public B, public C { 27 protected: 28 char name[40]; 29 public: 30 Derived(int, char, float, const char *); 31 Derived(char, float, const char *); 32 void display(void) { 33 cout << x << " " << c << " "; 34 cout << f << " " << name << endl; 35 } 36 };
7-34
7
2 37 Derived::Derived(int a, char b, float c, const char *string) 38 : A(a), B(a, b), C(a,c)// uses A::A(int) constructor 39 { strcpy(name, string); } 40 41 Derived::Derived(char b, float c, const char *string) 42 : B(10, b), C(20, c)// uses A::A(void) constructor 43 { strcpy(name, string); } 44 45 main() { 46 Derived d1(4, z, 23.4, "Sun"); 47 Derived d2(z, 23.4, "Sun"); 48 49 d1.display(); 50 d2.display(); 51 } 52
Output
4 z 23.4 Sun 0 z 23.4 Sun
Code 7-13
7-35
7-36
7
The following code example implements virtual base classes and overloaded functions. 1 #include <string.h> 2 #include <iostream.h> 3 class A { 4 protected: 5 int x; 6 public: 7 A(int a=0) { x = a; } 8 virtual void func(void) { cout << "func in A" << endl; } 9 }; 10 11 class B : virtual public A { 12 protected: 13 char c; 14 public: 15 B(char b=?) { c = b; } 16 virtual void func(void) { cout << "func in B" << endl; } 17 }; 18 19 class C : virtual public A { 20 protected: 21 float f; 22 public: 23 C(float num=3.6) { f = num; } 24 }; 25 26 class Derived : public B, public C { 27 protected: 28 char name[40]; 29 public: 30 Derived(const char *string="Hello") { strcpy(name,string); } 31 }; 32 33 main() { 34 Derived *dp = new Derived; 35 36 dp->func(); 37 }
7-37
7
Output
func in B
Code 7-14
7-38
7
Exercises
Exercise objectives In the exercises for this module, which are located in the Module7 folder online, you will:
G
Create a base class, and create a derived class that inherits from the base class and a class in a previous exercise. Derive a class from two classes previously implemented and use existing base class functionality.
7-39
7
Exercises Summary
Discussion Take a few minutes to discuss what experiences, issues, or discoveries you had during the lab exercises.
Manage the discussion here based on the time allowed for this module, which was given in the About This Course module. If you find you do not have time to spend on discussion, then just highlight the key concepts students should have learned from the lab exercise.
G
Experiences
Ask students what their overall experiences with this exercise have been. You may want to go over any trouble spots or especially confusing areas at this time.
G
Interpretations
Ask students to interpret what they observed during any aspects of this exercise.
G
Conclusions
Have students articulate any conclusions they reached as a result of this exercise experience.
G
Applications
Explore with students how they might apply what they learned in this exercise to situations at their workplace.
7-40
7
Check Your Progress
Before continuing on to the next module, check that you are able to accomplish or answer the following: K K K K Write derived classes that have multiple base classes Use the scope operator (::), functions, and namespace to resolve member identier conicts that can arise in multiple inheritance Use virtual base classes to avoid duplication of data members Resolve the conict of multiple constructors trying to initialize a single virtual base class
7-41
7
Think Beyond
Are there other techniques you can use, in addition to inheritance, to maximize software reuse and increase development speed and efciency? Does C++ let you create functions and classes that serve as a basis for easily creating new functions and classes?
7-42
Write template functions Write template classes Handle exceptions Throw exceptions Write applications using the Tools.h++ class library
8-1
Copyright 1999 Sun Microsystems, Inc. All Rights Reserved. Enterprise Services Nov. 1999, Revision H
8
Relevance
Present the following questions to stimulate the students and get them thinking about the issues and topics presented in this module. While they are not expected to know the answers to these questions, the answers should be of interest to them and inspire them to learn the material presented in this module.
Discussion How can using templates in C++ simultaneously speed up the development process and let you create more stable software? How do you perform tasks such as string manipulation and date handling in C++? How do you support internationalization?
8-2
Templates
A template class or function is the specication for an innite set of classes or functions. Templates do the following:
G G
Provide parameterized types and functions. Implement functions and classes that are independent of the types of objects that they operate on. Provide code automatically generated by the compiler by substituting the actual types used for the template argument types (instantiating). Offer the convenience of macros in C with the added benet of type checking. Templates also provide better diagnostics for errors. Provide functionality to build a templates database (Templates.DB) at compile time when a template needs to be instantiated. This directory contains all conguration les needed to handle and instantiate templates required.
8-3
Template Functions
The following syntax and rules apply to using template functions.
Syntax
Following is the syntax for implementing template functions. template <class type> return-value function-name(function parameters)
8-4
8
Rules
The following rules apply to implementing template functions.
G
The template keyword must be used in both the denition and declaration of the function. The angle brackets enclose a comma-separated list of formal parameters. Each parameter consists of the keyword class followed by an identier name. The keyword class species that the data type of the identier can be either a built-in data type or a user-dened data type. The template parameters are placeholders for data types. The function denition or declaration follows the parameter list. The formal template parameters can be used as a data type specier in the body of the function. If the function uses operators on the data parameters and objects are passed as parameters, the operators must be dened for those objects.
The following code example shows template function max. template <class type> type max(type a, type b) { return a > b ? a : b; } The following code example shows template function foo. template <class type1, class type2> int foo(type1 a, int b, type2 c); For template function foo, the actual arguments to foo could be:
M M M
Any data type An integer Any data type, possibly different other data type(s) used
8-5
8
The following code example implements a template function. 1 #include <iostream.h> 2 3 template <class type> 4 type min(type a, type b) { return a < b ? a : b; } 5 6 7 main() { 8 int a = 10, b = 20; 9 char d = A, e = Z; 10 11 cout << min(a, b) << endl;// Okay - both ints 12 13 //cout << min(a, e) << endl;// Error - no implicit 14 // conversion. 15 cout << min(d, e) << endl;// Okay - both chars 16 } Code 8-1 Template function
8-6
Template Classes
Template classes are useful for container classes. Container classes are classes that hold an object of some type. A list class is an example of a container class. The list class manages the objects on the list without concern for the type of objects on the list. A user of the list class would like to be able to create a list that holds some specic data type without modifying the list class. Template classes provide that functionality. When a template class is used as a template argument, you must use a space to separate the closing angle brackets. List< Set<char> > not List< Set<char>> A template class can be used for derivation.
8-7
8
Using a Template for a Stack Class
The following code example uses a template for a stack container class. 1 #include <iostream.h> 2 template <class type> 3 class Stack { 4 public: 5 Stack(int); 6 ~Stack(void) { delete [] items; } 7 void push(type); 8 type pop(void); 9 int is_empty(void); 10 int is_full(void); 11 private: 12 type *items; 13 int top_item; 14 int size; 15 }; 16 17 template <class type> 18 Stack<type>::Stack(int stack_size) : top_item(0), 19 size(stack_size),items(new type[stack_size]) {} 20 21 template <class type> 22 void Stack<type>::push(type val) { 23 items[top_item++] = val; 24 } 25 26 template <class type> 27 type Stack<type>::pop(void) { 28 return items[--top_item]; 29 } 30 31 template <class type> 32 int Stack<type>::is_empty(void) { 33 return top_item == 0 ? 1 : 0; 34 } 35 36 template <class type> 37 int Stack<type>::is_full(void) { 38 return top_item >= size ? 1 : 0; 39 } 40 main() { 41 Stack<int> s(5); 42
8-8
8
43 cout << "Stack is " << (s.is_empty()? "empty" : "not empty") << endl; 44 45 int i = 0; 46 cout << "Fill up integer stack" << endl; 47 while(!(s.is_full())) s.push(i++); 48 49 cout << "Stack is " << (s.is_full()? "full" : "not full") << endl; 50 51 cout << "Pop stack until empty" << endl; 52 while(!(s.is_empty())) 53 cout <<"Popped item is " << s.pop() << endl; 54 55 Stack<const char *> c(3); 56 c.push("world!"); 57 c.push("Hello"); 58 while(!(c.is_empty())) 59 cout << "Popped item is " << c.pop() << endl; 60 }
Output
Stack is empty Fill up integer stack Stack is full Pop stack until empty Popped item is 4 Popped item is 3 Popped item is 2 Popped item is 1 Popped item is 0 Popped item is Hello Popped item is world!
Code 8-2
8-9
Exception Handling
The exception handling facility provides a consistent method of handling runtime errors.
Traditional Methods
Following are some traditional ways to handle run-time errors:
G G G G G G
Ignore them Abort Call an error handling function Set an error state ag Return an error code Use setjmp and longjmp
8-10
8
Exception Handling Mechanism
The exception handling mechanism provides an alternative to the traditional methods. The traditional methods do not always provide an adequate solution because:
G G
Constructors cannot return values. setjmp and longjmp are C library functions and destructors are not called for objects on the stack between the longjmp and the setjmp.
8-11
8
The following code example illustrates exception handling in C++. 1 #include <iostream.h> 2 class ExceptExample { 3 public: 4 ExceptExample(const char *s) : errorString(s) { } 5 const char *reason(void) { return errorString; } 6 private: 7 const char *errorString; 8 }; 9 10 int main() { 11 void f1(void); 12 13 try { // setup a try block 14 f1(); 15 } 16 // if f1() throws an ExceptExample exception, the following 17 // catch clause is executed 18 catch (ExceptExample &e) { 19 cout << "In mains catch clause\n"; 20 cout << "" << e.reason() << endl; 21 } 22 23 cout << "End of main" << endl; 24 } 25 26 void f1(void) { 27 cout << "Entering function f1" << endl; 28 throw ExceptExample("Throwing an exception example"); 29 cout << "Leaving function f1" << endl; 30 }
Output
Entering function f1 In main's catch clause throwing an exception example End of main
Code 8-3
Exception handling
8-12
8
The throw keyword is used to raise an exception. It takes a single argument of any type. The try block (try keyword followed by a sequence of program statements enclosed in braces) groups together statements that can throw an exception that must be handled. The catch clause identies the exception handlers. When a throw is executed, control is passed up to the nearest enclosing exception handler that can "catch" the exception. The throw argument is passed to the exception handler. If an exception is not thrown when control reaches the end of the try block, the exception handler(s) are skipped and the program ow continues at the rst statement after the exception handler(s). If an exception is thrown, the stack is unwound and destructors are called as appropriate until a try block is found. The exception handlers are examined in order of appearance, trying to match the throw argument to the exception handler type.
G
If a match is found, control is transferred to the matching exception handler and the exception is no longer considered raised. After the execution of the exception handler, control is transferred to the rst statement after the handlers. If no matching exception handler can be found, the predened terminate()function is called.
Use catch(...)to catch any exception. A throw without an operand rethrows the current exception. This can only be done from within an exception handler.
8-13
Tools.h++
The Tools.h++ class library is included with the compiler. It provides classes for the following:
G G G G G
String and character manipulation Time and date handling Internationalization support Persistent store Lists, stacks, queues, sets, etc.
The command to compile and link using the Tools.h++ class library is: CC -o example6 -compat=4 example6.cc -Bstatic -lrwtool Note The -compat=4 option is required because Tools.h++ version 7 and CC version 5.0 are not compatible.
8-14
8
Tools.h++ String and Date Example
The following code example implements string manipulation and date handling using the Tools.h++ library. 1 #include <rw/rwdate.h> 2 #include <rw/rwtime.h> 3 #include <rw/cstring.h> 4 #include <iostream.h> 5 6 class Employee { 7 RWCString name; 8 int id; 9 RWDate start; 10 public: 11 Employee(const char *n, int no, RWDate &hire) : name(n), id(no), start(hire) { } 12 friend ostream& operator<<(ostream &out, const Employee &e); 13 }; 14 15 ostream& operator<<(ostream &out, const Employee &e) { 16 out << "EmployeeIDStart DateDays Employed" << endl; 17 RWDate today; 18 out << e.name << "" << e.id << "" << e.start << "" << (today e.start) << endl; 19 return out; 20 } 21 22 main() { 23 RWDate hiredate(1,"Nov",95); 24 25 Employee emp("Barry Evans", 8991, hiredate); 26 27 cout << emp << endl; 28 }
Output
Employee Barry Evans ID 8991 Start Date 11/01/90 Days Employed 1274
Code 8-4
8-15
8-16
8
Template-Based Classes
Template-based classes are a set of collection classes based on C++ templates. They include singly and doubly linked lists, stacks, queues, ordered collections, hash tables, sets, dictionaries, and iterators.
Generic-Based Classes
Generic-based classes are a set of collection classes based on the macros dened in <generic.h>. They include singly and doubly linked lists, stacks, queues, ordered collections, and iterators. These classes are useful for compilers that do not have templates implemented.
Smalltalk-Like Classes
Smalltalk-like classes are a set of collection classes modeled after the Smalltalk-80 programming environment. These include Bag, Set, OrderedCollection, SortedCollection, Dictionary, Stack, Queue, LinkedList, and iterators. When an object is inserted into a value-based collection, a copy is made. When an object is inserted into a reference-based collection, a pointer to the object is stored. An iterator allows sequential access to the elements of a collection.
8-17
8
The following code example implements template-based collection classes. 1 #include <rw/tpslist.h> 2 #include <rw/cstring.h> 3 #include <iostream.h> 4 5 main () { 6 7 RWTPtrSlist<RWCString> words; 8 9 words.append(new RWCString("List")); 10 words.append(new RWCString("Set")); 11 words.append(new RWCString("Dictionary")); 12 13 RWCString item("Set"), *match; 14 15 if (match = words.find(&item)) { 16 cout << "Match for " << item << " found at index " 17 << words.index(match) << endl; 18 } else { 19 cout << "No match found for " << item << endl; 20 } 21 }
Code 8-5
8-18
8
The following code example implements generic-based collection classes. 1 #include <rw/gdlist.h> 2 #include <rw/cstring.h> 3 #include <iostream.h> 4 5 declare (RWGDlist, RWCString) 6 7 RWBoolean tester(const RWCString *,const void *); 8 9 main () { 10 11 RWGDlist(RWCString) words; 12 13 words.append(new RWCString("List")); 14 words.append(new RWCString("Set")); 15 words.append(new RWCString("Dictionary")); 16 17 RWCString item("Set"), *match; 18 19 if (match = words.find(tester,&item)) { 20 cout << "Match for " << item << " found" << endl; 21 } else { 22 cout << "No match found for " << item << endl; 23 } 24 } 25 26 RWBoolean tester(const RWCString *listitem,const void *item) { 27 if (*listitem == *(RWCString *)item) 28 return TRUE; 29 return FALSE; 30 } 31
Code 8-6
8-19
8
Exercises
Exercise objectives In the exercises for this module, which are located in the Module8 folder online, you will:
G
Use a template for a linked-list class so it can handle any type of data. Correctly implement the Tools.h++ string class in a program from a previous exercise. Correctly implement the Tools.h++ linked-list class in a program from a previous exercise.
8-20
8
Exercises Summary
Discussion Take a few minutes to discuss what experiences, issues, or discoveries you had during the lab exercises.
Manage the discussion here based on the time allowed for this module, which was given in the About This Course module. If you find you do not have time to spend on discussion, then just highlight the key concepts students should have learned from the lab exercise.
G
Experiences
Ask students what their overall experiences with this exercise have been. You may want to go over any trouble spots or especially confusing areas at this time.
G
Interpretations
Ask students to interpret what they observed during any aspects of this exercise.
G
Conclusions
Have students articulate any conclusions they reached as a result of this exercise experience.
G
Applications
Explore with students how they might apply what they learned in this exercise to situations at their workplace.
8-21
8
Check Your Progress
Before continuing on to the next module, check that you are able to accomplish or answer the following: K K K K K Write template functions Write template classes Handle exceptions Throw exceptions Write applications using the Tools.h++ class library
8-22
8
Think Beyond
Does C++ offer any generic functionality for utility routines such as data extraction, comparison, and sorting?
8-23
Describe the STL and its overall importance List the three main components of the STL and dene the general purpose of each component Correctly implement the STL in your code
9-1
Copyright 1999 Sun Microsystems, Inc. All Rights Reserved. Enterprise Services Nov. 1999, Revision H
9
Relevance
Present the following question to stimulate the students and get them thinking about the issues and topics presented in this module. While they are not expected to know the answer to this question, the answer should be of interest to them and inspire them to learn the material presented in this module.
Discussion What types of generic utility code have you written in the past that you wish would have been available in a library?
9-2
Container classes (also known as collection classes) Iterators, which are modeled after standard C pointers Generic algorithms (template functions)
The STL can be used independently from the C++ library. The following sections describe the general features of the STL. Sample code using the STL appears in the last three gures of the module.
1 The STL was developed at Hewlett-Packard Laboratories and was adopted by
9-3
Container Classes
Container classes hold collections of objects. The STL container classes provide ve major types of containers for manipulating and managing objects. A sixth member of the container classes, which is not really a container, is bitset, a denition of bitwise arithmetic operators. The major categories of STL classes are:
G G G G G G
Each class has an include le that has the same name as the class. For example, the Vector class has an include le call <vector>. None of the include les use a .h extension.
9-4
9
Sequence Containers
Sequence containers let you insert and remove values in specic positions of an object. They also let you iterate through objects forward, backward, and randomly.
Associative Containers
Associative containers associate keys with objects (as pairings of hash elements) to let you retrieve object elements. You can also use associative containers to insert and sort values, but not in specic positions as with sequence containers.
String Package
The String class lets you perform operations on characters. Some operations are assign, compare, nd, move, copy, search, concatenate, and return values.
Ropes
Rope containers are similar to string containers, but they perform operations on entire strings rather than on characters. Ropes are ideal for operations such as assignment and concatenation on entire strings. While ropes can be used on characters, they are best suited for handling long strings.
Container Adaptors
Container adaptors provide a subset of overall container functionality. They manage how objects are inserted into and removed from memory stacks and queues. For example, the Stack adaptor inserts, removes, and inspects only the object at the top of a stack in a last-inrst-out (LIFO) data structure.
Bitset
Bitset is not a container, because it doesnt contain iterators. Instead, it denes and provides access to bitwise arithmetic operators such as |= and &=.
9-5
Iterators
Iterators, which are modeled after standard C pointers, serve as intermediaries between STL classes and algorithms. They are often friend functions in STL classes that iterate over a range of objects and allow manipulation of private member data by STL algorithms. Specic iterators were created for specic classes. Iterators let you extend the STL with new algorithms that manipulate STL class members or with new classes that use STL algorithms. The major categories of STL iterators are:
G G G G G G
9-6
9
Input Iterators
Input iterators allow algorithms a single pass through a range of elements and provide only read access for returning values.
Output Iterators
Output iterators also allow algorithms a single pass through a range of elements but provide only write access for assigning new values.
Forward Iterators
Forward iterators allow algorithms multiple passes through elements in a forward direction, letting you either read elements or write new ones. You would use a forward iterator, for example, to move through a single linked list.
Bidirectional Iterators
Bidirectional iterators allow algorithms multiple passes through elements with both read and write access. But as the name suggests, bidirectional iterators allow algorithms to move forward and backward through values. You would use a bidirectional iterator, for example, to move forward then backward through a double linked list.
Trivial Iterators
A trivial iterator is an object that you can de-reference to refer to another mutable or constant object.
9-7
Generic Algorithms
STL algorithms are used for data manipulation on a variety of container classes. Generic algorithms can be applied to many different structures, including C++ arrays, vectors, and strings. The major categories of STL algorithms are:
G G G G
Non-Mutating Algorithms
Non-mutating algorithms read and return values and iterators. Non-mutating algorithm functionality includes returning the rst iterator in a range, comparing iterators for equality, and applying function object f to each element in a range and returning the function object after it has been applied to each element.
9-8
9
Mutating Algorithms
Mutating algorithms manipulate and change data. Mutating algorithm functionality includes copying elements from range to range, swapping element contents, replacing elements in a range, removing elements in a range that have certain values, and randomly rearranging elements in a range.
Sorting Algorithms
Sorting algorithms rearrange data. Sorting algorithm functionality includes sorting elements into ascending order (fully or partially), locating correct positions to insert elements into an ordered range, combining sorted ranges into a single sorted range, creating and manipulating heaps, and performing lexicographical comparison and permutation.
9-9
9
vector Class
The vector class supports random movement through a list to add and remove elements. vector is an array that can grow when requested. 1 #include <iostream> 2 #include <vector> 3 4 using namespace std; 5 6 typedef vector<int> intVector; 7 8 void showVector(const intVector& v){ 9 cout << "\nelements:\n"; 10 for(intVector::size_type i=0;i<v.size();++i) 11 cout << v[i] << ", "; 12 cout << "\nfront() = " << v.front(); 13 cout << "\nback() = " << v.back(); 14 15 cout << endl << endl; 16 } 17 18 int main() { 19 intVector vInt(3); 20 21 cout << "vInt(3)" << endl; 22 23 for(intVector::size_type i = 0; i<vInt.size(); ++i) 24 vInt[i] = 5*i; 25 26 try { 27 vInt.at((intVector::size_type)4) = 50; 28 } catch (out_of_range) { 29 cout << "Index out of range" << endl; 30 } 31 32 showVector(vInt); 33 34 vInt.resize(5,100); 35 36 cout << "vInt after resize(5,100)" << endl; 37 showVector(vInt); 38 39 try { 40 vInt.at((intVector::size_type)4) = 50;
9-10
9
41 } catch (out_of_range) { 42 cout << "Index out of range" << endl; 43 } 44 45 showVector(vInt); 46 }
Output
vInt(3) Index out of range elements: 0, 5, 10, front() = 0 back() = 10 vInt after resize(5,100) elements: 0, 5, 10, 100, 100, front() = 0 back() = 100 elements: 0, 5, 10, 100, 50, front() = 0 back() = 50
Code 9-1
9-11
9
List Class
The list class supports moving forward and backward through a double link list to add and remove elements. 1 #include <iostream> 2 #include <list> 3 4 using namespace std; 5 6 typedef list<int> intList; 7 typedef list<int>::iterator intListItor; 8 9 void showList(const intList& l){ 10 cout << "size() = "<<l.size() << ":"; 11 for (intList::const_iterator i=l.begin(); i!=l.end(); i++) 12 cout << *i << ", "; 13 14 cout << endl << endl; 15 } 16 17 int main() { 18 intList lInt(3); 19 int j = 0; 20 21 for (intListItor ia = lInt.begin(); ia!=lInt.end(); ia++) 22 *ia = 5 * j++; 23 24 cout << "lInt" << endl; 25 showList(lInt); 26 27 intList lInt2(5); 28 j = 0; 29 30 for (intListItor ia = lInt2.begin(); ia!=lInt2.end(); ia++) 31 *ia = 5 * j++; 32 33 cout << "lInt2" << endl; 34 showList(lInt2); 35 36 cout << "Splice:" << endl; 37 lInt.splice(++lInt.begin(),lInt2,++(++lInt2.begin()), lInt2.end()); 38 39 cout << "lInt" << endl; 40 showList(lInt); 41 cout << "lInt2" << endl;
9-12
9
42 showList(lInt2); 43 44 }
Output
lInt size() = 3: lInt2 size() = 5: Splice: lInt size() = 6: lInt2 size() = 2: 0, 5, 10,
0, 5,
Code 9-2
9-13
9
Stack Class
The stack class lets you read, insert, and remove the element at the top of a stack. stack is a last-in-rst-out (LIFO) data structure, meaning the element at the top of the stack is the most recent. 1 #include <iostream> 2 #include <stack> 3 4 using namespace std; 5 6 typedef stack<int> intStack; 7 8 void showStack(const intStack& aStack){ 9 cout << "size() = "<<aStack.size() << ""; 10 if (!aStack.empty()) 11 cout << "top = " << aStack.top(); 12 13 cout << endl << endl; 14 } 15 16 int main() { 17 intStack sInt; 18 19 cout << "Stack sInt created:" << endl; 20 showStack(sInt); 21 22 for (unsigned int i=0; i<5; i++) 23 sInt.push(i*2); 24 25 cout << "sInt:" << endl; 26 showStack(sInt); 27 28 sInt.top() = 100; 29 cout << "sInt top was modifed" << endl; 30 showStack(sInt); 31 32 cout << "show all elements:" << endl; 33 while (!sInt.empty()) { 34 cout << sInt.top() << ", "; 35 sInt.pop(); 36 } 37 cout << endl; 38 }
9-14
9
Output
Stack sInt created: size() = 0 sInt: size() = 5 sInt top was modifed size() = 5 show all elements: 100, 6, 4, 2, 0,
top = 8
top = 100
Code 9-3
9-15
9
Exercise
Exercise objective In the exercise for this module, which is located in the Module9 folder online, you will:
G
9-16
9
Exercise Summary
Discussion Take a few minutes to discuss what experiences, issues, or discoveries you had during the lab exercises.
Manage the discussion here based on the time allowed for this module, which was given in the About This Course module. If you find you do not have time to spend on discussion, then just highlight the key concepts students should have learned from the lab exercise.
G
Experiences
Ask students what their overall experiences with this exercise have been. You may want to go over any trouble spots or especially confusing areas at this time.
G
Interpretations
Ask students to interpret what they observed during any aspects of this exercise.
G
Conclusions
Have students articulate any conclusions they reached as a result of this exercise experience.
G
Applications
Explore with students how they might apply what they learned in this exercise to situations at their workplace.
9-17
9
Check Your Progress
Before continuing on to the next module, check that you are able to accomplish or answer the following: K K K Describe the STL and its overall importance List the three main components of the STL and dene the general purpose of each components Correctly implement the STL in your code
9-18
9
Think Beyond
How do you implement input and output in C++?
9-19
iostream Library
Objectives
Upon completion of this module, you will be able to:
G
10
Use member functions of the ostream and istream classes for input and output Use manipulators with objects of the ostream and istream classes Use the format state and error state bit ags for the istream and ostream classes to change the default formatting and to test the error state Use the ifstream, ofstream, and fstream classes to perform le input and output (I/O) Overload the insertion (<<) and extraction (>>) operators so that istream and ostream objects can read and write user-dened data types
10-1
Copyright 1999 Sun Microsystems, Inc. All Rights Reserved. Enterprise Services Nov. 1999, Revision H
10
Relevance
Present the following question to stimulate the students and get them thinking about the issues and topics presented in this module. While they are not expected to know the answer to this question, the answer should be of interest to them and inspire them to learn the material presented in this module.
10-2
10
iostream Library
Copyright 1999 Sun Microsystems, Inc. All Rights Reserved. Enterprise Services Nov. 1999, Revision H
10-3
10
ostream Class cout Corresponds to standard output (buffered) cerr Corresponds to standard error output (unbuffered) clog Corresponds to standard error output (buffered)
10-4
10
ios (error state and format state information) istream (input methods) ostream (output methods) fstream, ifstream, and ofstream (le input and output) The istream, ostream, and iostream classes require the <iostream.h> header le. The ifstream, ofstream and fstream classes require the <fstream.h> header le.
iostream Library
Copyright 1999 Sun Microsystems, Inc. All Rights Reserved. Enterprise Services Nov. 1999, Revision H
10-5
10
10-6
10
The following code example implements the fail() and clear() member functions. 1 #include <iostream.h> 2 main() 3 { 4 int val; 5 6 cout << "Enter a number:"; 7 cin >> val; 8 while (!cin) {// or while (cin.fail()) 9 // to test the error state 10 cin.clear(); // to clear error state 11 cin.ignore(80, \n);// remove data from stream 12 cout << "Enter a number:"; 13 cin >> val; 14 } // go back and try again 15 cout << val << endl;// got a number 16 } Code 10-1 Useful member functions
iostream Library
Copyright 1999 Sun Microsystems, Inc. All Rights Reserved. Enterprise Services Nov. 1999, Revision H
10-7
10
Stream Format Functions
Stream format functions control formatted input (using cin and the >> operator) and formatted output (using cout and the << operator). fill(),fill(char) flags(),flags(long) precision(),precision(int) setf(long, long) setf(long),unsetf(long) width(),width(int) Returns/sets the current ll character Returns/sets the current format ag settings Returns/sets the current oating point precision Resets ags in second parameter to setting in rst parameter Sets/unsets the format control ags (see the tables below) Returns/sets the current eld width (affects only the next item displayed)
Table 10-1 Formatting constants for setf(long) Formatting Constants for setf(long) ios::showbase ios::showpoint ios::uppercase ios::showpos Use base prexes on output (0, 0x) Show trailing decimal point and zeros for oating point numbers Use uppercase letters for hex output Use + before positive numbers Table 10-2 Arguments for setf(long, long) Arguments for setf(long,long) First Argument (how to set the bits) ios::dec,ios::hex,ios::oct ios::fixed, ios::scientific ios::left, ios::right ios::internal Second Argument (which bits to set) ios::basefield ios::floatfield ios::adjustfield ios::adjustfield Meaning Base 10, base 16, or base 8 Fixed-point or scientic Left or right justication Left justify sign or base prex and right justify value
10-8
10
Features of the ios Class
The following code example illustrates features of the ios class. 1 #include <iostream.h> 2 3 main() { 4 char input[80]; 5 int x = 89; 6 7 cout << "x is: " << x << endl; 8 cout.setf(ios::hex, ios::basefield); 9 cout << "hex x is: " << x << " and 54 is " << 54 << endl; 10 // this setting remains in effect 11 12 cout.setf(ios::dec, ios::basefield); 13 cout << "dec x is: " << x << endl;// reset to dec format 14 15 cout << "Using a field width, x is "; 16 cout.width(10); // only affects next output item 17 cout << x << endl; 18 cout << "and with no field width x is "<< x << endl; 19 cout.width(10); cout.fill(&); cout << x << endl; 20 cout.fill( ); // reset fill character to default 21 22 cout << "Enter some text: "; cin.width(5); cin >> input; 23 cout << input << endl; 24 cin >> input; cout << input << endl; 25 26 float f = 34.2845435, g = 54.0; 27 28 cout << "Default format: f = " << f << " and g = " << g 29 << endl; // without showpoint 30 31 cout.setf(ios::showpoint); 32 cout << "With showpoint set g = " << g << endl; 33 cout.precision(4); 34 cout << "With precision of 4: f = " << f << endl; 35 cout.setf(ios::fixed, ios::floatfield); 36 cout.precision(6); 37 cout << "With precision of 6 and fixed notation: f = " 38 << f << endl; 39 }
iostream Library
Copyright 1999 Sun Microsystems, Inc. All Rights Reserved. Enterprise Services Nov. 1999, Revision H
10-9
10
Output
x is: 89 hex x is: 59 and 54 is 36 dec x is: 89 Using a field width, x is 89 and with no field width x is 89 &&&&&&&&89 Enter some text: computerized comp uterized Default format: f = 34.2845 and g = 54 With showpoint set g = 54.0000 With precision of 4: f = 34.28 With precision of 6 and fixed notation: f = 34.284542
Code 10-2
10-10
10
Manipulators
Manipulators are special functions that are part of the iostream library. Manipulators are placed in an ostream or an istream statement as if they were an item to be written or read. For example: cout << 83 << flush; The word flush is actually a call to the function: ostream& flush(ostream&); Manipulators provide a method for extending the insertion and extraction operators. There are two types of manipulators:
G G
Non-parameterized Parameterized
iostream Library
10-11
Copyright 1999 Sun Microsystems, Inc. All Rights Reserved. Enterprise Services Nov. 1999, Revision H
10
Non-parameterized Manipulators
Non-parameterized manipulators do not require parameter values. The flush parameter is an example. Following is a list of non-parameterized manipulators with the class les to which they belong.
G
dec (istream or ostream) Reads/writes integers in decimal format hex (istream or ostream) Reads/writes integers in hexadecimal format oct (istream or ostream) Reads/writes integers in octal format endl (ostream) Writes a newline on the output stream and ush the buffer ends (ostream) Writes a NULL on the output stream flush (ostream) Flushes the output buffer ws (istream) Extracts whitespace characters
G G G
Parameterized Manipulators
Parameterized manipulators require one or more parameters when they are used. For example: char input[60]; cin >> setw(60) >> input; Following is a list of parameterized manipulators for reading (cin) or writing (cout).
G G G
setw(int) Sets eld width setfill(int) Sets ll character setprecision(int) Sets precision (number of digits), default is 6
10-12
10
G
setiosflags(long) Calls the setf(long) to set ags for the stream resetiosflags(long) Calls setf(0, long) to reset ags for the stream
iostream Library
10-13
Copyright 1999 Sun Microsystems, Inc. All Rights Reserved. Enterprise Services Nov. 1999, Revision H
10
Manipulators Example
The following code example implements iostream manipulators. 1 #include <iostream.h> 2 #include <iomanip.h> 3 4 using namespace std; 5 6 main() { 7 char input[80]; 8 int x = 89; 9 10 cout << "x is: " << x << endl; 11 cout << hex; 12 cout << "hex x is: " << x << " and 54 is " << 54 << endl; 13 // this setting remains in effect 14 15 cout << dec; 16 cout << "dec x is: " << x << endl;// reset to dec format 17 18 cout << "Using a field width, x is "; 19 cout << setw(10);// only affects next output item 20 cout << x << endl; 21 cout << " and with no field width x is "<< x << endl; 22 cout << setw(10); cout << setfill(&); cout << x << endl; 23 cout << setfill( );// reset fill character to default 24 25 cout << "Enter some text: "; cin >> setw(5); cin >> input; 26 cout << input << endl; 27 cin >> input; cout << input << endl; 28 29 float f = 34.2845435, g = 54.0; 30 31 cout << "Default format: f = " << f << " and g = " << g 32 << endl;// without showpoint 33 34 cout << setiosflags(ios::showpoint); 35 cout << "With showpoint set g = " << g << endl; 36 cout << setprecision(4); 37 cout << "With precision of 4: f = " << f << endl; 38 cout << setiosflags(ios::fixed); 39 cout << setprecision(6); 40 cout << "With precision of 6 and fixed notation: f = " << f << endl; 41 }
10-14
10
Output
x is: 89 hex x is: 59 and 54 is 36 dec x is: 89 Using a field width, x is 89 and with no field width x is 89 &&&&&&&&89 Enter some text: computerized comp uterized Default format: f = 34.2845 and g = 54 With showpoint set g = 54.0000 With precision of 4: f = 34.28 With precision of 6 and fixed notation: f = 34.284542
Code 10-3
iostream Library
10-15
Copyright 1999 Sun Microsystems, Inc. All Rights Reserved. Enterprise Services Nov. 1999, Revision H
10
Writing a Non-Parameterized Manipulator
Writing a manipulator that takes no arguments is easy, as the following code example shows. 1 2 3 4 5 6 7 8 9 #include <iostream.h> ostream & tab(ostream &out) { return out << \t; } main() { cout << "hello" << tab << "world" << endl; }
Output
hello world
Code 10-4
10-16
10
Writing a Parameterized Manipulator
Writing a manipulator that takes parameters is more complicated. It requires the use of macros dened in the iomanip.h header le, as the following code example shows. 1 #include <iostream.h> 2 #include <iomanip.h> 3 4 using namespace std; 5 6 ostream & mytab(ostream & out, int n) { 7 while(n-- > 0) 8 out << ; 9 return out; 10 } 11 12 OMANIP(int) mytab(int n) { 13 return OMANIP(int)(mytab, n); 14 } 15 16 main() { 17 cout << "hello" << mytab(3) << "world" << endl; 18 }
Output
hello world
Code 10-5
iostream Library
10-17
Copyright 1999 Sun Microsystems, Inc. All Rights Reserved. Enterprise Services Nov. 1999, Revision H
10
10-18
10
iostream Library
10-19
Copyright 1999 Sun Microsystems, Inc. All Rights Reserved. Enterprise Services Nov. 1999, Revision H
10
Reads and discards n chars or up to delimiter Returns next character (as integer) without extracting it Puts char back on input stream to be read Reads i characters and stores in string Moves get-pointer in stream. seek_dir can be one of: beg, cur, end Returns offset of get-pointer in stream
10-20
10
Using istream and ostream Functions
The following code example implements istream and ostream functions. 1 #include <stdlib.h> 2 #include <iostream.h> 3 main() { 4 char input[80]; 5 char one_char; 6 7 cout << "this is formatted output" << endl; 8 cout << "and here is non-formatted output" << endl; 9 cout.write("Sun Microsystems, Inc.", 16); 10 cout << endl; 11 cout.put(x); 12 cout.put(y); 13 cout.put(z).put(z).put(y).put(\n); 14 cout << x << y << z << z << y << \n << flush; 15 16 cout << "Enter some text: " ; 17 // reading from STDIN causes STDOUT to be flushed 18 cin >> input; // reads one word only (no whitespace) 19 cin.ignore(256, \n); // ignore up to next newline 20 cout << input << " was read, the rest was ignored" << endl; 21 cout << "Enter some text: " ; 22 23 cin.getline(input, 80, \n); // non-formatted input 24 cout << input << " was read" << endl; 25 26 cout <<"Enter some text: " ; 27 cin.getline(input, 80); 28 // newline is default value for last parameter 29 cout << input << " was read" << endl; 30 cout << cin.gcount() << " characters were read." << endl; 31 32 cout << "Enter some text: "; 33 cin.get(one_char); 34 cout << one_char; 35 cout << (char)cin.get() << (char)cin.get(); 36 cout << (char)cin.get() << endl; 37 // casting is because cin.get() returns an integer value 38 cout << "the next character to be read is: " ; 39 cout << (char)cin.peek() << endl; 40 // cin.peek() returns integer value also
iostream Library
10-21
Copyright 1999 Sun Microsystems, Inc. All Rights Reserved. Enterprise Services Nov. 1999, Revision H
10
41 42 43 44 45 46 47 48 49 50 51 52 53 54 } cin.get(one_char); cout << "and here it is: " << one_char << endl;
cout << "and now it is put back" << endl; cin.putback(one_char); cout << "and here it is again: " << (char)cin.get() << endl; cin.ignore(256, \n); // clear out input buffer cout << "Enter some text: "; cin.read(input, 8); input[cin.gcount()] = \0; cout<< input << endl;
Output
this is formatted output and here is non-formatted output Sun Microsystems xyzzy xyzzy Enter some text: hello there world hello was read, the rest was ignored Enter some text: hello there world hello there world was read Enter some text: hello there world hello there world was read 18 characters were read. Enter some text: hello there world hell the next character to be read is: o and here it is: o and now it is put back and here it is again: o Enter some text: hello there world hello th
Code 10-6
10-22
10
The operator<<() and operator>>() functions should usually be implemented as friend functions.
For consistency, the output stream should be on the left side of the operator and the user-dened data type object should be on the right. cout << one;
iostream Library
10-23
Copyright 1999 Sun Microsystems, Inc. All Rights Reserved. Enterprise Services Nov. 1999, Revision H
10
G
If the operator<<() function is implemented as a member function, then the object that is being printed must be on the left side of the operator, and the output stream must be on the right side, as the following example shows. class Number { int x; public: // various member functions ostream& operator<<(ostream&); }; Number one; one << cout;
Return Value
The return value of the operator<<() function should be a reference to an ostream object (ostream&). This is done so that statements such as the following can be executed: Number one; cout << 5 << one << hello << endl;
Each occurrence of the insertion operator (<<) is a call to the operator<<() function. When overloading the extraction operator, the operator>>() function should return a reference to an istream object (istream&).
10-24
10
The following code example implements overloaded insertion and extraction operators. 1 #include <iostream.h> 2 #include <string.h> 3 class Employee { 4 int id; 5 char *name; 6 float salary; 7 public: 8 Employee (const char* = "", int = -1, float = 0.0); 9 ~Employee (void) { delete name; } 10 friend ostream& operator<< (ostream&, const Employee&); 11 friend istream& operator>> (istream&, Employee&); 12 }; 13 14 Employee::Employee (const char *n, int num, float pay) :id(num), salary(pay) { 15 name = new char[strlen(n) + 1]; 16 strcpy(name, n); 17 } 18 19 ostream& operator<< (ostream &out, const Employee &emp ) { 20 out << emp.id << " " << emp.name << " " <<emp.salary << endl; 21 return out; 22 } 23 24 istream& operator>> (istream &in, Employee &emp) { 25 26 char input[80]; 27 cout << "Enter employee id: "; in >> emp.id; 28 29 cout << "Enter employee name: " << flush; 30 in.ignore(256,\n); 31 in.getline(input, sizeof(input)); 32 delete [] emp.name; 33 emp.name = new char[strlen(input) + 1]; 34 strcpy(emp.name, input); 35 36 cout << "Enter employee salary: "; in >> emp.salary; 37 return in; 38 } 39 40 main() { 41 42 Employee eric("eric", 200, 12300.0);
iostream Library
10-25
Copyright 1999 Sun Microsystems, Inc. All Rights Reserved. Enterprise Services Nov. 1999, Revision H
10
43 44 45 46 47 48 49 50 } Employee temp; cout << eric; cin >> temp; cout << temp;
Output
200 eric 12300 Enter employee id: 999 Enter employee name: J. Temp Enter employee salary: 21.10 999 J. Temp 21.1
Code 10-7
10-26
10
These classes are derived from the ostream and istream classes. All of the features discussed about istream (cin) and ostream (cout) objects also apply to le input and output objects. The <fstream.h> header le is required to perform le I/O.
iostream Library
10-27
Copyright 1999 Sun Microsystems, Inc. All Rights Reserved. Enterprise Services Nov. 1999, Revision H
10
Creating File I/O Objects
There are no predened le I/O objects to use. You can use constructors to associate a le with a le object. Use the following constructors for le input:
G G
ifstream(); ifstream(const char* name, int mode=ios::in, int prot=filebuf::openprot); ifstream(int fd);
ofstream(); ofstream(const char* name, int mode=ios::out, int prot=filebuf::openprot); ofstream(int fd);
fstream(); fstream(const char* name, int mode, int prot=filebuf::openprot); fstream(int fd);
The second argument to the constructor that opens the le is the open mode as dened in the ios class. For example: enum open_mode { in, out, ate, app, trunc, nocreate, noreplace };
10-28
10
The following table describes each open mode. Table 10-3 ios class modes for opening les Open Modes in out ate app Meaning Open le for input (this is assumed when ifstream objects are created). Open le for output (this is assumed when ofstream objects are created), implies ios::trunc (truncates le). Move to end of le (input or output), prevents truncation. Move to end of le. All data that is written is added (appended) to the end of the le. This implies ios::out; prevents truncation. If the le exists, truncate it (this is assumed when ios::out is used and neither ios::ate or ios::app is used). If ios::out is set and the le does not exist, the open fails. If ios::out is set and the le does exist, the open fails.
iostream Library
10-29
Copyright 1999 Sun Microsystems, Inc. All Rights Reserved. Enterprise Services Nov. 1999, Revision H
10
Useful Member Functions
The following member functions are available in the le I/O classes.
G G G
The open()function opens a le and associates it with a le object. The close()function disassociates and closes the le. The attach(int fd)function connects the le object to the specied le descriptor. fstream file; file.open("file", ios::in); file.close(); file.open("file", ios::out, 0600); file.close(); int fd; ... // fd is an open file descriptor file.attach(fd);
10-30
10
The following code example implements le I/O. 1 #include <string.h> 2 #include <stdlib.h> 3 #include <fstream.h> 4 5 /* append contents of filename2 to end of filename1 then 6 ** re-read filename1 one line at a time and output each 7 ** line to stdout preceded by a count of the number of 8 ** characters in the line 9 */ 10 int main(int argc, char **argv) { 11 char c; 12 13 if(argc != 3) { 14 cerr << "Usage: append filename1 filename2" << endl; 15 exit(1); 16 } 17 fstream out(argv[1], ios::in | ios::out | ios::app); 18 if(!out) { 19 cerr << "error on opening " << argv[1] << endl; 20 exit(1); 21 } 22 ifstream in(argv[2]); 23 if (!in) { 24 cerr << "error on opening " << argv[2] << endl; 25 exit(1); 26 } 27 while(in.get(c) && !in.eof()) 28 out.put(c); 29 in.close(); 30 31 out.seekg(0, ios::beg); 32 char linebuf[100]; 33 while(out.getline(linebuf, sizeof(linebuf))) 34 cout << "[" << out.gcount() << "] " << linebuf << endl; 35 out.close(); 36 return 0; 37 } Code 10-8 File I/O
iostream Library
10-31
Copyright 1999 Sun Microsystems, Inc. All Rights Reserved. Enterprise Services Nov. 1999, Revision H
10
Sample Output for Code 10-8
G
Contents of filename1: The C++ Programming Language, Stroustrup Effective C++, Meyers Advanced C++, Coplien
Output of example program: [41] [22] [22] [20] The C++ Programming Language, Stroustrup Effective C++, Meyers Advanced C++, Coplien C++ Primer, Lippman
Contents of filename1 after running program: The C++ Programming Language, Stroustrup Effective C++, Meyers Advanced C++, Coplien C++ Primer, Lippman
10-32
10
iostream Library
10-33
Copyright 1999 Sun Microsystems, Inc. All Rights Reserved. Enterprise Services Nov. 1999, Revision H
10
1 #include <strstream.h> 2 int main(int argc, char **argv) { 3 int arg; 4 int sum = 0; 5 6 for(int i = 1; i < argc; i++) { 7 istrstream(argv[i]) >> arg;// unnamed stream 8 sum += arg; 9 } 10 11 char total[80]; 12 ostrstream output(total, sizeof(total));// named stream 13 14 output << "The total is " << sum << ends; 15 cout << total << endl; 16 return 0; 17 }
Output
% a.out 1 3 5 The total is 9 %
Code 10-9
10-34
10
Another File I/O Example
Discussion Look through the following program and figure out what it does.
1 #include <fstream.h> 2 class Employee { 3 char name[40]; 4 short id; 5 float salary; 6 long file_pos; 7 public: 8 static fstream file; 9 Employee(void) { 10 file_pos = file.tellg(); 11 file.read((char *)this, (sizeof(Employee) - sizeof(file_pos))); 12 } 13 ~Employee(void) { 14 file.clear(); 15 file.seekp(file_pos); 16 file << this; 17 } 18 friend fstream& operator<<(fstream &f, Employee *e); 19 void raise(float amt) { salary *= (1.0 + amt); } 20 void print(void) { cout << name << " has id # " << id << " with 21 salary " << salary << endl; } 22 }; 23 24 fstream Employee::file("employee.data", ios::in | ios::out); 25 26 fstream& operator<<(fstream &f, Employee *e) { 27 f.write((char *)e, (sizeof(Employee) - sizeof(e->file_pos))); 28 return f; 29 } 30 31 main() { 32 const int NUM_EMPS = 5; 33 Employee records[NUM_EMPS]; 34 35 for(int i = 0; i < NUM_EMPS; i++) 36 records[i].raise(0.15);
iostream Library
10-35
Copyright 1999 Sun Microsystems, Inc. All Rights Reserved. Enterprise Services Nov. 1999, Revision H
10
37 38 for(int i = 0; i < NUM_EMPS; i++) 39 records[i].print(); 40 } Code 10-10 Another File I/O example
10-36
10
Exercise
Exercise objective In the exercise for this module, which is located in the Module10 folder online, you will:
G
Modify a previous exercise to implement input and output for the program.
iostream Library
10-37
Copyright 1999 Sun Microsystems, Inc. All Rights Reserved. Enterprise Services Nov. 1999, Revision H
10
Exercise Summary
Discussion Take a few minutes to discuss what experiences, issues, or discoveries you had during the lab exercises.
Manage the discussion here based on the time allowed for this module, which was given in the About This Course module. If you find you do not have time to spend on discussion, then just highlight the key concepts students should have learned from the lab exercise.
G
Experiences
Ask students what their overall experiences with this exercise have been. You may want to go over any trouble spots or especially confusing areas at this time.
G
Interpretations
Ask students to interpret what they observed during any aspects of this exercise.
G
Conclusions
Have students articulate any conclusions they reached as a result of this exercise experience.
G
Applications
Explore with students how they might apply what they learned in this exercise to situations at their workplace.
10-38
10
Check Your Progress
Before continuing on to the next module, check that you are able to accomplish or answer the following: K K K Use member functions of the ostream and istream classes for input and output Use manipulators with objects of the ostream and istream classes Use the format state and error state bit ags for the istream and ostream classes to change the default formatting and to test the error state Use the ifstream, ofstream, and fstream classes to perform le input and output (I/O) Overload the insertion (<<) and extraction (>>) operators so that istream and ostream objects can read and write user-dened data types
K K
iostream Library
10-39
Copyright 1999 Sun Microsystems, Inc. All Rights Reserved. Enterprise Services Nov. 1999, Revision H
10
Think Beyond
What are some good resources to help you move forward with the concepts presented in this course?
10-40
Solution to trace.cc
This appendix provides the solution to the trace.cc problem in Module 5, Exercise 2.
A-1
Copyright 1999 Sun Microsystems, Inc. All Rights Reserved. Enterprise Services Nov. 1999, Revision H
A
trace.cc Program
Following is the trace.cc program. The exercise asked you to look at the code and try to determine the order of the constructor and operator calls. You were then to compile and run the program to compare expected output to actual output. 1 #include <string.h> 2 #include <stdio.h> 3 class String{ 4 int length; 5 char *string; 1 public: 2 String(void) { 3 printf("void constructor \n"); 4 length = 1; string = new char('\0'); 5 printf(" destination object %x string +%x\n\n", this, 6 string); 7 } 8 9 String(const char * arg) { 10 printf("char * constructor \n"); 11 printf(" source object %x contents %s\n", arg, arg); 12 strcpy(string = new char[length = strlen(arg) + 1], arg); 13 printf(" destination object %x string +%x\n\n", this, 14 string); 15 } 16 17 String(const String& arg) { 18 printf("const String& constructor\n"); 19 printf(" source object %x string %x contents %s\n", 20 &arg, arg.string, arg.string); 21 strcpy(string = new char[length = arg.length + 1], 22 arg.string); 23 printf(" destination object %x string +%x\n\n", this, 24 string); 25 } 26 27 String& operator=(const String& arg) { 28 if(this == &arg) return *this; 29 printf("operator =\n"); 30 printf(" source object %x string %x contents %s\n", 31 &arg, arg.string, arg.string); 32 printf(" destination object %x old string -%x contents 33 %s\n", this, string, string);
A-2
A
34 delete [] string; 35 strcpy(string = new char[length = arg.length + 1], 36 arg.string); 37 printf("\t\t\tnew string +%x\n\n", string); 38 return *this; 39 } 40 ~String(void) { 41 printf("Destructor object %x string -%x contents %s\n\n", 42 this, string, string); 43 delete [] string; 44 } 45 46 friend String operator+(const String left, 47 const String right) { 48 printf("operator+\n"); 49 String temp; 50 printf(" left object %x string %x contents %s\n", 51 &left, left.string, left.string); 52 printf(" right object %x string %x contents %s\n", 53 &right, right.string, right.string); 54 temp.length = left.length + right.length; 55 temp.string = new char[temp.length+1]; 56 strcpy(temp.string, left.string); 57 strcat(temp.string, right.string); 58 printf(" destination object %x string +%x contents 59 %s\n\n", &temp, temp.string, temp.string); 60 return temp; 61 } 62 }; 63 64 65 main(){ 66 String s("Hello "); 67 s = s + "World"; 68 } 69 The following diagrams show the correct order in which the constructors and operators were called, along with the respective output.
Solution to trace.cc
Copyright 1999 Sun Microsystems, Inc. All Rights Reserved. Enterprise Services Nov. 1999, Revision H
A-3
A
String s(Hello);
main effffbfc
s
STACK
6 235c0
235c0
21ce0 21be4
Output
char * constructor source destination object 21be4 contents Hello object effffbfc string +235c0
A-4
A
s = s + " World"; // setup for operator+
s
main
effffbfc
6 235c0
STACK
operator+
unnamed temp
effffbec
6 235d0
unnamed temp
effffbd8
7 235e0
temp
effffbc0
1 235f0
Solution to trace.cc
Copyright 1999 Sun Microsystems, Inc. All Rights Reserved. Enterprise Services Nov. 1999, Revision H
A-5
A
Output
const String& constructor source object effffbfc string 235c0 contents Hello destination object effffbec string +235d0 char * constructor source destination operator+ void constructor destination
A-6
A
Just before "return temp;" in operator+
main
s
STACK
effffbfc
6 235c0
unnamed temp
operator+
effffbec
6 235d0
unnamed temp
(copy ctor) s (left) (char * ctor) World (right) result returned by operator+
effffbd8
7 235e0
temp
effffbc0
HEAP
DATA TEXT
Output
left right destination object effffbec string 235d0 contents Hello object effffbd8 string 235e0 contents World object effffbc0 string +239b8 contents Hello World
Solution to trace.cc
Copyright 1999 Sun Microsystems, Inc. All Rights Reserved. Enterprise Services Nov. 1999, Revision H
A-7
A
Return to main from operator+ (before dtors)
main
s
STACK
effffbfc
6 235c0
unnamed temp
effffbc8
13 239d0
Hello World Hello World \0 World Hello Hello World Hello TEXT HEAP DATA
Output
const String& constructor source object effffbc0 string 239b8 contents Hello World destination object effffbc8 string 239d0
A-8
A
Return to main from operator+ (after dtors)
main
s
STACK
effffbfc
6 235c0
unnamed temp
effffbc8
13 239d0
HEAP DATA
Output
Destructor object effffbc0 string -239b8 contents Hello World Destructor object effffbec string -235d0 contents Hello Destructor object effffbd8 string -235e0 contents World
Solution to trace.cc
Copyright 1999 Sun Microsystems, Inc. All Rights Reserved. Enterprise Services Nov. 1999, Revision H
A-9
A
s = s + "World";
main
STACK
effffbfc
6 235c0
unnamed temp
effffbc8
13 239d0
operator=
reference to s
6 235c0
reference to unnamed temp
(this)
(arg)
Output
operator= source destination object effffbc8 string 239d0 contents Hello World object effffbfc old string -235c0 contents Hello new string +221f0
A-10
A
s = s + "World"; // Before return from operator=
main effffbfc
s
13 221f0
unnamed temp
STACK
effffbc8
13 239d0
reference to s
operator=
13 221f0
reference to unnamed temp
(this)
13 239d0
(arg)
Solution to trace.cc
Copyright 1999 Sun Microsystems, Inc. All Rights Reserved. Enterprise Services Nov. 1999, Revision H
A-11
A
s = s + "World";
main
effffbfc
STACK
13 221f0
221f0
Hello World
235f0
\0 HEAP
21ce0 21be4
World Hello
DATA
TEXT
Output
Destructor object effffbc8 string -239d0 contents Hello World Destructor object effffbfc string -221f0 contents Hello World
A-12
Glossary
abstraction A term applied to the process of hiding unimportant details in favor of those that matter. Function and data abstraction are tools employed in software engineering to handle complexity. aggregation See composition. ANSI American National Standards Institute. association A term that describes an object that is associated with another when it uses the other for some purpose. This is a exible object relationship, in which the association can be made and broken at any time. A Person object may be associated with a Book object, then another Book object. The lifetimes of the objects need only intersect. See also composition. base class A class that is used to derive a new class. class UML notation used to dene the classication of a group of related objects. The objects share common behavior and a common state. The class provides a description of the common behavior (operations) and state (data). For example, a class Person denes the common behavior and state which objects of Person will possess. See also object.
Glossary-1
Copyright 1999 Sun Microsystems, Inc. All Rights Reserved. Enterprise Services Nov. 1999, Revision H
collection class Used to contain collections of other objects. The behavior of the collection reects the organizational structure required when grouping the objects. For example, a list collection class organizes objects into a list, a tree collection class organizes objects into a tree. Also called container class. composition The object relationship of has a or aggregation. It is useful when one object contains another for the duration of its life and its components life. For example, a Person object contains a Heart object, both are created together and destroyed together. Composition is less exible than association, but it removes the need to manage explicitly the creation and destruction of the components. See also association. constructor A special member function that is called automatically when an object is created. A constructor is used to initialize the data members of an object. container class See collection class. demangling Reversing the compiler name mangling process on functions. destructor A function that cleans up when an object goes out of scope. Cleaning up involves releasing memory, ushing I/O buffers, or closing les. dynamic binding The process a computer uses to carry out actions in a program dynamically at runtime rather than earlier at compile time. encapsulation Separates the external aspects of an object, which are accessible to other objects, from the internal implementation details of the object, which are hidden from other objects. The keywords used to implement encapsulation are public, private, and protected. exception A program error that occurs at runtime.
Glossary-2
friend function A function that non-member functions can access to modify private parts of a class. inheritance The process by which a new class is derived from an existing class (base class). It is a central concept in object-oriented systems and enables the reuse of the base class members. During class inheritance, the derived class may extend, override, and hide members inherited from the base class. ISO International Standards Organization. iterator Functions that allow access to private class members, letting you iterate through a range of objects. Iterators are prominent parts of the Standard Template Library. Iterators were modeled after C pointers. mangling See name mangling. manipulators Special functions that are part of the iostream library. Manipulators provide a method for extending the insertion and extraction operators (<< and >>). member A function or variable that is dened within the opening and closing braces of a class, structure, or object denition. name mangling The process the C++ compiler uses to resolve duplicate function identiers. object An instance or variable of a class. The class species the nature of an object, its operations and attributes, and the object is an actual instantiation of this object. A class Person describes persons in general. Jon, Sonja, and Mark are actual objects of Person.
Glossary
Glossary-3
Copyright 1999 Sun Microsystems, Inc. All Rights Reserved. Enterprise Services Nov. 1999, Revision H
object-oriented (OO) programming A non-procedural programming methodology used with objectoriented programming languages (such as C++, Java, and Smalltalk). The goal of object orientation (OO) is to model programs after real or abstract things, or objects: coffee cup, person, computer, sunshine. Rather than a program running through a long list of sequential statements, objects interact with each other. They contain both data and operations and are usually stand-alone, making them easy to maintain, reference, and reuse. The efciency with which objects are modeled and built to reect their environment, or problem domain, determines the level of maintainability and reusemaking OO more of an art than a science. Key concepts of OO programming include objects, classes, encapsulation, inheritance, and polymorphism. OO See object-oriented (OO) programming. overloaded functions Functions that have the same name but have different parameters. polymorphism Two functions with the same name but different implementations. For the classes Football and Baseball, the function throw might exist for both. However, the way one throws a football differs from throwing a baseball; therefore the implementation of the function is different in each class and the function is polymorphic. reference A copy of an existing piece of data in memory. Standard Template Library (STL) A library of C++ templates, developed at Hewlett-Packard Laboratories and adopted as an ANSI/ISO standard to the C++ language in 1994. STL is used to perform generic data and object manipulation such as sorting, reordering, searching, comparing, moving, concatenating, and so forth. template A class or function that serves as the basis for an innite set of classes or functions. For example, a single function template can be used to manipulate multiple data types.
Glossary-4
UML Unied Modeling Language. UML is used to model and notate a system in preparation for development. virtual function A function that provides dynamic binding and denes type- or class-dependent operations within an inheritance hierarchy. Virtual functions are the means by which you implement polymorphism in C++.
Glossary
Glossary-5
Copyright 1999 Sun Microsystems, Inc. All Rights Reserved. Enterprise Services Nov. 1999, Revision H
Copyright 1999 Sun Microsystems Inc., 901 San Antonio Road, Palo Alto, California 94303, Etats-Unis. Tous droits rservs. Ce produit ou document est protg par un copyright et distribu avec des licences qui en restreignent lutilisation, la copie, la distribution, et la dcompilation. Aucune partie de ce produit ou document ne peut tre reproduite sous aucune forme, par quelque moyen que ce soit, sans lautorisation pralable et crite de Sun et de ses bailleurs de licence, sil y en a. Le logiciel dtenu par des tiers, et qui comprend la technologie relative aux polices de caractres, est protg par un copyright et licenci par des fournisseurs de Sun. Des parties de ce produit pourront tre drives du systmes Berkeley 4.3 BSD licencis par lUniversit de Californie. UNIX est une marque dpose aux Etats-Unis et dans dautres pays et licencie exclusivement par X/Open Company Ltd. Sun, Sun Microsystems, le logo Sun, Sun Visual Workshop, Sun C++, OpenWindows, Java, et Solaris sont des marques de fabrique ou des marques dposes de Sun Microsystems, Inc. aux Etats-Unis et dans dautres pays. Toutes les marques SPARC sont utilises sous licence sont des marques de fabrique ou des marques dposes de SPARC International, Inc. aux Etats-Unis et dans dautres pays. Les produits portant les marques SPARC sont bass sur une architecture dveloppe par Sun Microsystems, Inc. UNIX est une marques dpose aux Etats-Unis et dans dautres pays et licencie exclusivement par X/Open Company, Ltd. Linterfaces dutilisation graphique OPEN LOOK et Sun a t dveloppe par Sun Microsystems, Inc. pour ses utilisateurs et licencis. Sun reconnat les efforts de pionniers de Xerox pour larecherche et le dveloppement du concept des interfaces dutilisation visuelle ou graphique pour lindustrie de linformatique. Sun dtient une licence non exclusive de Xerox sur linterface dutilisation graphique Xerox, cette licence couvrant galement les licencis de Sun qui mettent en place linterface dutilisation graphique OPEN LOOK et qui en outre se conforment aux licences crites de Sun. Laccord du gouvernement amricain est requis avant lexportation du produit. Le systme X Window est un produit de X Consortium, Inc. LA DOCUMENTATION EST FOURNIE EN LETAT ET TOUTES AUTRES CONDITIONS, DECLARATIONS ET GARANTIES EXPRESSES OU TACITES SONT FORMELLEMENT EXCLUES, DANS LA MESURE AUTORISEE PAR LA LOI APPLICABLE, Y COMPRIS NOTAMMENT TOUTE GARANTIE IMPLICITE RELATIVE A LA QUALITE MARCHANDE, A LAPTITUDE A UNE UTILISATION PARTICULIERE OU A LABSENCE DE CONTREFAON.
Please Recycle