Beginning Modern C++ 148420008X, 9781484200087, 9781484200070, 1484200071

Beginning Modern C++ is based on and supersedes Ivor Horton s previous book, Beginning ANSI C++. This book is a tutorial

591 115 7MB

English Pages 1120 [620] Year 2014

Report DMCA / Copyright

DOWNLOAD FILE

Polecaj historie

Beginning Modern C++
 148420008X, 9781484200087, 9781484200070, 1484200071

Table of contents :
Contents at a Glance......Page 3
Contents......Page 603
About the Author......Page 619
About the Technical Reviewer......Page 620
Introduction......Page 5
Modern C++......Page 7
Comments and Whitespace......Page 8
Functions......Page 9
Statements......Page 10
Namespaces......Page 11
Names and Keywords......Page 12
Code Presentation Style......Page 13
Creating an Executable......Page 14
Binary Numbers......Page 15
Hexadecimal Numbers......Page 17
Negative Binary Numbers......Page 18
Big-Endian and Little-Endian Systems......Page 20
Floating-Point Numbers......Page 21
ASCII Codes......Page 22
C++ Source Characters......Page 23
Escape Sequences......Page 24
Procedural and Object-Oriented Programming......Page 26
Summary......Page 27
Variables, Data, and Data Types......Page 29
Defining Integer Variables......Page 30
Decimal Integer Literals......Page 32
Octal Literals......Page 33
Calculations with Integers......Page 34
More on Assignment Operations......Page 36
The op= Assignment Operators......Page 38
The sizeof Operator......Page 40
Postfix Increment and Decrement Operations......Page 41
Defining Floating-Point Variables......Page 42
Floating-Point Literals......Page 43
Floating-Point Calculations......Page 44
Mathematical Functions......Page 46
Formatting Stream Output......Page 49
Mixed Expressions and Type Conversion......Page 51
Explicit Type Conversion......Page 53
Finding the Limits......Page 55
Working with Character Variables......Page 56
Working with Unicode Characters......Page 57
Lvalues and Rvalues......Page 58
Summary......Page 59
Operator Precedence and Associativity......Page 61
Bitwise Operators......Page 63
The Bitwise Shift Operators......Page 64
Logical Operations on Bit Patterns......Page 66
Using the Bitwise AND......Page 67
Using the Bitwise OR......Page 68
Using the Bitwise Exclusive OR......Page 69
Enumerated Data Types......Page 73
Synonyms for Data Types......Page 76
Global Variables......Page 77
External Variables......Page 81
Summary......Page 82
Comparing Data Values......Page 84
Applying the Comparison Operators......Page 85
The if Statement......Page 87
Nested if Statements......Page 90
Code-Neutral Character Handling......Page 91
The if-else Statement......Page 93
Nested if-else Statements......Page 94
Understanding Nested ifs......Page 95
Logical AND......Page 97
Logical Negation......Page 98
The Conditional Operator......Page 100
The switch Statement......Page 102
Unconditional Branching......Page 105
Statement Blocks and Variable Scope......Page 106
Summary......Page 107
Arrays......Page 109
Using an Array......Page 110
Understanding Loops......Page 111
The for Loop......Page 112
Avoiding Magic Numbers......Page 114
Determining the Size of an Array......Page 115
Controlling a for Loop with Floating-Point Values......Page 117
More Complex for Loop Control Expressions......Page 118
The Ranged-based for Loop......Page 120
The while Loop......Page 121
Allocating an Array at Runtime......Page 123
The do-while Loop......Page 125
Nested Loops......Page 127
Skipping Loop Iterations......Page 129
Indefinite Loops......Page 131
Arrays of Characters......Page 135
Multidimensional Arrays......Page 138
Initializing Multidimensional Arrays......Page 140
Setting Dimensions by Default......Page 141
Multidimensional Character Arrays......Page 142
Using array Containers......Page 144
Using std::vector Containers......Page 148
The Capacity and Size of a Vector......Page 149
Deleting Elements from a Vector container......Page 151
Summary......Page 152
What Is a Pointer ?......Page 154
The Address-Of Operator......Page 156
The Indirection Operator......Page 157
Pointers to Type char......Page 159
Arrays of Pointers......Page 161
Constant Pointers and Pointers to Constants......Page 163
Pointer Arithmetic......Page 165
Using Pointer Notation with an Array Name......Page 167
The Stack and the Heap......Page 170
Using the new and delete Operators......Page 171
Dynamic Allocation of Arrays......Page 172
Hazards of Dynamic Memory Allocation......Page 174
Fragmentation of the Free Store......Page 175
Raw Pointers and Smart Pointers......Page 176
Using unique_ptr Pointers......Page 177
Using shared_ptr Pointers......Page 178
Comparing shared_ptr Objects......Page 181
weak_ptr Pointers......Page 182
Understanding References......Page 183
Using a Reference Variable in a Range-Based for Loop......Page 184
Defining rvalue References......Page 185
Summary......Page 186
A Better Class of String......Page 188
Defining string Objects......Page 189
Concatenating Strings......Page 191
Accessing Characters in a String......Page 193
Accessing Substrings......Page 195
Comparing Strings......Page 196
The compare( ) Function......Page 198
Comparisons Using substr( )......Page 200
Searching Strings......Page 201
Searching for any of a Set of Characters......Page 203
Searching a String Backwards......Page 206
Inserting a String......Page 207
Replacing a Substring......Page 208
Removing Characters from a String......Page 210
Strings of wchar_t Characters......Page 211
Raw String Literals......Page 212
Summary......Page 213
Segmenting Your Programs......Page 215
Defining Functions......Page 216
The Function Body......Page 218
Function Declarations......Page 219
Function Prototypes......Page 220
Pass-by-Value......Page 221
Passing a Pointer to a Function......Page 223
Passing an Array to a Function......Page 224
const Pointer Parameters......Page 225
Passing a Multidimensional Array to a Function......Page 226
Pass-by-Reference......Page 227
References Can Be Risky......Page 228
Improving the Program......Page 230
References versus Pointers......Page 231
Arguments to main()......Page 232
Multiple Default Parameter Values......Page 233
Returning a Pointer......Page 235
Returning a Reference......Page 240
Static Variables......Page 241
Function Overloading......Page 243
Overloading and Reference Parameters......Page 245
Overloading with const Pointer Parameters......Page 247
Overloading and Default Argument Values......Page 248
A Sausage Machine for Functions......Page 249
Creating Instances of a Function Template......Page 250
Explicit Template Argument......Page 251
Function Template Specialization......Page 252
Function Templates and Overloading......Page 253
Function Templates with Multiple Parameters......Page 254
Non-Type Template Parameters......Page 255
Trailing Return Types......Page 256
Pointers to Functions......Page 257
Defining Pointers to Functions......Page 258
Recursion......Page 260
The Quicksort Algorithm......Page 263
The main() Function......Page 264
The extract_words() Function......Page 265
The sort() function......Page 266
The max_word_length() Function......Page 267
The show_words() Function......Page 268
Summary......Page 269
Introducing Lambda Expressions......Page 273
Naming a Lambda Expression......Page 274
Function Templates that Accept Lambda Expression Arguments......Page 276
A Function Parameter Type for Lambda Arguments......Page 277
Using the std::function Template Type......Page 278
The Capture Clause......Page 281
Capturing Specific Variables......Page 282
Using Lambda Expressions in a Template......Page 283
Recursion in Lambda Expressions......Page 285
Summary......Page 286
Understanding Translation Units......Page 288
Determining Linkage for a Name......Page 289
Preprocessing Your Source Code......Page 290
Defining Preprocessing Identifiers......Page 292
Including Header Files......Page 293
Preventing Duplication of Header File Contents......Page 294
Namespaces......Page 295
Defining a Namespace......Page 296
Functions and Namespaces......Page 299
Namespace Aliases......Page 302
Nested Namespaces......Page 303
Testing for Specific Identifier Values......Page 304
Multiple Choice Code Selection......Page 305
Standard Preprocessing Macros......Page 306
Integrated Debuggers......Page 307
Preprocessing Directives in Debugging......Page 308
Switching Off assert() Macros......Page 312
Static Assertions......Page 313
Summary......Page 314
Classes and Object-Oriented Programming......Page 316
Encapsulation......Page 317
Inheritance......Page 318
Polymorphism......Page 319
Terminology......Page 320
Defining a Class......Page 321
Constructors......Page 323
Defining Constructors Outside the Class......Page 325
Using a Constructor Initialization List......Page 327
Use of the explicit Keyword......Page 328
Delegating Constructors......Page 330
The Copy Constructor......Page 331
Accessing Private Class Members......Page 332
The Friend Functions of a Class......Page 334
The this Pointer......Page 337
Returning this from a Function......Page 338
const Objects and const Member Functions......Page 339
Casting Away const......Page 340
Arrays of Class Objects......Page 341
The Size of a Class Object......Page 342
Static Data Members......Page 343
Accessing Static Data Members......Page 346
Static Function Members......Page 347
Destructors......Page 348
Using Pointers As Class Members......Page 351
Defining the Package Class......Page 354
Defining the Truckload Class......Page 355
Implementing the Truckload Class......Page 356
Nested Classes......Page 360
Summary......Page 363
Implementing Operators for a Class......Page 366
Operators That Can Be Overloaded......Page 367
Implementing an Overloaded Operator......Page 368
Global Operator Functions......Page 370
Implementing Full Support for an Operator......Page 371
Implementing All Comparison Operators in a Class......Page 372
Operator Function Idioms......Page 374
Default Class Members......Page 375
Defining the Destructor......Page 376
Implementing the Assignment Operator......Page 378
Implementing Move Operations......Page 380
Overloading the Arithmetic Operators......Page 381
Improving Output Operations......Page 385
Implementing One Operator in Terms of Another......Page 387
Overloading the Subscript Operator......Page 388
Lvalues and the Overloaded Subscript Operator......Page 393
Overloading the Increment and Decrement Operators......Page 396
Overloading Type Conversions......Page 395
Function Objects......Page 397
Summary......Page 398
Classes and Object-Oriented Programming......Page 400
Hierarchies......Page 401
Inheritance vs. Aggregation......Page 402
Deriving Classes......Page 403
The Access Level of Inherited Class Members......Page 406
Choosing Access Specifiers in Class Hierarchies......Page 408
Changing the Access Specification of Inherited Members......Page 409
Constructor Operation in a Derived Class......Page 410
The Copy Constructor in a Derived Class......Page 413
The Default Constructor in a Derived Class......Page 415
Inheriting Constructors......Page 416
Destructors Under Inheritance......Page 417
The Order in Which Destructors Are Called......Page 418
Duplicate Data Member Names......Page 419
Multiple Inheritance......Page 420
Multiple Base Classes......Page 421
Inherited Member Ambiguity......Page 422
Repeated Inheritance......Page 425
Virtual Base Classes......Page 426
Summary......Page 427
Using a Base Class Pointer......Page 429
Calling Inherited Functions......Page 431
Virtual Functions......Page 434
Virtual Functions and Class Hierarchies......Page 438
Using final......Page 440
Access Specifiers and Virtual Functions......Page 441
Default Argument Values in Virtual Functions......Page 442
Using References to Call Virtual Functions......Page 444
Calling the Base Class Version of a Virtual Function......Page 445
Converting Between Pointers to Class Objects......Page 446
Casting Pointers Dynamically......Page 448
Determining the Polymorphic Type......Page 450
The Cost of Polymorphism......Page 451
Pure Virtual Functions......Page 452
Abstract Classes......Page 453
Abstract Classes As Interfaces......Page 455
Indirect Abstract Base Classes......Page 456
Destroying Objects Through a Pointer......Page 458
Summary......Page 460
Handling Errors......Page 462
Understanding Exceptions......Page 463
Throwing an Exception......Page 464
The Exception Handling Process......Page 466
Unhandled Exceptions......Page 467
Code That Causes an Exception to Be Thrown......Page 468
Nested try Blocks......Page 470
How It Works......Page 472
Class Objects as Exceptions......Page 473
Matching a Catch Handler to an Exception......Page 474
How It Works......Page 476
Catching Derived Class Exceptions with a Base Class Handler......Page 477
Rethrowing Exceptions......Page 479
Catching All Exceptions......Page 482
Function try Blocks......Page 484
Constructor try Blocks......Page 485
Standard Library Exceptions......Page 486
The Exception Class Definitions......Page 488
Deriving your own Exception Classes......Page 489
Summary......Page 492
Understanding Class Templates......Page 494
Defining Class Templates......Page 495
Template Parameters......Page 496
A Simple Class Template......Page 497
Constructor Templates......Page 499
The Destructor Template......Page 500
The Assignment Operator Template......Page 501
Instantiating a Class Template......Page 502
Static Members of a Class Template......Page 507
Non-Type Class Template Parameters......Page 508
Templates for Function Members with Non-Type Parameters......Page 511
Pointers and Arrays as Non-Type Parameters......Page 515
Default Values for Template Parameters......Page 516
Special Cases......Page 517
Using static_assert( ) in a Class Template......Page 518
Defining a Class Template Specialization......Page 519
Choosing between Multiple Partial Specializations......Page 520
Friends of Class Templates......Page 521
Class Templates with Nested Classes......Page 523
Function Templates for Stack Members......Page 525
Summary......Page 529
Input and Output in C++......Page 531
Binary Mode Operations......Page 532
Advantages of Using Streams......Page 533
Stream Classes......Page 534
Stream Insertion and Extraction Operations......Page 535
Stream Insertion Operations......Page 536
Stream Manipulators......Page 537
Manipulators with Arguments......Page 539
File Streams......Page 540
Writing a File in Text Mode......Page 541
Checking the State of a File Stream......Page 543
Reading the File......Page 544
Setting the Stream Open Mode......Page 546
Managing the Current Stream Position......Page 551
Unformatted Stream Operations......Page 553
Unformatted Stream Input......Page 554
Errors in Stream Input/Output......Page 556
Input/Output Errors and Exceptions......Page 558
Stream Operations in Binary Mode......Page 559
Writing Numeric Data in Binary......Page 561
File Read/Write Operations......Page 569
Random File Operations in Practice......Page 570
Implementing the Constructor......Page 571
Checking for the Existence of a File......Page 572
Finding a Prime that follows a Prime......Page 573
Implementing the Subscript Operator......Page 574
Using the Primes Class......Page 575
String Streams......Page 576
Using the Insertion Operator with Objects......Page 577
Using the Extraction Operator with Objects......Page 578
Object I/O in Binary Mode......Page 580
More Complex Objects in Streams......Page 583
Summary......Page 588
Index......Page 590

