283 43 3MB
English Pages 626 Year 2003
C++ from the Ground Up Third Edition
About the Author Herbert Schildt is the world’s leading programming author. He is an authority on the C, C++, Java, and C# languages, and is a master Windows programmer. His programming books have sold more than 3 million copies worldwide and have been translated into all major foreign languages. He is the author of numerous bestsellers, including C++: The Complete Reference, C#: The Complete Reference, Java 2: The Complete Reference, C: The Complete Reference, C++ From the Ground Up, C++: A Beginner’s Guide, C#: A Beginner’s Guide, and Java 2: A Beginner’s Guide. Schildt holds a master’s degree in computer science from the University of Illinois. He can be reached at his consulting office at (217) 586-4683.
C++ from the Ground Up Third Edition
Herbert Schildt
McGraw-Hill/Osborne New York Chicago San Francisco Lisbon London Madrid Mexico City Milan New Delhi San Juan Seoul Singapore Sydney Toronto
McGraw-Hill/Osborne 2600 Tenth Street Berkeley, California 94710 U.S.A. To arrange bulk purchase discounts for sales promotions, premiums, or fund-raisers, please contact McGraw-Hill/Osborne at the above address. For information on translations or book distributors outside the U.S.A., please see the International Contact Information page immediately following the index of this book. C++ from the Ground Up, Third Edition Copyright © 2003 by The McGraw-Hill Companies. All rights reserved. Printed in the United States of America. Except as permitted under the Copyright Act of 1976, no part of this publication may be reproduced or distributed in any form or by any means, or stored in a database or retrieval system, without the prior written permission of publisher, with the exception that the program listings may be entered, stored, and executed in a computer system, but they may not be reproduced for publication. 1234567890 DOC DOC 019876543 ISBN 0-07-222897-0 Publisher Brandon A. Nordin
Indexer Sheryl Schildt
Vice President & Associate Publisher Scott Rogers
Computer Designers Tabitha M. Cagan, Tara A. Davis, John Patrus, Lucie Ericksen
Acquisitions Editor Lisa McClain
Illustrators Michael Mueller, Lyssa Wald, Melinda Lytle
Project Editors Jenn Tust, Elizabeth Seymour Proofreader Marian M. Selig
Cover Series Design John Nedwidek, emdesign Cover Illustration Lance Ravella
This book was composed with Corel VENTURA™ Publisher.
Information has been obtained by McGraw-Hill/Osborne from sources believed to be reliable. However, because of the possibility of human or mechanical error by our sources, McGraw-Hill/Osborne, or others, McGraw-Hill/Osborne does not guarantee the accuracy, adequacy, or completeness of any information and is not responsible for any errors or omissions or the results obtained from the use of such information.
Contents
Preface
1
2
.....................................................
xvii
The Story of C++ . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
1
The Origins of C++ . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . The Creation of C . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Understanding the Need for C++ . . . . . . . . . . . . . . . . . . C++ Is Born . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . The Evolution of C++ . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . What Is Object-Oriented Programming? . . . . . . . . . . . . . . . . . . . . . Encapsulation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Polymorphism . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Inheritance . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . C++ Implements OOP . . . . . . . . . . . . . . . . . . . . . . . . . . . How C++ Relates to Java and C# . . . . . . . . . . . . . . . . . . .
2 2 4 5 6 6 7 7 8 8 8
An Overview of C++ . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
11
Your First C++ Program . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Entering the Program . . . . . . . . . . . . . . . . . . . . . . . . . . . . Compiling the Program . . . . . . . . . . . . . . . . . . . . . . . . . . Run the Program . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . A Line-by-Line Explanation . . . . . . . . . . . . . . . . . . . . . . .
12 12 13 14 14
v
vi
3
C++ from the Ground Up
Handling Syntax Errors . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . A Second Simple Program . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . A More Practical Example . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . A New Data Type . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . A Quick Review . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Functions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . A Program with Two Functions . . . . . . . . . . . . . . . . . . . . Function Arguments . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Functions Returning Values . . . . . . . . . . . . . . . . . . . . . . . The main( ) Function . . . . . . . . . . . . . . . . . . . . . . . . . . . . The General Form of C++ Functions . . . . . . . . . . . . . . . . Some Output Options . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Two Simple Commands . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . The if Statement . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . The for Loop . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Blocks of Code . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Semicolons and Positioning . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Indentation Practices . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . C++ Keywords . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Identifiers in C++ . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . The Standard C++ Library . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
16 17 18 19 20 20 21 22 24 25 26 26 27 27 28 29 30 31 31 32 32
The Basic Data Types . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
33
Declaration of Variables . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Local Variables . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Formal Parameters . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Global Variables . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Some Type Modifiers . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Literals . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Hexadecimal and Octal Literals . . . . . . . . . . . . . . . . . . . . String Literals . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Character Escape Sequences . . . . . . . . . . . . . . . . . . . . . . Variable Initializations . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Operators . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Arithmetic Operators . . . . . . . . . . . . . . . . . . . . . . . . . . . . Increment and Decrement . . . . . . . . . . . . . . . . . . . . . . . . How C++ Got Its Name . . . . . . . . . . . . . . . . . . . . . . . . . . Relational and Logical Operators . . . . . . . . . . . . . . . . . . . Expressions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Type Conversion in Expressions . . . . . . . . . . . . . . . . . . . Converting to and from bool . . . . . . . . . . . . . . . . . . . . . Casts . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Spacing and Parentheses . . . . . . . . . . . . . . . . . . . . . . . . .
35 35 36 37 38 41 43 43 44 45 46 46 48 49 50 53 53 53 54 55
vii
Contents
4
5
6
Program Control Statements . . . . . . . . . . . . . . . . . . . . . . . .
57
The if Statement . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . The Conditional Expression . . . . . . . . . . . . . . . . . . . . . . Nested ifs . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . The if-else-if Ladder . . . . . . . . . . . . . . . . . . . . . . . . . . . . . The for Loop . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Some Variations on the for Loop . . . . . . . . . . . . . . . . . . . Missing Pieces . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . The Infinite Loop . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Time Delay Loops . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . The switch Statement . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Nested switch Statements . . . . . . . . . . . . . . . . . . . . . . . . The while Loop . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . The do-while Loop . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Using continue . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Using break to Exit Loops . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Nested Loops . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Using the goto Statement . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Putting Together the Pieces . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
58 59 60 61 62 64 66 66 67 67 71 71 73 74 75 76 77 78
Arrays and Strings . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
81
One-Dimensional Arrays . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . No Bounds Checking . . . . . . . . . . . . . . . . . . . . . . . . . . . . Sorting an Array . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Strings . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Reading a String from the Keyboard . . . . . . . . . . . . . . . . Some String Library Functions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . strcpy . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . strcat . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . strcmp . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . strlen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Using the Null Terminator . . . . . . . . . . . . . . . . . . . . . . . Two-Dimensional Arrays . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Multidimensional Arrays . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Array Initialization . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Unsized Array Initializations . . . . . . . . . . . . . . . . . . . . . . Arrays of Strings . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . An Example Using String Arrays . . . . . . . . . . . . . . . . . . .
82 84 85 86 87 89 89 89 90 91 93 94 96 96 100 101 102
Pointers . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
105
What Are Pointers? . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . The Pointer Operators . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . The Base Type Is Important . . . . . . . . . . . . . . . . . . . . . . . Assigning Values Through a Pointer . . . . . . . . . . . . . . . .
106 107 108 110
viii
7
8
C++ from the Ground Up
Pointer Expressions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Pointer Arithmetic . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Pointer Comparisons . . . . . . . . . . . . . . . . . . . . . . . . . . . . Pointers and Arrays . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Indexing a Pointer . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Are Pointers and Arrays Interchangeable? . . . . . . . . . . . . Pointers and String Literals . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . A Comparison Example . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Arrays of Pointers . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . The Null Pointer Convention . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Multiple Indirection . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Pointers and 16-bit Environments . . . . . . . . . . . . . . . . . . Problems with Pointers . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Uninitialized Pointers . . . . . . . . . . . . . . . . . . . . . . . . . . . Invalid Pointer Comparisons . . . . . . . . . . . . . . . . . . . . . . Forgetting to Reset a Pointer . . . . . . . . . . . . . . . . . . . . . .
110 111 112 112 115 116 117 117 118 121 122 122 124 124 124 125
Functions, Part One: The Fundamentals . . . . . . . . . . . . . . . .
127
Scope Rules of Functions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Local Variables . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Formal Parameters . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Global Variables . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Passing Pointers and Arrays . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Calling Functions with Pointers . . . . . . . . . . . . . . . . . . . Calling Functions with Arrays . . . . . . . . . . . . . . . . . . . . . Passing Strings . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . argc and argv: Arguments to main( ) . . . . . . . . . . . . . . . . . . . . . . . . Passing Numeric Command Line Arguments . . . . . . . . . Converting Numeric Strings to Numbers . . . . . . . . . . . . The return Statement . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Returning from a Function . . . . . . . . . . . . . . . . . . . . . . . Returning Values . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . void Functions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Functions That Return Pointers . . . . . . . . . . . . . . . . . . . . Function Prototypes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Headers: A Closer Look . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Old-Style versus Modern Function Parameter Declarations . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Recursion . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
128 128 134 134 136 136 137 140 141 144 145 145 146 147 149 149 151 152 153 153
Functions, Part Two: References, Overloading, and Default Arguments . . . . . . . . . . . . . . . . . . . . . . . . . . .
157
Two Approaches to Argument Passing . . . . . . . . . . . . . . . . . . . . . . . How C++ Passes Arguments . . . . . . . . . . . . . . . . . . . . . . . Using a Pointer to Create a Call-by-Reference . . . . . . . . .
158 158 159
ix
Contents
9
10
Reference Parameters . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Declaring Reference Parameters . . . . . . . . . . . . . . . . . . . . Returning References . . . . . . . . . . . . . . . . . . . . . . . . . . . . Creating a Bounded Array . . . . . . . . . . . . . . . . . . . . . . . . Independent References . . . . . . . . . . . . . . . . . . . . . . . . . . A Few Restrictions When Using References . . . . . . . . . . . Function Overloading . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . The overload Anachronism . . . . . . . . . . . . . . . . . . . . . . . Default Function Arguments . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Default Arguments versus Overloading . . . . . . . . . . . . . . Using Default Arguments Correctly . . . . . . . . . . . . . . . . Function Overloading and Ambiguity . . . . . . . . . . . . . . . . . . . . . . .
160 163 164 167 168 169 170 173 173 175 177 177
More Data Types and Operators . . . . . . . . . . . . . . . . . . . . . .
181
The const and volatile Qualifiers . . . . . . . . . . . . . . . . . . . . . . . . . . . const . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . volatile . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Storage Class Specifiers . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . auto . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . extern . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . static Variables . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Register Variables . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . The Origins of the register Modifier . . . . . . . . . . . . . . . . Enumerations . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . typedef . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . More Operators . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Bitwise Operators . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . AND, OR, XOR, and NOT . . . . . . . . . . . . . . . . . . . . . . . . The Shift Operators . . . . . . . . . . . . . . . . . . . . . . . . . . . . . The ? Operator . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Compound Assignment . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . The Comma Operator . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Multiple Assignments . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Using sizeof . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Dynamic Allocation Using new and delete . . . . . . . . . . . . . . . . . . . Initializing Dynamically Allocated Memory . . . . . . . . . . Allocating Arrays . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . C’s Approach to Dynamic Allocation: malloc( ) and free( ) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Precedence Summary . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
182 182 184 185 185 186 187 191 192 193 197 197 197 198 202 203 205 205 206 206 207 210 210
Structures and Unions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
215
Structures
............................................. Accessing Structure Members . . . . . . . . . . . . . . . . . . . . . Arrays of Structures . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
211 213 216 218 219
x
C++ from the Ground Up
A Simple Inventory Example . . . . . . . . . . . . . . . . . . . . . . Passing Structures to Functions . . . . . . . . . . . . . . . . . . . . Assigning Structures . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Pointers to Structures and the Arrow Operator . . . . . . . . References to Structures . . . . . . . . . . . . . . . . . . . . . . . . . . Arrays and Structures Within Structures . . . . . . . . . . . . . C Structure Versus C++ Structures . . . . . . . . . . . . . . . . . . Bit-Fields . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Unions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Anonymous Unions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Using sizeof to Ensure Portability . . . . . . . . . . . . . . . . . . . . . . . . . . Moving On to Object-Oriented Programming . . . . . . . . . . . . . . . . .
11
12
Introducing the Class
219 226 227 228 232 233 234 235 237 242 243 243
..............................
245
Class Fundamentals . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . The General Form of a class . . . . . . . . . . . . . . . . . . . . . . . A Closer Look at Class Member Access . . . . . . . . . . . . . . . . . . . . . . Constructors and Destructors . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Parameterized Constructors . . . . . . . . . . . . . . . . . . . . . . . An Initialization Alternative . . . . . . . . . . . . . . . . . . . . . . Classes and Structures Are Related . . . . . . . . . . . . . . . . . . . . . . . . . . Structures versus Classes . . . . . . . . . . . . . . . . . . . . . . . . . Unions and Classes Are Related . . . . . . . . . . . . . . . . . . . . . . . . . . . . Inline Functions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Creating Inline Functions Inside a Class . . . . . . . . . . . . . Arrays of Objects . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Initializing Object Arrays . . . . . . . . . . . . . . . . . . . . . . . . . Pointers to Objects . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Object References . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
246 250 250 252 255 259 260 262 263 264 265 267 268 270 272
A Closer Look at Classes
............................
273
Friend Functions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Overloading Constructors . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Dynamic Initialization . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Applying Dynamic Initialization to Constructors . . . . . . Assigning Objects . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Passing Objects to Functions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Constructors, Destructors, and Passing Objects . . . . . . . A Potential Problem When Passing Objects . . . . . . . . . . Returning Objects . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . A Potential Problem When Returning Objects . . . . . . . . Creating and Using a Copy Constructor . . . . . . . . . . . . . . . . . . . . . Copy Constructors and Parameters . . . . . . . . . . . . . . . . . Copy Constructors and Initializations . . . . . . . . . . . . . .
274 278 280 280 282 283 284 285 288 289 291 292 294
xi
Contents
13
14
15
16
Using Copy Constructors When an Object Is Returned . . . Copy Constructors—Is There a Simpler Way? . . . . . . . . The this Keyword . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
295 296 297
Operator Overloading . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
299
Operator Overloading Using Member Functions . . . . . . . . . . . . . . . Using Member Functions to Overload Unary Operators . . Operator Overloading Tips and Restrictions . . . . . . . . . . Nonmember Operator Functions . . . . . . . . . . . . . . . . . . . . . . . . . . . Order Matters . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Using a Friend to Overload a Unary Operator . . . . . . . . Overloading the Relational and Logical Operators . . . . . A Closer Look at the Assignment Operator . . . . . . . . . . . . . . . . . . . Overloading [ ] . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Overloading ( ) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Overloading Other Operators . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Another Example of Operator Overloading . . . . . . . . . . . . . . . . . . .
300 303 308 309 309 313 316 317 320 324 325 325
Inheritance . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
331
Introducing Inheritance . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Base Class Access Control . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Using protected Members . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Using protected for Inheritance of a Base Class . . . . . . . Reviewing public, protected, and private . . . . . . . . . . . . Inheriting Multiple Base Classes . . . . . . . . . . . . . . . . . . . . . . . . . . . Constructors, Destructors, and Inheritance . . . . . . . . . . . . . . . . . . . When Constructors and Destructors Are Executed . . . . . Passing Parameters to Base Class Constructors . . . . . . . . Granting Access . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Reading C++ Inheritance Graphs . . . . . . . . . . . . . . . . . . Virtual Base Classes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
332 335 337 340 342 342 343 343 346 350 352 352
Virtual Functions and Polymorphism . . . . . . . . . . . . . . . . .
357
Pointers to Derived Types . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . References to Derived Types . . . . . . . . . . . . . . . . . . . . . . Virtual Functions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Virtual Functions Are Inherited . . . . . . . . . . . . . . . . . . . . Why Virtual Functions? . . . . . . . . . . . . . . . . . . . . . . . . . . A Simple Application of Virtual Functions . . . . . . . . . . . Pure Virtual Functions and Abstract Classes . . . . . . . . . . Early versus Late Binding . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Polymorphism and the Purist . . . . . . . . . . . . . . . . . . . . .
358 360 360 363 365 366 370 372 373
Templates
........................................
375
Generic Functions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . A Function with Two Generic Types . . . . . . . . . . . . . . . . Explicitly Overloading a Generic Function . . . . . . . . . . .
376 378 379
xii
17
18
C++ from the Ground Up
Overloading a Function Template . . . . . . . . . . . . . . . . . . Using Standard Parameters with Template Functions . . . Generic Function Restrictions . . . . . . . . . . . . . . . . . . . . . Creating a Generic abs( ) Function . . . . . . . . . . . . . . . . . Generic Classes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . An Example with Two Generic Data Types . . . . . . . . . . . Creating a Generic Array Class . . . . . . . . . . . . . . . . . . . . Using Non-Type Arguments with Generic Classes . . . . . Using Default Arguments with Template Classes . . . . . . Explicit Class Specializations . . . . . . . . . . . . . . . . . . . . . .
381 382 383 383 384 387 388 389 391 393
Exception Handling . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
395
Exception Handling Fundamentals . . . . . . . . . . . . . . . . . . . . . . . . . exit( ) and abort( ) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Catching Class Types . . . . . . . . . . . . . . . . . . . . . . . . . . . . Using Multiple catch Statements . . . . . . . . . . . . . . . . . . . Options for Exception Handling . . . . . . . . . . . . . . . . . . . . . . . . . . . Catching All Exceptions . . . . . . . . . . . . . . . . . . . . . . . . . Restricting Exceptions Thrown by a Function . . . . . . . . Rethrowing an Exception . . . . . . . . . . . . . . . . . . . . . . . . Handling Exceptions Thrown by new . . . . . . . . . . . . . . . . . . . . . . . The nothrow Alternative . . . . . . . . . . . . . . . . . . . . . . . . . Overloading new and delete . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Overloading the nothrow Version of new . . . . . . . . . . . .
396 398 401 402 404 404 406 408 409 410 411 415
The C++ I/O System . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
417
Old VS Modern C++ I/O . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . C++ Streams . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . The C++ Predefined Streams . . . . . . . . . . . . . . . . . . . . . . The C++ Stream Classes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Overloading the I/O Operators . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Creating Inserters . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Using Friend Functions to Overload Inserters . . . . . . . . . Overloading Extractors . . . . . . . . . . . . . . . . . . . . . . . . . . C I/O Versus C++ I/O . . . . . . . . . . . . . . . . . . . . . . . . . . . . Formatted I/O . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Formatting with the ios Member Functions . . . . . . . . . . Using I/O Manipulators . . . . . . . . . . . . . . . . . . . . . . . . . . Creating Your Own Manipulator Functions . . . . . . . . . . File I/O . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Opening and Closing a File . . . . . . . . . . . . . . . . . . . . . . . Reading and Writing Text Files . . . . . . . . . . . . . . . . . . . . Unformatted Binary I/O . . . . . . . . . . . . . . . . . . . . . . . . . Reading and Writing Blocks of Data . . . . . . . . . . . . . . . . Detecting EOF . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . A File Comparison Example . . . . . . . . . . . . . . . . . . . . . .
418 418 419 419 420 421 423 424 426 426 426 431 433 435 435 438 439 441 442 443
xiii
Contents
More Binary I/O Functions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Random Access . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Checking I/O Status . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Customized I/O and Files . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
19
20
21
Run-Time Type ID and the Casting Operators
444 446 448 449
..........
451
Run-Time Type Identification (RTTI) . . . . . . . . . . . . . . . . . . . . . . . . A Simple Application of Run-Time Type ID . . . . . . . . . . typeid Can Be Applied to Template Classes . . . . . . . . . . The Casting Operators . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . dynamic_cast . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . const_cast . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . static_cast . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . reinterpret_cast . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . The Traditional Cast Versus the Four Casting Operators . .
452 456 458 462 462 467 468 469 470
Namespaces and Other Advanced Topics . . . . . . . . . . . . . . .
471
Namespaces . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Namespace Fundamentals . . . . . . . . . . . . . . . . . . . . . . . . using . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Unnamed Namespaces . . . . . . . . . . . . . . . . . . . . . . . . . . . The std Namespace . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Pointers to Functions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Finding the Address of an Overloaded Function . . . . . . . Static Class Members . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . const Member Functions and mutable . . . . . . . . . . . . . . . . . . . . . . Explicit Constructors . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . An Interesting Benefit from Implicit Constructor Conversion . . . . . . . . . . . . . . . . . . . . . . . The Member Initialization Syntax . . . . . . . . . . . . . . . . . . . . . . . . . . Using the asm Keyword . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Linkage Specification . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . The .* and –>* Pointer-to-Member Operators . . . . . . . . . . . . . . . . . Creating Conversion Functions . . . . . . . . . . . . . . . . . . . . . . . . . . . .
472 472 475 477 478 480 483 484 486 488
Introducing the Standard Template Library . . . . . . . . . . .
499
An Overview of the STL . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . The Container Classes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Vectors . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Accessing a Vector Through an Iterator . . . . . . . . . . . . . Inserting and Deleting Elements in a Vector . . . . . . . . . Storing Class Objects in a Vector . . . . . . . . . . . . . . . . . . . The Power of Iterators . . . . . . . . . . . . . . . . . . . . . . . . . . . Lists . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Sort a List . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Merging One List with Another . . . . . . . . . . . . . . . . . . . . Storing Class Objects in a List . . . . . . . . . . . . . . . . . . . . .
500 502 504 508 509 510 513 514 519 520 521
490 490 493 493 495 497
xiv
22
C++ from the Ground Up
Maps . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Storing Class Objects in a Map . . . . . . . . . . . . . . . . . . . . Algorithms . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Counting . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Removing and Replacing Elements . . . . . . . . . . . . . . . . . Reversing a Sequence . . . . . . . . . . . . . . . . . . . . . . . . . . . . Transforming a Sequence . . . . . . . . . . . . . . . . . . . . . . . . Exploring the Algorithms . . . . . . . . . . . . . . . . . . . . . . . . The string Class . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Some string Member Functions . . . . . . . . . . . . . . . . . . . . Putting Strings into Other Containers . . . . . . . . . . . . . . Final Thoughts on the STL . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
523 528 529 532 533 535 535 537 537 541 545 545
The C++ Preprocessor . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
547
#define
A
............................................... Function-Like Macros . . . . . . . . . . . . . . . . . . . . . . . . . . . #error . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . #include . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Conditional Compilation Directives . . . . . . . . . . . . . . . . . . . . . . . . #if, #else, #elif, and #endif . . . . . . . . . . . . . . . . . . . . . . . . #ifdef and #ifndef . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . #undef . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Using defined . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . The Diminishing Role of the Preprocessor . . . . . . . . . . . #line . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . #pragma . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . The # and ## Preprocessor Operators . . . . . . . . . . . . . . . . . . . . . . . . Predefined Macro Names . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Final Thoughts . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
548 550 552 552 553 553 555 556 557 557 558 559 559 560 561
C-Based I/O . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
563
C I/O Uses Streams . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Understanding printf( ) and scanf( ) . . . . . . . . . . . . . . . . . . . . . . . . printf( ) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . scanf( ) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . The C File System . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . fopen( ) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . fputc( ) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . fgetc( ) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . feof( ) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . fclose( ) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Using fopen( ), fgetc( ), fputc( ), and fclose( ) . . . . . . . . . ferror( ) and rewind( ) . . . . . . . . . . . . . . . . . . . . . . . . . . . fread( ) and fwrite( ) . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
564 565 565 567 572 573 574 574 575 575 575 576 577
xv
Contents
B C
fseek( ) and Random-Access I/O . . . . . . . . . . . . . . . . . . . . . . . . . . . . fprintf( ) and fscanf( ) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Erasing Files . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
578 579 580
Working with an Older C++ Compiler . . . . . . . . . . . . . . . . .
581
Two Simple Changes . . . . . . . . . . . . . . . . . . . . . . . . . . . .
583
The .NET Managed Extensions to C++
.................
585
The .NET Keyword Extensions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . _ _abstract . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . _ _box . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . _ _delegate . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . _ _event . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . _ _finally . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . _ _gc . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . _ _identifier . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . _ _interface . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . _ _nogc . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . _ _pin . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . _ _property . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . _ _sealed . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . _ _try_cast . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . _ _typeof . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . _ _value . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Preprocessor Extensions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . The attribute Attribute . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Compiling Managed C++ . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
586 586 587 587 587 587 587 587 587 587 588 588 588 588 588 588 588 589 589
Index
...........................................
591
This page intentionally left blank
Preface This book teaches you how to program in C++ — the most powerful computer language in use today. No previous programming experience is required. The book starts with the basics, covers the fundamentals, moves on to the core of the language, and concludes with its more advanced features. By the time you finish, you will be an accomplished C++ programmer. C++ is your gateway to modern, object-oriented programming. It is the preeminent language for the development of high-performance software and is the choice of programmers worldwide. Simply put, to be a top-flight, professional programmer today implies competency in C++. C++ is more than just a popular language. C++ provides the conceptual substrata that underlie the design of several other languages, and much of modern computing. It is no accident that two other important languages, Java and C#, are descended from C++. There is little in programming that has not been influenced by the syntax, style, and philosophy of C++. Because C++ was designed for professional programming, C++ is not the easiest programming language to learn. It is, however, the best programming language to learn. Once you have mastered C++, you will be able to write professional-quality, high-performance programs. You will also be able to easily learn languages like Java or C# because they share the same basic syntax and design as C++.
What Is New in the Third Edition In the time that has passed since the previous edition of this book, there have been no changes to the C++ language. There have, however, been big changes to the computing environment. For example, Java became the dominant language for Web programming, the .NET Framework was released, and C# was invented. Through all the changes of the past few years, one thing has remained constant: the staying
xvii
xviii
C++ from the Ground Up
power of C++. C++ has been, is, and will remain the dominant language of “power programmers” well into the forseeable future. The overall structure and organization of the third edition is similar to the second edition. Most of the changes involve updating and expanding the coverage throughout. In some cases, additional details were added. In other cases, the presentation of a topic was improved. In still other situations, descriptions were modernized to reflect the current programming environment. Several new sections were also added. Two appendices were added. One describes the extended keywords defined by Microsoft that are used for creating managed code for the .NET Framework. The second explains how to adapt the code in this book for use with an older, non-standard C++ compiler. Finally, all code examples were retested against the current crop of compilers, including Microsoft’s Visual Studio .NET and Borland’s C++ Builder.
What Version of C++ The material in this book describes Standard C++. This is the version of C++ defined by the ANSI/ISO Standard for C++, and it is the one that is currently supported by all major compilers. Therefore, using this book, you can be confident that what you learn today will also apply tomorrow.
How to Use This Book The best way to learn any programming language, including C++, is by doing. Therefore, after you have read through a section, try the sample programs. Make sure that you understand why they do what they do before moving on. You should also experiment with the programs, changing one or two lines at a time and observing the results. The more you program, the better you become at programming.
If You’re Using Windows If your computer uses Windows and your goal is to write Windows-based programs, then you have chosen the right language to learn. C++ is completely at home with Windows programming. However, none of the programs in this book use the Windows graphical user interface (GUI). Instead, they are console-based programs that can be run under a Windows console session, such as that provided by the Command Prompt window. The reason for this is easy to understand: GUI-based Windows programs are, by their nature, large and complex. They also use many techniques not directly related to the C++ language. Thus, they are not well-suited for teaching a programming language. However, you can still use a Windows-based compiler to compile the programs in this book because the compiler will automatically create a console session in which to execute your program. Once you have mastered C++, you will be able to apply your knowledge to Windows programming. In fact, Windows programming using C++ allows the use of class libraries such as MFC or the newer .NET Framework, which can greatly simplify the development of a Windows program.
Don’t Forget: Code on the Web Remember, the source code for all of the programs in this book is available free of charge on the Web at http://www.osborne.com. Downloading this code prevents you from having to type in the examples.
xix
For Further Study C++from the Ground Up is your gateway to the Herb Schildt series of programming books. Here are some others that you will find of interest. To learn more about C++, try C++: The Complete Reference C++: A Beginner’s Guide Teach Yourself C++ STL Programming From the Ground Up C++ Programmer’s Reference To learn about Java programming, we recommend the following: Java 2: A Beginner’s Guide Java 2: The Complete Reference Java 2 Programmer’s Reference To learn about C#, Herb offers these books: C#: A Beginner’s Guide C#: The Complete Reference To learn about Windows programming we suggest the following Schildt books: Windows 98 Programming From the Ground Up Windows 2000 Programming From the Ground Up MFC Programming From the Ground Up The Windows Programming Annotated Archives If you want to learn about the C language, which is the foundation of all modern programming, then the following titles will be of interest. C: The Complete Reference Teach Yourself C
When you need solid answers, fast, turn to Herbert Schildt, the recognized authority on programming.
This page intentionally left blank
CHAPTER 1 The Story of C++
1
2
C++ from the Ground Up
C
++ is the single most important language that any programmer can learn. This is a strong statement, but it is not an exaggeration. C++ is the center of gravity around which all of modern programming revolves. Its syntax and design philosophy define the essence of object-oriented programming. Moreover, C++ charts the course for future language development. For example, both Java and C# are directly descended from C++. C++ is also the universal language of programming; it is the language in which programmers share ideas with one another. To be a professional programmer today implies competency in C++. It is that fundamental and that important. C++ is the gateway to all of modern programming. Before beginning your study of C++, it is important for you to know how C++ fits into the historical context of computer languages. Understanding the forces that drove its creation, the design philosophy it represents, and the legacy that it inherits makes it easier to appreciate the many innovative and unique features of C++. With this in mind, this chapter presents a brief history of the C++ programming language, its origins, its relationship to its predecessor (C), its uses, and the programming philosophies that it supports. It also puts C++ into perspective relative to other programming languages.
The Origins of C++ The story of C++ begins with C. The reason for this is simple: C++ is built upon the foundation of C. In fact, C++ is a superset of C. (Indeed, all C++ compilers can also be used to compile C programs!) Specifically, C++ is an expanded and enhanced version of C that embodies the philosophy of object-oriented programming (which is described later in this chapter). C++ also includes several other improvements to the C language, including an extended set of library routines. However, much of the spirit and flavor of C++ is inherited directly from C. To fully understand and appreciate C++, you need to understand the “how and why” behind C.
The Creation of C The C language shook the computer world. Its impact should not be underestimated because it fundamentally changed the way programming was approached and thought about. C is considered by many to be the first modern “programmer’s language.” Prior to the invention of C, computer languages were generally designed either as academic exercises or by bureaucratic committees. C is different. C was designed, implemented, and developed by real, working programmers, and it reflected the way they approached the job of programming. Its features were honed, tested, thought about, and rethought by the people who actually used the language. The result of this process was a language that programmers liked to use. Indeed, C quickly attracted many followers who had a near-religious zeal for it, and it found wide and rapid acceptance in the programmer community. In short, C is a language designed by and for programmers. C was invented and first implemented by Dennis Ritchie on a DEC PDP-11 using the UNIX operating system. C is the result of a development process that started with an older language called BCPL, which was developed by Martin Richards. BCPL influenced a language called B, invented by Ken Thompson, which led to the development of C in the 1970s.
The Story of C++
3
For many years, the de facto standard for C was the one supplied with the Unix operating system and described in The C Programming Language, by Brian Kernighan and Dennis Ritchie (Prentice-Hall, 1978). However, because no formal standard existed, there were discrepancies between different implementations of C. To alter this situation, a committee was established in the beginning of the summer of 1983 to work on the creation of an ANSI (American National Standards Institute) standard that would define—once and for all—the C language. The final version of the standard was adopted in December 1989, the first copies of which became available in early 1990. This version of C is commonly referred to as C89, and it is the foundation upon which C++ is built.
N
OTE: The C standard was updated in 1999 and this version of C is usually referred to as C99. This version contains some new features, including a few borrowed from C++, but, overall, it is compatible with the original C89 standard. At the time of this writing, no widely available compiler supports C99 and it is still C89 that defines what is commonly thought of as the C language. Furthermore, it is C89 that is the basis for C++. It is possible that a future standard for C++ will include the features added by C99, but they are not part of C++ at this time. It may seem hard to understand at first, but C is often called a “middle-level” computer language. As it is applied to C, middle-level does not have a negative connotation; it does not mean that C is less powerful, harder to use, or less developed than a “high-level” language, or that it is as difficult to use as assembly language. (Assembly language, or assembler, as it is often called, is simply a symbolic representation of the actual machine code that a computer can execute.) C is thought of as a middle-level language because it combines elements of high-level languages, such as Pascal, Modula-2, or Visual Basic, with the functionality of assembler. From a theoretical point of view, a high-level language attempts to give the programmer everything he or she could possibly want, already built into the language. A low-level language provides nothing other than access to the actual machine instructions. A middle-level language gives the programmer a concise set of tools and allows the programmer to develop higher-level constructs on his or her own. A middle-level language offers the programmer built-in power, coupled with flexibility. Being a middle-level language, C allows you to manipulate bits, bytes, and addresses— the basic elements with which a computer functions. Thus, C does not attempt to buffer the hardware of the machine from your program to any significant extent. For example, the size of an integer in C is directly related to the word size of the CPU. In most high-level languages there are built-in statements for reading and writing disk files. In C, all of these procedures are performed by calls to library routines and not by keywords defined by the language. This approach increases C’s flexibility. C allows—indeed, needs—the programmer to define routines for performing high-level operations. These routines are called functions, and they are very important to the C language. In fact, functions are the building blocks of both C and C++. You can easily tailor a library of functions to perform various tasks that are used by your program. In this sense, you can personalize C to fit your needs.
1
4
C++ from the Ground Up
There is another aspect of C that you must understand, because it is also important to C++: C is a structured language. The most distinguishing feature of a structured language is that it uses blocks. A block is a set of statements that are logically connected. For example, imagine an IF statement that, if successful, will execute five discrete statements. If these statements can be grouped together and referenced as an indivisible unit, then they form a block. A structured language supports the concept of subroutines with local variables. A local variable is simply a variable that is known only to the subroutine in which it is defined. A structured language also supports several loop constructs, such as while, do-while, and for. The use of the goto statement, however, is either prohibited or discouraged, and is not the common form of program control in the same way that it is in traditional BASIC or FORTRAN. A structured language allows you to indent statements and does not require a strict field concept (as did early versions of FORTRAN). Finally, and perhaps most importantly, C is a language that stays out of the way. The underlying philosophy of C is that the programmer, not the language, is in charge. Therefore, C will let you do virtually anything that you want, even if what you tell it to do is unorthodox, highly unusual, or suspicious. C gives you nearly complete control over the machine. Of course, with this power comes considerable responsibility, which you, the programmer, must shoulder.
Understanding the Need for C++ Given the preceding discussion of C, you might be wondering why C++ was invented. Since C is a successful and useful computer programming language, why was there a need for something else? The answer is complexity. Throughout the history of programming, the increasing complexity of programs has driven the need for better ways to manage that complexity. C++ is a response to that need. To better understand this correlation, consider the following. Approaches to programming have changed dramatically since the invention of the computer. The primary reason for change has been to accommodate the increasing complexity of programs. For example, when computers were first invented, programming was done by toggling in the binary machine instructions using the computer’s front panel. As long as programs were just a few hundred instructions long, this approach worked. As programs grew, assembly language was invented so that programmers could deal with larger, increasingly complex programs by using symbolic representations of the machine instructions. As programs continued to grow, high-level languages were developed to give programmers more tools with which to handle complexity. The first widespread language was, of course, FORTRAN. While FORTRAN was a very impressive first step, it is hardly a language that encourages clear, easy-to-understand programs. The 1960s gave birth to structured programming. This is the method of programming supported by languages such as C. With structured languages, it was, for the first time, possible to write moderately complex programs fairly easily. However, even with structured programming methods, once a project reaches a certain size, its complexity exceeds what a programmer can manage. By the late 1970s, many projects were near or at this point. To solve this problem, a new way to program began to emerge. This method is called object-oriented programming (OOP for short). Using OOP,
The Story of C++
5
a programmer could handle larger programs. The trouble was that C did not support object-oriented programming. The desire for an object-oriented version of C ultimately led to the creation of C++. In the final analysis, although C is one of the most liked and widely used professional programming languages in the world, there comes a time when its ability to handle complexity reaches its limit. The purpose of C++ is to allow this barrier to be broken and to help the programmer comprehend and manage larger, more complex programs.
C++ Is Born In response to the need to manage greater complexity, C++ was born. It was invented by Bjarne Stroustrup in 1979 at Bell Laboratories in Murray Hill, New Jersey. He initially called the new language “C with Classes.” However, in 1983 the name was changed to C++. C++ contains the entire C language. As stated earlier, C is the foundation upon which C++ is built. C++ includes all of C’s features, attributes, and benefits. It also adheres to C’s philosophy that the programmer, not the language, is in charge. At this point, it is critical to understand that the invention of C++ was not an attempt to create a new programming language. Instead, it was an enhancement to an already highly successful language. Most of the additions that Stroustrup made to C were designed to support object-oriented programming. In essence, C++ is the object-oriented version of C. By building upon the foundation of C, Stroustrup provided a smooth migration path to OOP. Instead of having to learn an entirely new language, a C programmer needed to learn only a few new features to reap the benefits of the object-oriented methodology. But C is not the only language that influenced C++. Stroustrup states that some of its object-oriented features were inspired by another object-oriented language called Simula67. Therefore, C++ represents the blending of two powerful programming methods. When creating C++, Stroustrup knew that it was important to maintain the original spirit of C, including its efficiency, flexibility, and philosophy, while at the same time adding support for object-oriented programming. Happily, his goal was accomplished. C++ still provides the programmer with the freedom and control of C, coupled with the power of objects. Although C++ was initially designed to aid in the management of very large programs, it is in no way limited to this use. In fact, the object-oriented attributes of C++ can be effectively applied to virtually any programming task. It is not uncommon to see C++ used for projects such as compilers, editors, programmer tools, games, and networking programs. Because C++ shares C’s efficiency, much high-performance systems software is constructed using C++. Also, C++ is frequently the language of choice for Windows programming. One important point to remember is this: Because C++ is a superset of C, once you can program in C++, you can also program in C! Thus, you will actually be learning two programming languages at the same time, with the same effort that you would use to learn only one.
1
6
C++ from the Ground Up
The Evolution of C++ Since C++ was first invented, it has undergone three major revisions, with each revision adding to and altering the language. The first revision was in 1985 and the second occurred in 1990. The third revision occurred during the C++ standardization process. In the early 1990s, work began on a standard for C++. Towards that end, a joint ANSI and ISO (International Standards Organization) standardization committee was formed. The first draft of the proposed standard was created on January 25, 1994. In that draft, the ANSI/ISO C++ committee (of which I was a member) kept the features first defined by Stroustrup and added some new ones as well. But, in general, this initial draft reflected the state of C++ at the time. Soon after the completion of the first draft of the C++ standard, an event occurred that caused the standard to expand greatly: the creation of the Standard Template Library (STL) by Alexander Stepanov. As you will learn, the STL is a set of generic routines that you can use to manipulate data. It is both powerful and elegant. But the STL is also quite large. Subsequent to the first draft, the committee voted to include the STL in the specification for C++. The addition of the STL expanded the scope of C++ well beyond its original definition. While important, the inclusion of the STL, among other things, slowed the standardization of C++. It is fair to say that the standardization of C++ took far longer than any one had expected when it began. In the process, many new features were added to the language and many small changes were made. In fact, the version of C++ defined by the C++ committee is much larger and more complex than Stroustrup’s original design. The final draft was passed out of committee on November 14, 1997, and an ANSI/ISO standard for C++ became a reality in 1998. This specification for C++ is commonly referred to as Standard C++. The material in this book describes Standard C++. This is the version of C++ supported by all mainstream C++ compilers, including Microsoft’s Visual C++ and Borland’s C++ Builder. Therefore, the code and information in this book is fully applicable to all modern C++ environments.
What Is Object-Oriented Programming? Since object-oriented programming was fundamental to the development of C++, it is important to define precisely what object-oriented programming is. Object-oriented programming has taken the best ideas of structured programming and has combined them with several powerful concepts that allow you to organize your programs more effectively. In general, when programming in an object-oriented fashion, you decompose a problem into its constituent parts. Each component becomes a self-contained object that contains its own instructions and data related to that object. Through this process, complexity is reduced and you can manage larger programs. All object-oriented programming languages have three things in common: encapsulation, polymorphism, and inheritance. Although we will examine these concepts in detail later in this book, let’s take a brief look at them now.
The Story of C++
7
Encapsulation As you probably know, all programs are composed of two fundamental elements: program statements (code) and data. Code is that part of a program that performs actions, and data is the information affected by those actions. Encapsulation is a programming mechanism that binds together code and the data it manipulates, and that keeps both safe from outside interference and misuse. In an object-oriented language, code and data may be bound together in such a way that a self-contained black box is created. Within the box are all necessary data and code. When code and data are linked together in this fashion, an object is created. In other words, an object is the device that supports encapsulation. Within an object, the code, data, or both may be private to that object or public. Private code or data is known to, and accessible only by, another part of the object. That is, private code or data may not be accessed by a piece of the program that exists outside the object. When code or data is public, other parts of your program may access it, even though it is defined within an object. Typically, the public parts of an object are used to provide a controlled interface to the private elements of the object.
Polymorphism Polymorphism (from the Greek, meaning “many forms”) is the quality that allows one interface to be used for a general class of actions. The specific action is determined by the exact nature of the situation. A simple example of polymorphism is found in the steering wheel of an automobile. The steering wheel (i.e., the interface) is the same no matter what type of actual steering mechanism is used. That is, the steering wheel works the same whether your car has manual steering, power steering, or rack-and-pinion steering. Therefore, once you know how to operate the steering wheel, you can drive any type of car. The same principle can also apply to programming. For example, consider a stack (which is a first-in, last-out list). You might have a program that requires three different types of stacks. One stack is used for integer values, one for floating-point values, and one for characters. In this case, the algorithm that implements each stack is the same, even though the data being stored differs. In a non-object-oriented language, you would be required to create three different sets of stack routines, calling each set by a different name, with each set having its own interface. However, because of polymorphism, in C++ you can create one general set of stack routines (one interface) that works for all three specific situations. This way, once you know how to use one stack, you can use them all. More generally, the concept of polymorphism is often expressed by the phrase “one interface, multiple methods.” This means that it is possible to design a generic interface to a group of related activities. Polymorphism helps reduce complexity by allowing the same interface to be used to specify a general class of action. It is the compiler’s job to select the specific action (i.e., method) as it applies to each situation. You, the programmer, don’t need to do this selection manually. You need only remember and utilize the general interface. The first object-oriented programming languages were interpreters, so polymorphism was, of course, supported at run time. However, C++ is a compiled language. Therefore, in C++, both run-time and compile-time polymorphism are supported.
1
8
C++ from the Ground Up
Inheritance Inheritance is the process by which one object can acquire the properties of another object. The reason this is important is that it supports the concept of hierarchical classification. If you think about it, most knowledge is made manageable by hierarchical (i.e., top-down) classifications. For example, a Red Delicious apple is part of the classification apple, which in turn is part of the fruit class, which is under the larger class food. That is, the food class possesses certain qualities (edible, nutritious, etc.) that also apply, logically, to its fruit subclass. In addition to these qualities, the fruit class has specific characteristics (juicy, sweet, etc.) that distinguish it from other food. The apple class defines those qualities specific to an apple (grows on trees, not tropical, etc.). A Red Delicious apple would, in turn, inherit all the qualities of all preceding classes, and would define only those qualities that make it unique. Without the use of hierarchies, each object would have to explicitly define all of its characteristics. However, using inheritance, an object needs to define only those qualities that make it unique within its class. It can inherit its general attributes from its parent. Thus, it is the inheritance mechanism that makes it possible for one object to be a specific instance of a more general case.
C++ Implements OOP As you will see as you progress through this book, many of the features of C++ exist to provide support for encapsulation, polymorphism, and inheritance. Remember, however, that you can use C++ to write any type of program, using any type of approach. The fact that C++ supports object-oriented programming does not mean that you can only write object-oriented programs. As with its predecessor, C, one of C++’s strongest advantages is its flexibility.
How C++ Relates to Java and C# As most readers will know, there are two other computer languages that are having a strong impact on programming: Java and C#. Java was developed by Sun Microsystems and C# was created by Microsoft. Because there is sometimes confusion about how these two languages relate to C++, a brief discussion of their relationship is in order. C++ is the parent for both Java and C#. Although Java and C# added, removed, and modified various features, in total the syntax for all three languages is nearly identical. Furthermore, the object model used by C++ is similar to the ones used by Java and C#. Finally, the overall “look and feel” of these languages is very similar. This means that once you know C++, you can easily learn Java or C#. This is one reason that Java and C# borrowed C++’s syntax and object model; it facilitated their rapid adoption by legions of experienced C++ programmers. The reverse case is also true. If you know Java or C#, learning C++ is easy. The main difference between C++, Java, and C# is the type of computing environment for which each is designed. C++ was created to produce high-performance programs for a specific type of CPU and operating system. For example, if you want to write a high-performance program that runs on an Intel Pentium under the Windows operating system, then C++ is the best language to use.
The Story of C++
9
Java and C# were developed in response to the unique programming needs of the highly distributed networked environment that typifies much of contemporary computing. Java was designed to enable the creation of cross-platform portable code for the Internet. Using Java, it is possible to write a program that runs in a wide variety of environments, on a wide range of operating systems and CPUs. Thus, a Java program can move about freely on the Internet. C# was designed for Microsoft’s .NET Framework, which supports mixed-language, component-based code that works in a networked environment. Although both Java and C# enable the creation of portable code that works in a highly distributed environment, the price one pays for this portability is efficiency. Java programs execute slower than do C++ programs. The same is true for C#. Thus, if you want to create high-performance software, use C++. If you need to create highly portable software, use Java or C#. One final point: C++, Java, and C# are designed to solve different sets of problems. It is not an issue of which language is best in and of itself. Rather, it is a question of which language is right for the job at hand.
1
This page intentionally left blank
CHAPTER 2 An Overview of C++
11
12
C++ from the Ground Up
O
ne of the hardest things about learning a programming language is the fact that no element exists in isolation. Rather, the components of the language work together. It is this interrelatedness that makes it difficult to discuss one aspect of C++ without involving another. To help overcome this problem, this chapter provides a brief overview of several core C++ features, including the general form of a C++ program, some simple control statements, variables, and operators. It does not go into too many details, but rather concentrates on the general concepts common to all C++ programs. Most of the topics presented here are examined more closely in later chapters. Since learning is best accomplished by doing, it is recommended that you work through the examples using your computer.
Your First C++ Program Before getting into any theory, let’s look at a simple C++ program. We will start by entering, compiling, and running the following program. /* Program #1 - A first C++ program. Enter this program, then compile and run it. */ #include using namespace std; // main() is where program execution begins. int main() { cout cl -GX MyProg.cpp
The –GX option enhances compilation. To use the Visual C++ command-line compiler, you must first execute the batch file VCVARS32.BAT, which is provided by Visual C++. (You will want to consult your Visual C++ documentation for details.) To compile MyProg.cpp using C++ Builder, use this command line. C:\...>bcc32 Sample.cpp
The output from a C++ compiler is executable object code. For a Windows environment, the executable file will use the same name as the source file, but have the .exe extension. Thus, the executable version of MyProg.cpp will be in MyProg.exe.
N
OTE: If you are receiving error messages when you try to compile the first sample program and are positive that you have entered it correctly, then you may be using an older C++ compiler that predates the ANSI/ISO standard for C++. If this is the case, refer to Appendix B for instructions on using an older compiler.
2
14
C++ from the Ground Up
Run the Program After a C++ program has been compiled, it is ready to be run. Since the output from a C++ compiler is executable object code, to run the program, simply enter its name at the command prompt. For example, to run MyProg.exe use this command line: C:\...>MyProg
When run, the program displays the following output. This is my first C++ program.
If you are using an Integrated Development Environment, then you can run a program by selecting Run from a menu. Consult the instructions for your specific compiler. As mentioned earlier, for the programs in this book, it is usually easier to compile and run from the command line. One last point: The programs in this book are console-based, not window-based. That is, they run in a Command Prompt session. C++ is completely at home with Windows programming. Indeed, it is the most commonly used language for Windows development. However, none of the programs in this book use the Windows Graphic User Interface (GUI). The reason for this is easy to understand: Windows is a complicated environment to write programs for, involving many side issues unrelated to the C++ language. In contrast, console-based programs are much shorter and are the type of programs normally used to teach programming. Once you have mastered C++, you will be able to apply your knowledge to Windows programming with no trouble.
A Line-by-Line Explanation Now that you have successfully compiled and run the first sample program it is time to understand how it works. Towards this end, we will examine the program line by line. The program begins with the lines /* Program #1 - A first C++ program. Enter this program, then compile and run it. */ A comment is a remark that is embedded in your program.
This is a comment. Like most other programming languages, C++ lets you enter a remark into a program’s source code. The contents of a comment are ignored by the compiler. The purpose of a comment is to describe or explain the operation of a program to anyone reading its source code. In the case of this comment, it identifies the program. In more complex programs, you will use comments to help explain what each feature of the program is for and how it goes about doing its work. In other words, you can use comments to provide a “play-by-play” description of what your program does. In C++, there are two types of comments. The one you’ve just seen is called a multiline comment. This type of comment begins with a /* (a slash followed by an asterisk). It ends only when a */ is encountered. Anything between these two comment symbols
An Overview of C++
15
is completely ignored by the compiler. Multiline comments may be one or more lines long. The second type of comment is found a little further on in the program; we’ll be discussing it shortly. The next line of code looks like this: #include
The C++ language defines several headers, which contain information that is either necessary or useful to your program. For this program, the header is needed. (It is used to support the C++ I/O system.) This header is provided with your compiler. A header is included in your program by using the #include directive. Later in this book, you will learn more about headers and why they are important. The next line in the program is using namespace std;
This tells the compiler to use the std namespace. Namespaces are a relatively recent addition to C++. Although namespaces are discussed in detail later in this book, here is a brief description. A namespace creates a declarative region in which various program elements can be placed. Elements declared in one namespace are separate from elements declared in another. Namespaces help in the organization of large programs. The using statement informs the compiler that you want to use the std namespace. This is the namespace in which the entire Standard C++ library is declared. By using the std namespace, you simplify access to the standard library. The next line in the program is // main() is where program execution begins.
This line shows you the second type of comment available in C++: the single-line comment. Single-line comments begin with // and stop at the end of the line. Typically, C++ programmers use multiline comments when writing larger, more detailed commentaries, and they use single-line comments when short remarks are needed. However, this is a matter of personal style. The next line, as the preceding comment indicates, is where program execution begins: int main() main( ) is where a C++ program begins execution.
All C++ programs are composed of one or more functions. (Loosely speaking, a function is a subroutine.) Every C++ function must have a name, and the only function that any C++ program must include is the one shown here, called main( ). The main( ) function is where program execution begins and (most commonly) ends. (Technically speaking, a C++ program begins with a call to main( ) and, in most cases, ends when main( ) returns.) The opening curly brace on the line that follows main( ) marks the start of the main( ) function’s code. The int that precedes main( ) specifies the type
2
16
C++ from the Ground Up
of data returned by main( ). As you will learn, C++ supports several built-in data types and int is one of them. It stands for integer. The next line in the program is cout