- •Contents
- •Introduction
- •Who This Book Is For
- •What This Book Covers
- •How This Book Is Structured
- •What You Need to Use This Book
- •Conventions
- •Source Code
- •Errata
- •p2p.wrox.com
- •The Basics of C++
- •The Obligatory Hello, World
- •Namespaces
- •Variables
- •Operators
- •Types
- •Conditionals
- •Loops
- •Arrays
- •Functions
- •Those Are the Basics
- •Diving Deeper into C++
- •Pointers and Dynamic Memory
- •Strings in C++
- •References
- •Exceptions
- •The Many Uses of const
- •C++ as an Object-Oriented Language
- •Declaring a Class
- •Your First Useful C++ Program
- •An Employee Records System
- •The Employee Class
- •The Database Class
- •The User Interface
- •Evaluating the Program
- •What Is Programming Design?
- •The Importance of Programming Design
- •Two Rules for C++ Design
- •Abstraction
- •Reuse
- •Designing a Chess Program
- •Requirements
- •Design Steps
- •An Object-Oriented View of the World
- •Am I Thinking Procedurally?
- •The Object-Oriented Philosophy
- •Living in a World of Objects
- •Object Relationships
- •Abstraction
- •Reusing Code
- •A Note on Terminology
- •Deciding Whether or Not to Reuse Code
- •Strategies for Reusing Code
- •Bundling Third-Party Applications
- •Open-Source Libraries
- •The C++ Standard Library
- •Designing with Patterns and Techniques
- •Design Techniques
- •Design Patterns
- •The Reuse Philosophy
- •How to Design Reusable Code
- •Use Abstraction
- •Structure Your Code for Optimal Reuse
- •Design Usable Interfaces
- •Reconciling Generality and Ease of Use
- •The Need for Process
- •Software Life-Cycle Models
- •The Stagewise and Waterfall Models
- •The Spiral Method
- •The Rational Unified Process
- •Software-Engineering Methodologies
- •Extreme Programming (XP)
- •Software Triage
- •Be Open to New Ideas
- •Bring New Ideas to the Table
- •Thinking Ahead
- •Keeping It Clear
- •Elements of Good Style
- •Documenting Your Code
- •Reasons to Write Comments
- •Commenting Styles
- •Comments in This Book
- •Decomposition
- •Decomposition through Refactoring
- •Decomposition by Design
- •Decomposition in This Book
- •Naming
- •Choosing a Good Name
- •Naming Conventions
- •Using Language Features with Style
- •Use Constants
- •Take Advantage of const Variables
- •Use References Instead of Pointers
- •Use Custom Exceptions
- •Formatting
- •The Curly Brace Alignment Debate
- •Coming to Blows over Spaces and Parentheses
- •Spaces and Tabs
- •Stylistic Challenges
- •Introducing the Spreadsheet Example
- •Writing Classes
- •Class Definitions
- •Defining Methods
- •Using Objects
- •Object Life Cycles
- •Object Creation
- •Object Destruction
- •Assigning to Objects
- •Distinguishing Copying from Assignment
- •The Spreadsheet Class
- •Freeing Memory with Destructors
- •Handling Copying and Assignment
- •Different Kinds of Data Members
- •Static Data Members
- •Const Data Members
- •Reference Data Members
- •Const Reference Data Members
- •More about Methods
- •Static Methods
- •Const Methods
- •Method Overloading
- •Default Parameters
- •Inline Methods
- •Nested Classes
- •Friends
- •Operator Overloading
- •Implementing Addition
- •Overloading Arithmetic Operators
- •Overloading Comparison Operators
- •Building Types with Operator Overloading
- •Pointers to Methods and Members
- •Building Abstract Classes
- •Using Interface and Implementation Classes
- •Building Classes with Inheritance
- •Extending Classes
- •Overriding Methods
- •Inheritance for Reuse
- •The WeatherPrediction Class
- •Adding Functionality in a Subclass
- •Replacing Functionality in a Subclass
- •Respect Your Parents
- •Parent Constructors
- •Parent Destructors
- •Referring to Parent Data
- •Casting Up and Down
- •Inheritance for Polymorphism
- •Return of the Spreadsheet
- •Designing the Polymorphic Spreadsheet Cell
- •The Spreadsheet Cell Base Class
- •The Individual Subclasses
- •Leveraging Polymorphism
- •Future Considerations
- •Multiple Inheritance
- •Inheriting from Multiple Classes
- •Naming Collisions and Ambiguous Base Classes
- •Interesting and Obscure Inheritance Issues
- •Special Cases in Overriding Methods
- •Copy Constructors and the Equals Operator
- •The Truth about Virtual
- •Runtime Type Facilities
- •Non-Public Inheritance
- •Virtual Base Classes
- •Class Templates
- •Writing a Class Template
- •How the Compiler Processes Templates
- •Distributing Template Code between Files
- •Template Parameters
- •Method Templates
- •Template Class Specialization
- •Subclassing Template Classes
- •Inheritance versus Specialization
- •Function Templates
- •Function Template Specialization
- •Function Template Overloading
- •Friend Function Templates of Class Templates
- •Advanced Templates
- •More about Template Parameters
- •Template Class Partial Specialization
- •Emulating Function Partial Specialization with Overloading
- •Template Recursion
- •References
- •Reference Variables
- •Reference Data Members
- •Reference Parameters
- •Reference Return Values
- •Deciding between References and Pointers
- •Keyword Confusion
- •The const Keyword
- •The static Keyword
- •Order of Initialization of Nonlocal Variables
- •Types and Casts
- •typedefs
- •Casts
- •Scope Resolution
- •Header Files
- •C Utilities
- •Variable-Length Argument Lists
- •Preprocessor Macros
- •How to Picture Memory
- •Allocation and Deallocation
- •Arrays
- •Working with Pointers
- •Array-Pointer Duality
- •Arrays Are Pointers!
- •Not All Pointers Are Arrays!
- •Dynamic Strings
- •C-Style Strings
- •String Literals
- •The C++ string Class
- •Pointer Arithmetic
- •Custom Memory Management
- •Garbage Collection
- •Object Pools
- •Function Pointers
- •Underallocating Strings
- •Memory Leaks
- •Double-Deleting and Invalid Pointers
- •Accessing Out-of-Bounds Memory
- •Using Streams
- •What Is a Stream, Anyway?
- •Stream Sources and Destinations
- •Output with Streams
- •Input with Streams
- •Input and Output with Objects
- •String Streams
- •File Streams
- •Jumping around with seek() and tell()
- •Linking Streams Together
- •Bidirectional I/O
- •Internationalization
- •Wide Characters
- •Non-Western Character Sets
- •Locales and Facets
- •Errors and Exceptions
- •What Are Exceptions, Anyway?
- •Why Exceptions in C++ Are a Good Thing
- •Why Exceptions in C++ Are a Bad Thing
- •Our Recommendation
- •Exception Mechanics
- •Throwing and Catching Exceptions
- •Exception Types
- •Throwing and Catching Multiple Exceptions
- •Uncaught Exceptions
- •Throw Lists
- •Exceptions and Polymorphism
- •The Standard Exception Hierarchy
- •Catching Exceptions in a Class Hierarchy
- •Writing Your Own Exception Classes
- •Stack Unwinding and Cleanup
- •Catch, Cleanup, and Rethrow
- •Use Smart Pointers
- •Common Error-Handling Issues
- •Memory Allocation Errors
- •Errors in Constructors
- •Errors in Destructors
- •Putting It All Together
- •Why Overload Operators?
- •Limitations to Operator Overloading
- •Choices in Operator Overloading
- •Summary of Overloadable Operators
- •Overloading the Arithmetic Operators
- •Overloading Unary Minus and Unary Plus
- •Overloading Increment and Decrement
- •Overloading the Subscripting Operator
- •Providing Read-Only Access with operator[]
- •Non-Integral Array Indices
- •Overloading the Function Call Operator
- •Overloading the Dereferencing Operators
- •Implementing operator*
- •Implementing operator->
- •What in the World Is operator->* ?
- •Writing Conversion Operators
- •Ambiguity Problems with Conversion Operators
- •Conversions for Boolean Expressions
- •How new and delete Really Work
- •Overloading operator new and operator delete
- •Overloading operator new and operator delete with Extra Parameters
- •Two Approaches to Efficiency
- •Two Kinds of Programs
- •Is C++ an Inefficient Language?
- •Language-Level Efficiency
- •Handle Objects Efficiently
- •Use Inline Methods and Functions
- •Design-Level Efficiency
- •Cache as Much as Possible
- •Use Object Pools
- •Use Thread Pools
- •Profiling
- •Profiling Example with gprof
- •Cross-Platform Development
- •Architecture Issues
- •Implementation Issues
- •Platform-Specific Features
- •Cross-Language Development
- •Mixing C and C++
- •Shifting Paradigms
- •Linking with C Code
- •Mixing Java and C++ with JNI
- •Mixing C++ with Perl and Shell Scripts
- •Mixing C++ with Assembly Code
- •Quality Control
- •Whose Responsibility Is Testing?
- •The Life Cycle of a Bug
- •Bug-Tracking Tools
- •Unit Testing
- •Approaches to Unit Testing
- •The Unit Testing Process
- •Unit Testing in Action
- •Higher-Level Testing
- •Integration Tests
- •System Tests
- •Regression Tests
- •Tips for Successful Testing
- •The Fundamental Law of Debugging
- •Bug Taxonomies
- •Avoiding Bugs
- •Planning for Bugs
- •Error Logging
- •Debug Traces
- •Asserts
- •Debugging Techniques
- •Reproducing Bugs
- •Debugging Reproducible Bugs
- •Debugging Nonreproducible Bugs
- •Debugging Memory Problems
- •Debugging Multithreaded Programs
- •Debugging Example: Article Citations
- •Lessons from the ArticleCitations Example
- •Requirements on Elements
- •Exceptions and Error Checking
- •Iterators
- •Sequential Containers
- •Vector
- •The vector<bool> Specialization
- •deque
- •list
- •Container Adapters
- •queue
- •priority_queue
- •stack
- •Associative Containers
- •The pair Utility Class
- •multimap
- •multiset
- •Other Containers
- •Arrays as STL Containers
- •Strings as STL Containers
- •Streams as STL Containers
- •bitset
- •The find() and find_if() Algorithms
- •The accumulate() Algorithms
- •Function Objects
- •Arithmetic Function Objects
- •Comparison Function Objects
- •Logical Function Objects
- •Function Object Adapters
- •Writing Your Own Function Objects
- •Algorithm Details
- •Utility Algorithms
- •Nonmodifying Algorithms
- •Modifying Algorithms
- •Sorting Algorithms
- •Set Algorithms
- •The Voter Registration Audit Problem Statement
- •The auditVoterRolls() Function
- •The getDuplicates() Function
- •The RemoveNames Functor
- •The NameInList Functor
- •Testing the auditVoterRolls() Function
- •Allocators
- •Iterator Adapters
- •Reverse Iterators
- •Stream Iterators
- •Insert Iterators
- •Extending the STL
- •Why Extend the STL?
- •Writing an STL Algorithm
- •Writing an STL Container
- •The Appeal of Distributed Computing
- •Distribution for Scalability
- •Distribution for Reliability
- •Distribution for Centrality
- •Distributed Content
- •Distributed versus Networked
- •Distributed Objects
- •Serialization and Marshalling
- •Remote Procedure Calls
- •CORBA
- •Interface Definition Language
- •Implementing the Class
- •Using the Objects
- •A Crash Course in XML
- •XML as a Distributed Object Technology
- •Generating and Parsing XML in C++
- •XML Validation
- •Building a Distributed Object with XML
- •SOAP (Simple Object Access Protocol)
- •. . . Write a Class
- •. . . Subclass an Existing Class
- •. . . Throw and Catch Exceptions
- •. . . Read from a File
- •. . . Write to a File
- •. . . Write a Template Class
- •There Must Be a Better Way
- •Smart Pointers with Reference Counting
- •Double Dispatch
- •Mix-In Classes
- •Object-Oriented Frameworks
- •Working with Frameworks
- •The Model-View-Controller Paradigm
- •The Singleton Pattern
- •Example: A Logging Mechanism
- •Implementation of a Singleton
- •Using a Singleton
- •Example: A Car Factory Simulation
- •Implementation of a Factory
- •Using a Factory
- •Other Uses of Factories
- •The Proxy Pattern
- •Example: Hiding Network Connectivity Issues
- •Implementation of a Proxy
- •Using a Proxy
- •The Adapter Pattern
- •Example: Adapting an XML Library
- •Implementation of an Adapter
- •Using an Adapter
- •The Decorator Pattern
- •Example: Defining Styles in Web Pages
- •Implementation of a Decorator
- •Using a Decorator
- •The Chain of Responsibility Pattern
- •Example: Event Handling
- •Implementation of a Chain of Responsibility
- •Using a Chain of Responsibility
- •Example: Event Handling
- •Implementation of an Observer
- •Using an Observer
- •Chapter 1: A Crash Course in C++
- •Chapter 3: Designing with Objects
- •Chapter 4: Designing with Libraries and Patterns
- •Chapter 5: Designing for Reuse
- •Chapter 7: Coding with Style
- •Chapters 8 and 9: Classes and Objects
- •Chapter 11: Writing Generic Code with Templates
- •Chapter 14: Demystifying C++ I/O
- •Chapter 15: Handling Errors
- •Chapter 16: Overloading C++ Operators
- •Chapter 17: Writing Efficient C++
- •Chapter 19: Becoming Adept at Testing
- •Chapter 20: Conquering Debugging
- •Chapter 24: Exploring Distributed Objects
- •Chapter 26: Applying Design Patterns
- •Beginning C++
- •General C++
- •I/O Streams
- •The C++ Standard Library
- •C++ Templates
- •Integrating C++ and Other Languages
- •Algorithms and Data Structures
- •Open-Source Software
- •Software-Engineering Methodology
- •Programming Style
- •Computer Architecture
- •Efficiency
- •Testing
- •Debugging
- •Distributed Objects
- •CORBA
- •XML and SOAP
- •Design Patterns
- •Index
Professional C++
Nicholas A. Solter
Scott J. Kleper
Professional C++
Nicholas A. Solter
Scott J. Kleper
Professional C++
Published by
Wiley Publishing, Inc. 10475 Crosspoint Boulevard Indianapolis, IN 46256 www.wiley.com
Copyright © 2005 by Wiley Publishing, Inc. All rights reserved.
Published simultaneously in Canada
Printed in the United States of America
10 9 8 7 6 5 4 3 2 1
1B/QV/QR/QV/IN
No part of this publication may be reproduced, stored in a retrieval system or transmitted in any form or by any means, electronic, mechanical, photocopying, recording, scanning or otherwise, except as permitted under Sections 107 or 108 of the 1976 United States Copyright Act, without either the prior written permission of the Publisher, or authorization through payment of the appropriate per-copy fee to the Copyright Clearance Center, 222 Rosewood Drive, Danvers, MA 01923, (978) 750-8400, fax (978) 646-8600. Requests to the Publisher for permission should
be addressed to the Legal Department, Wiley Publishing, Inc., 10475 Crosspoint Blvd., Indianapolis, IN 46256, (317) 572-3447, fax (317) 572-4355, e-mail: brandreview@wiley.com.
LIMIT OF LIABILITY/DISCLAIMER OF WARRANTY: THE PUBLISHER AND THE AUTHOR MAKE NO REPRESENTATIONS OR WARRANTIES WITH RESPECT TO THE ACCURACY OR COMPLETENESS OF THE CONTENTS OF THIS WORK AND SPECIFICALLY DISCLAIM ALL WARRANTIES, INCLUDING WITHOUT LIMITATION WARRANTIES OF FITNESS FOR A PARTICULAR PURPOSE. NO WARRANTY MAY BE CREATED OR EXTENDED BY SALES OR PROMOTIONAL MATERIALS. THE ADVICE AND STRATEGIES CONTAINED HEREIN MAY NOT BE SUITABLE FOR EVERY SITUATION. THIS WORK IS SOLD WITH THE UNDERSTANDING THAT THE PUBLISHER IS NOT ENGAGED IN RENDERING LEGAL, ACCOUNTING, OR OTHER PROFESSIONAL SERVICES. IF PROFESSIONAL ASSISTANCE IS REQUIRED, THE SERVICES OF A COMPETENT PROFESSIONAL PERSON SHOULD BE SOUGHT. NEITHER THE PUBLISHER NOT THE AUTHOR SHALL BE LIABLE FOR DAMAGES ARISING HEREFROM. THE FACT THAT AN ORGANIZATION OR WEB SITE IS REFERRED TO IN THIS WORK AS A CITATION AND/OR A POTENTIAL SOURCE OF FURTHER INFORMATION DOES NOT MEAN THAT THE AUTHOR OR THE PUBLISHER ENDORSES THE INFORMATION THE ORGANIZATION OR WEB SITE MAY PROVIDE OR RECOMMENDATIONS IT MAY MAKE. FURTHER, READERS SHOULD BE AWARE THAT INTERNET WEBSITES LISTED IN THIS WORK MAY HAVE CHANGED OR DISAPPEARED BETWEEN WHEN THIS WORK WAS WRITTEN AND WHEN IT IS READ.
For general information on our other products and services please contact our Customer Care Department within the United States at (800) 762-2974, outside the United States at (317) 572-3993 or fax (317) 572-4002.
Trademarks: Wiley, the Wiley Publishing logo, Wrox, the Wrox logo, Programmer to Programmer and related trade dress are trademarks or registered trademarks of John Wiley & Sons, Inc. and/or its affiliates. All other trademarks are the property of their respective owners. Wiley Publishing, Inc., is not associated with any product or vendor mentioned in this book.
Wiley also publishes its books in a variety of electronic formats. Some content that appears in print may not be available in electronic books.
Solter, Nicholas, 1977-
Professional C++ / Nicholas Solter, Scott Kleper. p. cm.
Includes index.
ISBN 0-7645-7484-1 (paper/website)
1. C++ (Computer program language) I. Kleper, Scott, 1977II. Title. QA76.73.C153S665 2005
005.13'3--dc22
2004027959
Dedications
To Sonja, for her unconditional love and support, and to my son Kai, whose frequent interruptions reminded me what’s important in life.
—Nicholas A. Solter
To Marni, whose unpredictable cuteness brightens every day.
—Scott J. Kleper
Acknowledgments
We owe a debt of gratitude to the many people who have made this book possible. We’d like to thank David Fugate of Waterside Productions for all of his advice and guidance, and Robert Elliot at Wiley for giving two unknown authors the opportunity to tell the C++ story in a new way. This book would not have turned out nearly as well as it did without the assistance of our development editor, Adaobi Obi Tulton. Thanks also to Kathryn Malm Bourgoine for her editorial assistance. The photo on the cover, which artfully minimized our nerdiness, was taken by Adam Tow.
We also want to thank all of the coworkers and teachers who have encouraged us to code the right way over the years. In particular, thanks to Mike Hanson, Maggie Johnson, Adam Nash, Nick Parlante, Bob Plummer, Eric Roberts, Mehran Sahami, Bill Walker, Dan Walkowski, Patrick Young, and Julie Zelenski. Our eternal thanks to Jerry Cain, who not only taught us C++ originally, but also served as technical editor, religiously analyzing the code in this book as though it were one of our final exams.
Thanks also to the following people, who reviewed one or more chapters: Rob Baesman, Aaron Bradley, Elaine Cheung, Marni Kleper, Toli Kuznets, Akshay Rangnekar, Eltefaat Shokri, Aletha Solter, Ken Solter, and Sonja Solter. Any remaining errors are, of course, our own. We’d like to thank our families for their patience and support.
Finally, we’d like to thank you, our readers, for trying out our approach to professional C++ development.
Author Bios
Nicholas A. Solter studied computer science at Stanford University, where he earned bachelor of science and master of science degrees, with a concentration in systems. While a student, he worked as a teaching assistant for several classes ranging from introductory computer science for nonmajors to an upperdivision course on group projects and software engineering.
Now a software engineer at Sun Microsystems, Nick programs primarily in C and C++ in his work on high-availability software. His previous work experience includes several stints in the computer game industry. At Digital Media International, he was the lead programmer on the multimedia educational game, The Land Before Time Math Adventure. During an internship at Electronic Arts, he helped develop the Course Architect 2000 golf course–editing tool for the Tiger Woods PGA Tour 2000 game.
In addition to his industry experience, Nick taught C++ for one year as an adjunct professor of computer science at Fullerton College. When not working, Nick enjoys reading, playing basketball, taking care of his son Kai, and spending time with his family.
Scott J. Kleper began his programming career in elementary school, writing adventure games in BASIC for the Tandy TRS-80. As the resident Mac geek at his high school, Scott moved to higher-level languages and released several award-winning shareware applications.
Scott attended Stanford University, where he obtained bachelor of science and master of science degrees in computer science, with a concentration in human-computer interaction. While in college, Scott served as a teaching assistant for classes involving introductory programming, object-oriented design, data structures, GUI frameworks, group projects, and Internet programming.
Since graduating, Scott has served as a lead engineer on the founding teams of several companies and is currently a senior software engineer at Reactivity, Inc. Outside of work, Scott is a compulsive online shopper, an avid reader, and an awful guitarist.
Credits |
|
Vice President and Executive Group Publisher |
Senior Development Editor |
Richard Swadley |
Adaobi Obi Tulton |
Vice President and Publisher |
Production Editor |
Joseph B. Wikert |
Felicia Robinson |
Executive Editor |
Media Development Specialist |
Robert Elliott |
Richard Graves |
Editorial Manager |
Technical Editor |
Kathryn Malm Bourgoine |
Jerry Cain |
Senior Production Editor |
Text Design & Composition |
Geraldine Fahey |
Wiley Composition Services |
Cover Photographer
Adam Tow
Contents
Introduction |
xxi |
Who This Book Is For |
xxi |
What This Book Covers |
xxi |
How This Book Is Structured |
xxii |
What You Need to Use This Book |
xxiii |
Conventions |
xxiii |
Source Code |
xxiv |
Errata |
xxiv |
p2p.wrox.com |
xxiv |
Part I: Introduction to Professional C++ |
|
Chapter 1: A Crash Course in C++ |
1 |
The Basics of C++ |
1 |
The Obligatory Hello, World |
2 |
Namespaces |
4 |
Variables |
6 |
Operators |
8 |
Types |
10 |
Conditionals |
12 |
Loops |
14 |
Arrays |
15 |
Functions |
16 |
Those Are the Basics |
17 |
Diving Deeper into C++ |
18 |
Pointers and Dynamic Memory |
18 |
Strings in C++ |
21 |
References |
23 |
Exceptions |
23 |
The Many Uses of const |
25 |
C++ as an Object-Oriented Language |
26 |
Declaring a Class |
26 |
Your First Useful C++ Program |
29 |
An Employee Records System |
29 |
The Employee Class |
29 |
Contents
The Database Class |
34 |
The User Interface |
38 |
Evaluating the Program |
41 |
Summary |
41 |
Chapter 2: Designing Professional C++ Programs |
43 |
What Is Programming Design? |
44 |
The Importance of Programming Design |
44 |
What’s Different about C++ Design? |
46 |
Two Rules for C++ Design |
47 |
Abstraction |
47 |
Reuse |
49 |
Designing a Chess Program |
50 |
Requirements |
51 |
Design Steps |
51 |
Summary |
56 |
Chapter 3: Designing with Objects |
57 |
An Object-Oriented View of the World |
57 |
Am I Thinking Procedurally? |
57 |
The Object-Oriented Philosophy |
58 |
Living in a World of Objects |
61 |
Object Relationships |
63 |
Abstraction |
73 |
Summary |
76 |
Chapter 4: Designing with Libraries and Patterns |
77 |
Reusing Code |
77 |
A Note on Terminology |
78 |
Deciding Whether or Not to Reuse Code |
78 |
Strategies for Reusing Code |
81 |
Bundling Third-Party Applications |
85 |
Open-Source Libraries |
86 |
The C++ Standard Library |
87 |
Designing with Patterns and Techniques |
101 |
Design Techniques |
101 |
Design Patterns |
102 |
Summary |
103 |
vi
|
Contents |
Chapter 5: Designing for Reuse |
105 |
The Reuse Philosophy |
106 |
How to Design Reusable Code |
106 |
Use Abstraction |
107 |
Structure Your Code for Optimal Reuse |
108 |
Design Usable Interfaces |
112 |
Reconciling Generality and Ease of Use |
117 |
Summary |
118 |
Chapter 6: Maximizing Software-Engineering Methods |
119 |
The Need for Process |
119 |
Software Life-Cycle Models |
120 |
The Stagewise and Waterfall Models |
121 |
The Spiral Method |
123 |
The Rational Unified Process |
126 |
Software-Engineering Methodologies |
127 |
Extreme Programming (XP) |
128 |
Software Triage |
132 |
Building Your Own Process and Methodology |
132 |
Be Open to New Ideas |
132 |
Bring New Ideas to the Table |
132 |
Recognize What Works and What Doesn’t Work |
133 |
Don’t Be a Renegade |
133 |
Summary |
133 |
Part II: C++ Coding the Professional Way |
|
Chapter 7: Coding with Style |
135 |
The Importance of Looking Good |
135 |
Thinking Ahead |
135 |
Keeping It Clear |
136 |
Elements of Good Style |
136 |
Documenting Your Code |
136 |
Reasons to Write Comments |
136 |
Commenting Styles |
140 |
Comments in This Book |
145 |
vii
Contents
Decomposition |
145 |
Decomposition through Refactoring |
147 |
Decomposition by Design |
147 |
Decomposition in This Book |
148 |
Naming |
148 |
Choosing a Good Name |
148 |
Naming Conventions |
148 |
Using Language Features with Style |
151 |
Use Constants |
151 |
Take Advantage of const Variables |
151 |
Use References Instead of Pointers |
151 |
Use Custom Exceptions |
152 |
Formatting |
152 |
The Curly Brace Alignment Debate |
153 |
Coming to Blows over Spaces and Parentheses |
154 |
Spaces and Tabs |
154 |
Stylistic Challenges |
155 |
Summary |
155 |
Chapter 8: Gaining Proficiency with Classes and Objects |
157 |
Introducing the Spreadsheet Example |
157 |
Writing Classes |
158 |
Class Definitions |
158 |
Defining Methods |
161 |
Using Objects |
164 |
Object Life Cycles |
165 |
Object Creation |
165 |
Object Destruction |
176 |
Assigning to Objects |
177 |
Distinguishing Copying from Assignment |
180 |
Summary |
182 |
Chapter 9: Mastering Classes and Objects |
183 |
Dynamic Memory Allocation in Objects |
183 |
The Spreadsheet Class |
184 |
Freeing Memory with Destructors |
186 |
Handling Copying and Assignment |
186 |
Different Kinds of Data Members |
194 |
Static Data Members |
195 |
Const Data Members |
196 |
Reference Data Members |
198 |
Const Reference Data Members |
199 |
viii
|
Contents |
More about Methods |
199 |
Static Methods |
199 |
Const Methods |
200 |
Method Overloading |
202 |
Default Parameters |
203 |
Inline Methods |
204 |
Nested Classes |
206 |
Friends |
208 |
Operator Overloading |
209 |
Implementing Addition |
209 |
Overloading Arithmetic Operators |
212 |
Overloading Comparison Operators |
215 |
Building Types with Operator Overloading |
216 |
Pointers to Methods and Members |
217 |
Building Abstract Classes |
218 |
Using Interface and Implementation Classes |
218 |
Summary |
221 |
Chapter 10: Discovering Inheritance Techniques |
223 |
Building Classes with Inheritance |
224 |
Extending Classes |
224 |
Overriding Methods |
227 |
Inheritance for Reuse |
230 |
The WeatherPrediction Class |
230 |
Adding Functionality in a Subclass |
231 |
Replacing Functionality in a Subclass |
233 |
Respect Your Parents |
234 |
Parent Constructors |
234 |
Parent Destructors |
235 |
Referring to Parent Data |
237 |
Casting Up and Down |
239 |
Inheritance for Polymorphism |
240 |
Return of the Spreadsheet |
240 |
Designing the Polymorphic Spreadsheet Cell |
241 |
The Spreadsheet Cell Base Class |
242 |
The Individual Subclasses |
243 |
Leveraging Polymorphism |
245 |
Future Considerations |
246 |
Multiple Inheritance |
248 |
Inheriting from Multiple Classes |
248 |
Naming Collisions and Ambiguous Base Classes |
249 |
ix
Contents
Interesting and Obscure Inheritance Issues |
253 |
Changing the Overridden Method’s Characteristics |
253 |
Special Cases in Overriding Methods |
256 |
Copy Constructors and the Equals Operator |
263 |
The Truth about Virtual |
264 |
Runtime Type Facilities |
267 |
Non-Public Inheritance |
269 |
Virtual Base Classes |
269 |
Summary |
270 |
Chapter 11: Writing Generic Code with Templates |
271 |
Overview of Templates |
272 |
Class Templates |
273 |
Writing a Class Template |
273 |
How the Compiler Processes Templates |
280 |
Distributing Template Code between Files |
281 |
Template Parameters |
282 |
Method Templates |
285 |
Template Class Specialization |
290 |
Subclassing Template Classes |
293 |
Inheritance versus Specialization |
295 |
Function Templates |
295 |
Function Template Specialization |
296 |
Function Template Overloading |
297 |
Friend Function Templates of Class Templates |
298 |
Advanced Templates |
299 |
More about Template Parameters |
299 |
Template Class Partial Specialization |
307 |
Emulating Function Partial Specialization with Overloading |
313 |
Template Recursion |
314 |
Summary |
322 |
Chapter 12: Understanding C++ Quirks and Oddities |
323 |
References |
323 |
Reference Variables |
324 |
Reference Data Members |
326 |
Reference Parameters |
326 |
Reference Return Values |
327 |
Deciding between References and Pointers |
327 |
x
|
Contents |
Keyword Confusion |
330 |
The const Keyword |
330 |
The static Keyword |
333 |
Order of Initialization of Nonlocal Variables |
336 |
Types and Casts |
337 |
typedefs |
337 |
Casts |
338 |
Scope Resolution |
343 |
Header Files |
343 |
C Utilities |
345 |
Variable-Length Argument Lists |
345 |
Preprocessor Macros |
347 |
Summary |
348 |
Part III: Mastering Advanced Features of C++ |
|
Chapter 13: Effective Memory Management |
349 |
Working with Dynamic Memory |
349 |
How to Picture Memory |
350 |
Allocation and Deallocation |
351 |
Arrays |
353 |
Working with Pointers |
360 |
Array-Pointer Duality |
362 |
Arrays Are Pointers! |
363 |
Not All Pointers Are Arrays! |
364 |
Dynamic Strings |
365 |
C-Style Strings |
365 |
String Literals |
366 |
The C++ string Class |
367 |
Low-Level Memory Operations |
369 |
Pointer Arithmetic |
369 |
Custom Memory Management |
370 |
Garbage Collection |
370 |
Object Pools |
371 |
Function Pointers |
372 |
Common Memory Pitfalls |
374 |
Underallocating Strings |
374 |
Memory Leaks |
374 |
Double-Deleting and Invalid Pointers |
377 |
Accessing Out-of-Bounds Memory |
378 |
Summary |
378 |
xi
Contents
Chapter 14: Demystifying C++ I/O |
379 |
Using Streams |
379 |
What Is a Stream, Anyway? |
380 |
Stream Sources and Destinations |
380 |
Output with Streams |
380 |
Input with Streams |
384 |
Input and Output with Objects |
389 |
String Streams |
390 |
File Streams |
392 |
Jumping around with seek() and tell() |
392 |
Linking Streams Together |
395 |
Bidirectional I/O |
396 |
Internationalization |
397 |
Wide Characters |
397 |
Non-Western Character Sets |
398 |
Locales and Facets |
398 |
Summary |
400 |
Chapter 15: Handling Errors |
401 |
Errors and Exceptions |
402 |
What Are Exceptions, Anyway? |
402 |
Why Exceptions in C++ Are a Good Thing |
403 |
Why Exceptions in C++ Are a Bad Thing |
404 |
Our Recommendation |
404 |
Exception Mechanics |
404 |
Throwing and Catching Exceptions |
405 |
Exception Types |
406 |
Throwing and Catching Multiple Exceptions |
408 |
Uncaught Exceptions |
411 |
Throw Lists |
412 |
Exceptions and Polymorphism |
416 |
The Standard Exception Hierarchy |
416 |
Catching Exceptions in a Class Hierarchy |
417 |
Writing Your Own Exception Classes |
419 |
Stack Unwinding and Cleanup |
422 |
Catch, Cleanup, and Rethrow |
423 |
Use Smart Pointers |
424 |
xii
|
Contents |
Common Error-Handling Issues |
424 |
Memory Allocation Errors |
424 |
Errors in Constructors |
427 |
Errors in Destructors |
428 |
Putting It All Together |
428 |
Summary |
430 |
Part IV: Ensuring Bug-Free Code |
|
Chapter 16: Overloading C++ Operators |
431 |
Overview of Operator Overloading |
432 |
Why Overload Operators? |
432 |
Limitations to Operator Overloading |
432 |
Choices in Operator Overloading |
433 |
Operators You Shouldn’t Overload |
435 |
Summary of Overloadable Operators |
435 |
Overloading the Arithmetic Operators |
438 |
Overloading Unary Minus and Unary Plus |
438 |
Overloading Increment and Decrement |
439 |
Overloading the Bitwise and Binary Logical Operators |
441 |
Overloading the Insertion and Extraction Operators |
441 |
Overloading the Subscripting Operator |
443 |
Providing Read-Only Access with operator[] |
446 |
Non-Integral Array Indices |
447 |
Overloading the Function Call Operator |
448 |
Overloading the Dereferencing Operators |
449 |
Implementing operator* |
451 |
Implementing operator-> |
452 |
What in the World Is operator->* ? |
452 |
Writing Conversion Operators |
453 |
Ambiguity Problems with Conversion Operators |
454 |
Conversions for Boolean Expressions |
455 |
Overloading the Memory Allocation and Deallocation Operators |
457 |
How new and delete Really Work |
457 |
Overloading operator new and operator delete |
459 |
Overloading operator new and operator delete with Extra Parameters |
461 |
Summary |
463 |
xiii
Contents
Chapter 17: Writing Efficient C++ |
465 |
Overview of Performance and Efficiency |
465 |
Two Approaches to Efficiency |
466 |
Two Kinds of Programs |
466 |
Is C++ an Inefficient Language? |
466 |
Language-Level Efficiency |
467 |
Handle Objects Efficiently |
467 |
Don’t Overuse Costly Language Features |
471 |
Use Inline Methods and Functions |
472 |
Design-Level Efficiency |
472 |
Cache as Much as Possible |
472 |
Use Object Pools |
473 |
Use Thread Pools |
479 |
Profiling |
479 |
Profiling Example with gprof |
479 |
Summary |
488 |
Chapter 18: Developing Cross-Platform and Cross-Language Applications |
489 |
Cross-Platform Development |
489 |
Architecture Issues |
490 |
Implementation Issues |
492 |
Platform-Specific Features |
493 |
Cross-Language Development |
494 |
Mixing C and C++ |
494 |
Shifting Paradigms |
495 |
Linking with C Code |
498 |
Mixing Java and C++ with JNI |
499 |
Mixing C++ with Perl and Shell Scripts |
501 |
Mixing C++ with Assembly Code |
504 |
Summary |
505 |
Chapter 19: Becoming Adept at Testing |
507 |
Quality Control |
507 |
Whose Responsibility Is Testing? |
508 |
The Life Cycle of a Bug |
508 |
Bug-Tracking Tools |
509 |
Unit Testing |
510 |
Approaches to Unit Testing |
511 |
The Unit Testing Process |
512 |
Unit Testing in Action |
515 |
xiv
|
Contents |
Higher-Level Testing |
523 |
Integration Tests |
523 |
System Tests |
525 |
Regression Tests |
525 |
Tips for Successful Testing |
526 |
Summary |
526 |
Chapter 20: Conquering Debugging |
527 |
The Fundamental Law of Debugging |
527 |
Bug Taxonomies |
528 |
Avoiding Bugs |
528 |
Planning for Bugs |
528 |
Error Logging |
528 |
Debug Traces |
530 |
Asserts |
540 |
Debugging Techniques |
541 |
Reproducing Bugs |
541 |
Debugging Reproducible Bugs |
542 |
Debugging Nonreproducible Bugs |
543 |
Debugging Memory Problems |
544 |
Debugging Multithreaded Programs |
547 |
Debugging Example: Article Citations |
548 |
Lessons from the ArticleCitations Example |
559 |
Summary |
559 |
Chapter 21: Delving into the STL: Containers and Iterators |
561 |
Containers Overview |
562 |
Requirements on Elements |
562 |
Exceptions and Error Checking |
563 |
Iterators |
564 |
Sequential Containers |
565 |
Vector |
566 |
The vector<bool> Specialization |
583 |
deque |
584 |
list |
584 |
Container Adapters |
588 |
queue |
588 |
priority_queue |
591 |
stack |
594 |
xv
Contents
Associative Containers |
595 |
The pair Utility Class |
595 |
map |
596 |
multimap |
604 |
set |
608 |
multiset |
610 |
Other Containers |
611 |
Arrays as STL Containers |
611 |
Strings as STL Containers |
612 |
Streams as STL Containers |
613 |
bitset |
613 |
Summary |
618 |
Part V: Using Libraries and Patterns |
|
Chapter 22: Mastering STL Algorithms and Function Objects |
619 |
Overview of Algorithms |
620 |
The find() and find_if() Algorithms |
620 |
The accumulate() Algorithms |
623 |
Function Objects |
624 |
Arithmetic Function Objects |
624 |
Comparison Function Objects |
625 |
Logical Function Objects |
627 |
Function Object Adapters |
627 |
Writing Your Own Function Objects |
630 |
Algorithm Details |
631 |
Utility Algorithms |
632 |
Nonmodifying Algorithms |
633 |
Modifying Algorithms |
639 |
Sorting Algorithms |
643 |
Set Algorithms |
646 |
Algorithms and Function Objects Example: Auditing Voter Registrations |
648 |
The Voter Registration Audit Problem Statement |
648 |
The auditVoterRolls() Function |
648 |
The getDuplicates() Function |
649 |
The RemoveNames Functor |
650 |
The NameInList Functor |
651 |
Testing the auditVoterRolls() Function |
652 |
Summary |
653 |
xvi
|
Contents |
Chapter 23: Customizing and Extending the STL |
655 |
Allocators |
656 |
Iterator Adapters |
656 |
Reverse Iterators |
656 |
Stream Iterators |
657 |
Insert Iterators |
658 |
Extending the STL |
660 |
Why Extend the STL? |
660 |
Writing an STL Algorithm |
660 |
Writing an STL Container |
662 |
Summary |
691 |
Chapter 24: Exploring Distributed Objects |
693 |
The Appeal of Distributed Computing |
693 |
Distribution for Scalability |
693 |
Distribution for Reliability |
694 |
Distribution for Centrality |
694 |
Distributed Content |
695 |
Distributed versus Networked |
695 |
Distributed Objects |
696 |
Serialization and Marshalling |
696 |
Remote Procedure Calls |
700 |
CORBA |
702 |
Interface Definition Language |
702 |
Implementing the Class |
704 |
Using the Objects |
706 |
XML |
709 |
A Crash Course in XML |
709 |
XML as a Distributed Object Technology |
712 |
Generating and Parsing XML in C++ |
712 |
XML Validation |
721 |
Building a Distributed Object with XML |
723 |
SOAP (Simple Object Access Protocol) |
726 |
Summary |
728 |
Chapter 25: Incorporating Techniques and Frameworks |
729 |
“I Can Never Remember How to . . .” |
730 |
. . . Write a Class |
730 |
. . . Subclass an Existing Class |
731 |
xvii
Contents
. . . Throw and Catch Exceptions |
732 |
. . . Read from a File |
733 |
. . . Write to a File |
734 |
. . . Write a Template Class |
734 |
There Must Be a Better Way |
736 |
Smart Pointers with Reference Counting |
736 |
Double Dispatch |
741 |
Mix-In Classes |
747 |
Object-Oriented Frameworks |
750 |
Working with Frameworks |
750 |
The Model-View-Controller Paradigm |
750 |
Summary |
752 |
Chapter 26: Applying Design Patterns |
753 |
The Singleton Pattern |
754 |
Example: A Logging Mechanism |
754 |
Implementation of a Singleton |
754 |
Using a Singleton |
759 |
The Factory Pattern |
760 |
Example: A Car Factory Simulation |
760 |
Implementation of a Factory |
762 |
Using a Factory |
764 |
Other Uses of Factories |
766 |
The Proxy Pattern |
766 |
Example: Hiding Network Connectivity Issues |
766 |
Implementation of a Proxy |
767 |
Using a Proxy |
767 |
The Adapter Pattern |
768 |
Example: Adapting an XML Library |
768 |
Implementation of an Adapter |
768 |
Using an Adapter |
772 |
The Decorator Pattern |
773 |
Example: Defining Styles in Web Pages |
773 |
Implementation of a Decorator |
774 |
Using a Decorator |
775 |
The Chain of Responsibility Pattern |
776 |
Example: Event Handling |
776 |
Implementation of a Chain of Responsibility |
777 |
Using a Chain of Responsibility |
778 |
xviii
|
Contents |
The Observer Pattern |
778 |
Example: Event Handling |
778 |
Implementation of an Observer |
778 |
Using an Observer |
780 |
Summary |
781 |
Appendix A: C++ Interviews |
783 |
Chapter 1: A Crash Course in C++ |
783 |
Chapter 2: Designing Professional C++ Programs |
784 |
Chapter 3: Designing with Objects |
785 |
Chapter 4: Designing with Libraries and Patterns |
786 |
Chapter 5: Designing for Reuse |
787 |
Chapter 6: Maximizing Software Engineering Methods |
787 |
Chapter 7: Coding with Style |
788 |
Chapters 8 and 9: Classes and Objects |
789 |
Chapter 10: Discovering Inheritance Techniques |
792 |
Chapter 11: Writing Generic Code with Templates |
793 |
Chapter 12: Understanding C++ Quirks and Oddities |
793 |
Chapter 13: Effective Memory Management |
794 |
Chapter 14: Demystifying C++ I/O |
795 |
Chapter 15: Handling Errors |
796 |
Chapter 16: Overloading C++ Operators |
796 |
Chapter 17: Writing Efficient C++ |
797 |
Chapter 18: Developing Cross-Platform and Cross-Language Applications |
798 |
Chapter 19: Becoming Adept at Testing |
798 |
Chapter 20: Conquering Debugging |
799 |
Chapters 21, 22, and 23: The Standard Template Library |
799 |
Chapter 24: Exploring Distributed Objects |
800 |
Chapter 25: Incorporating Techniques and Frameworks |
801 |
Chapter 26: Applying Design Patterns |
801 |
Appendix B: Annotated Bibliography |
803 |
C++ |
803 |
Beginning C++ |
803 |
General C++ |
804 |
I/O Streams |
805 |
The C++ Standard Library |
805 |
C++ Templates |
806 |
xix
Contents
C |
806 |
Integrating C++ and Other Languages |
806 |
Algorithms and Data Structures |
807 |
Open-Source Software |
807 |
Software-Engineering Methodology |
807 |
Programming Style |
808 |
Computer Architecture |
809 |
Efficiency |
809 |
Testing |
809 |
Debugging |
809 |
Distributed Objects |
810 |
CORBA |
810 |
XML and SOAP |
810 |
Design Patterns |
811 |
Index |
813 |
xx