Citation preview

For your convenience Apress has placed some of the front matter material after the index. Please use the Bookmarks and Contents at a Glance links to access them.

Contents at a Glance About the Author������������������������������������������������������������������������������������������������������������� xxiii About the Technical Reviewer������������������������������������������������������������������������������������������ xxv Introduction�������������������������������������������������������������������������������������������������������������������� xxvii ■■Chapter 1: Basic Ideas������������������������������������������������������������������������������������������������������1 ■■Chapter 2: Introducing Fundamental Types of Data �������������������������������������������������������23 ■■Chapter 3: Working with Fundamental Data Types���������������������������������������������������������55 ■■Chapter 4: Making Decisions������������������������������������������������������������������������������������������79 ■■Chapter 5: Arrays and Loops�����������������������������������������������������������������������������������������105 ■■Chapter 6: Pointers and References������������������������������������������������������������������������������151 ■■Chapter 7: Working with Strings�����������������������������������������������������������������������������������185 ■■Chapter 8: Defining Functions���������������������������������������������������������������������������������������213 ■■Chapter 9: Lambda Expressions������������������������������������������������������������������������������������271 ■■Chapter 10: Program Files and Preprocessing Directives���������������������������������������������287 ■■Chapter 11: Defining Your Own Data Types�������������������������������������������������������������������315 ■■Chapter 12: Operator Overloading���������������������������������������������������������������������������������365 ■■Chapter 13: Inheritance������������������������������������������������������������������������������������������������399 ■■Chapter 14: Polymorphism��������������������������������������������������������������������������������������������429

v

■ Contents at a Glance

■■Chapter 15: Runtime Errors and Exceptions�����������������������������������������������������������������463 ■■Chapter 16: Class Templates�����������������������������������������������������������������������������������������495 ■■Chapter 17: File Input and Output���������������������������������������������������������������������������������533 Index���������������������������������������������������������������������������������������������������������������������������������593

vi

Introduction Welcome to Beginning C++. This is a revised and updated version of my previous book, Beginning ANSI C++. The C++ language has been extended and improved considerably since the previous book, so much so that it was no longer possible to squeeze detailed explanations of all of C++ in a single book. This tutorial will teach enough of the essential C++ language and Standard Library features to enable you to write your own C++ applications. With the knowledge from this book you should have no difficulty in extending the depth and scope of your C++ expertise. C++ is much more accessible than many people assume. I have assumed no prior programming knowledge. If you are keen to learn and have an aptitude for thinking logically, getting a grip on C++ will be easier than you might imagine. By developing C++ skills, you’ll be learning a language that is already used by millions, and that provides the capability for application development in just about any context. The C++ language in this book corresponds to the latest ISO standard, commonly referred to as C++ 14. C++ 14 is a minor extension over the previous standard, C++ 11, so there is very little in the book that is C++ 14 specific. All the examples in the book can be compiled and executed using C++ 11-conforming compilers that are available now.

Using the Book To learn C++ with this book, you’ll need a compiler that conforms reasonably well to the C++ 11 standard and a text editor suitable for working with program code. There are several compilers available currently that are reasonably C++ 11 compliant, some of which are free. The GCC compiler that is produced by the GNU Project has comprehensive support for C++ 11 and it is open source and free to download. Installing GCC and putting it together with a suitable editor can be a little tricky if you are new to this kind of thing. An easy way to install GCC along with a suitable editor is to download Code::Blocks from http://www.codeblocks.org. Code::Blocks is a free IDE for Linux, Apple Mac OS X, and Microsoft Windows. It supports program development using several compilers including compilers for GCC, Clang, and open Watcom. This implies you get support for C, C++, and Fortran. Another possibility is to use Microsoft Visual C++ that runs under Microsoft Windows. It is not fully compliant with C++ 11, but it’s getting there. The free version is available as Microsoft Visual Studio 2013 Express and at the time of writing this will compile most of the examples, and should compile them all eventually. You can download it from http://www.microsoft.com/en-us/download/details.aspx?id=43733. While the Microsoft Visual C++ compiler is more limited than GCC, in terms of the extent to which C++ 11 is supported, you get a professional editor and support for other languages such as C# and Basic. Of course, you can always install both! There are other compilers that support C++ 11, which you can find with a quick online search. I’ve organized the material in this book to be read sequentially, so you should start at the beginning and keep going until you reach the end. However, no one ever learned programming by just reading a book. You’ll only learn how to program in C++ by writing code, so make sure you key in all the examples—don’t just copy them from the download files—and compile and execute the code that you’ve keyed in. This might seem tedious at times, but it’s surprising how much just typing in C++ statements will help your understanding, especially when you may feel you’re struggling with some of the ideas. If an example doesn’t work, resist the temptation to go straight back to the book to see why. Try to figure out from your code what is wrong. This is good practice for what you’ll have to do when you are developing C++ applications for real.

xxvii

■ Introduction

Making mistakes is a fundamental part of the learning process and the exercises should provide you with ample opportunity for that. It’s a good idea to dream up a few exercises of your own. If you are not sure about how to do something, just have a go before looking it up. The more mistakes you make, the greater the insight you’ll have into what can, and does, go wrong. Make sure you attempt all the exercises, and remember, don’t look at the solutions until you’re sure that you can’t work it out yourself. Most of these exercises just involve a direct application of what’s covered in a chapter—they’re just practice, in other words—but some also require a bit of thought or maybe even inspiration. I wish you every success with C++. Above all, enjoy it!

—Ivor Horton

xxviii

Chapter 1

Basic Ideas I’ll sometimes have to make use of things in examples before I have explained them in detail. This chapter is intended to help when this occurs by giving you an overview of the major elements of C++ and how they hang together. I’ll also explain a few concepts relating to the representation of numbers and characters in your computer. In this chapter you’ll learn: •

What is meant by Modern C++



The elements of a C++ program



How to document your program code



How your C++ code becomes an executable program



How object-oriented programming differs from procedural programming



What binary, hexadecimal, and octal number systems are



What Unicode is

Modern C++ Modern C++ is programming using of the features of the latest and greatest incarnation of C++. This is the C++ language defined by the C++ 11 standard, which is being modestly extended and improved by the latest standard, C++ 14. This book relates to C++ as defined by C++14. There’s no doubt that C++ is the most widely used and most powerful programming language in the world today. If you were just going to learn one programing language, C++ is the ideal choice. It is effective for developing applications across an enormous range of computing devices and environments: for personal computers, workstations, mainframe computers, tablets, and mobile phones. Just about any kind of program can be written in C++ from device drivers to operating systems, from payroll and administrative programs to games. C++ compilers are available widely too. There are up-to-date compilers that run on PCs, workstations, and mainframes, often with cross-compiling capabilities, where you can develop the code in one environment and compile it to execute in another. C++ comes with a very extensive Standard Library. This is a huge collection of routines and definitions that provide functionality that is required by many programs. Examples are numerical calculations, string processing, sorting and searching, organizing and managing data, and input and output. The Standard Library is so vast that we will only scratch the surface of what is available in this book. It really needs several books to fully elaborate all the capability it provides. Beginning STL is a companion book that is a tutorial on using the Standard Template Library, which is the subset of the C++ Standard Library for managing and processing data in various ways.

1

Chapter 1 ■ Basic Ideas

Given the scope of the language and the extent of the library, it’s not unusual for a beginner to find C++ somewhat daunting. It is too extensive to learn in its entirety from a single book. However, you don’t need to learn all of C++ to be able to write substantial programs. You can approach the language step by step, in which case it really isn’t difficult. An analogy might be learning to drive a car. You can certainly become a very competent and safe driver without necessarily having the expertise, knowledge, and experience to drive in the Indianapolis 500. With this book you can learn everything you need to program effectively in C++. By the time you reach the end, you’ll be confidently writing your own applications. You’ll also be well equipped to explore the full extent of C++ and its Standard Library.

C++ Program Concepts There will be much more detail on everything I discuss in this section later in the book. I’ll jump straight in with the complete, fully working, C++ program shown in Figure 1-1, which explains what the various bits of it are. I’ll use the example as a base for discussing some more general aspects of C++.

This is a statement. Statements end with a semicolon. There is also a comment on this line.

// Ex1_01.cpp // A complete C++ program

These two lines are comments. Comments begin with //

#include

This line adds input/output capability.

int main ( ) {

This is the first line of the function main.

int answer {42};

// Defines answer with value 42

std::cout answer; if (toupper(answer) == 'N') break; } double total{}; size_t count{}; day = 1; std::cout value) result = value; return result; }   You need the compare.h header file to be included so that the namespace is identified. This tells the compiler to deduce that the functions are declared within the namespace. There's an #include directive for the vector header that is also included into compare.h. The contents of the vector header will only appear once in this file because all the Standard Library headers have preprocessing directives to prevent duplication. It's a good idea in general to have #include directives for every header that a file uses, even when one header may include another header that you use. This makes the file independent of potential changes to the header files. Of course you could place the code for the function definitions within the compare namespace directly. In this case, the contents of compare.cpp would be:   #include   namespace compare { double max(const std::vector& data) { // Code for max() as above... }   double min(const std::vector& data) { // Code for min() as above... } }  

299

Chapter 10 ■ Program Files and Preprocessing Directives

If you write the function definitions in this way, then you don’t need to #include compare.h into this file. This is because the definitions are within the namespace. Using the functions is the same, however you have defined them. To confirm how easy it is, let’s try it out with the functions that you’ve just defined. Create the compare.h header file with the contents I discussed earlier. Create the first version of compare.cpp where the definitions are not defined in a namespace block. All you need now is a .cpp file containing the definition of main() to try the functions out:   // Ex10_02.cpp // Using functions in a namespace #include #include #include "compare.h"   using compare::max; // Using declaration for max using compare::min; // Using declaration for min   int main() { std::vector data {1.5, 4.6, 3.1, 1.1, 3.8, 2.1}; std::cout 0) length = lv; return this; }   Box* Box::setWidth(double wv) { if(wv > 0) width = wv; return this; }   Box* Box::setHeight(double hv) { if(hv > 0) height = hv; return this; }   Now you can modify all the dimensions of a Box object in a single statement:   Box aBox {10.0,15.0,25.0}; // Create a box aBox.setLength(20.0)->setWidth(40.0)->setHeight(10.0); // Set all dimensions of aBox   Because the mutator functions return the this pointer, you can use the value returned by one function to call the next. Thus the pointer returned by setLength() is used to call setWidth(), which returns a pointer you can use to call setHeight(). Isn’t that nice?

const Objects and const Member Functions Let’s look again at the volume() function member of the Box class in Ex11_03. Suppose you change the code in main() so that box1 is const:   const Box box1 {2.0, 3.0, 4.0}; // A box that is a constant Box box2 {5.0}; // A box that is a cube std::cout getNext(); // Save the next package if (pPackage) // If there is one... { pCurrent = pPackage; // Update current to the next return pPackage->getBox(); } pCurrent = nullptr; // If we get to here... return nullptr; // ...there was no next }  

356

Chapter 11 ■ Defining Your Own Data Types

When pCurrent contains the address of a Package object, you call its getNext() member to obtain the address of the next Package object and save it in pPackage. If pCurrent is nullptr, then the first in the list is obtained and returned by calling getFirstBox(). If the pointer to the next Package object, pPackage, is not nullptr, it is stored in pCurrent and the Box pointer it contains is returned. If pPackage is nullptr, the end of the list has been reached so pCurrent is reset to nullptr and nullptr is returned. Because nullptr is returned to signal there is no next pointer to a Box, we cannot return a reference. The member to list the contents of the Truckload object can be implemented like this:   void Truckload::listBoxes() { pCurrent = pHead; size_t count {}; while (pCurrent) { pCurrent->getBox()->listBox(); pCurrent = pCurrent->getNext(); if(! (++count % 5)) std::cout pNext; return pHead->pBox; }   The function to obtain the address of the next Box object in the list can now be defined as:   ptr Truckload::getNextBox() { if (!pCurrent) // If there's no current... return getFirstBox(); // ...return the 1st   auto pPackage = pCurrent->pNext; // Save the next package if (pPackage) // If there is one... { pCurrent = pPackage; // Update current to the next return pPackage->pBox; } pCurrent = nullptr; // If we get to here... return nullptr; // ...there was no next }   Finally the listBoxes() member of Truckload will be:   void Truckload::listBoxes() { pCurrent = pHead; size_t count {}; while (pCurrent) { pCurrent->pBox->listBox(); pCurrent = pCurrent->pNext; if(! (++count % 5)) std::cout