42
A Crash Course in C++ The goal of this chapter is to cover briefly the most important parts of C++ so that you have a base of knowledge before embarking on the rest of the book. This chapter is not a comprehensive lesson in the C++ programming language. The very basic points (like what a program is and the differ- ence between = and ==) are not covered. The very esoteric points (remember what a union is? how about the volatile keyword?) are also omitted. Certain parts of the C language that are less rele- vant in C++ are also left out, as are parts of C++ that get in-depth coverage in later chapters. This chapter aims to cover the parts of C++ that programmers encounter on a daily basis. If you’ve been away from C++ for a while and you’ve forgotten the syntax for a for loop, you’ll find that in this chapter. If you’re fairly new to C++ and you don’t understand what a reference variable is, you’ll learn that here as well. If you already have significant experience with C++, skim this chapter to make sure that there aren’t any fundamental parts of the language on which you need to brush up. If you’re new to C++, take the time to read this chapter carefully and make sure that you understand the examples. If you need additional introductory information, consult the titles listed in Appendix B. The Basics of C++ The C++ language is often viewed as a “better C” or a “superset of C.” Many of the annoyances or rough edges of the C language were addressed when C++ was designed. Because C++ is based on C, much of the syntax you’ll see in this section will look familiar to you if are an experienced C programmer. The two languages certainly have their differences, though. As evidence, The C++ Programming Language by C++ creator Bjarne Stroustrup weighs in at 911 pages, while Kernighan and Ritchie’s The C Programming Language is a scant 274 pages. So if you’re a C programmer, be on the lookout for new or unfamiliar syntax! COPYRIGHTED MATERIAL

A Crash Course in C++ - Wiley › images › db › pdf › ... · The main function main()is, of course, where the program starts. An intis returned from main(), indicating the result

  • Upload
    others

  • View
    7

  • Download
    0

Embed Size (px)

Citation preview

Page 1: A Crash Course in C++ - Wiley › images › db › pdf › ... · The main function main()is, of course, where the program starts. An intis returned from main(), indicating the result

A Crash Course in C++

The goal of this chapter is to cover briefly the most important parts of C++ so that you have a baseof knowledge before embarking on the rest of the book. This chapter is not a comprehensive lessonin the C++ programming language. The very basic points (like what a program is and the differ-ence between = and ==) are not covered. The very esoteric points (remember what a union is? howabout the volatile keyword?) are also omitted. Certain parts of the C language that are less rele-vant in C++ are also left out, as are parts of C++ that get in-depth coverage in later chapters.

This chapter aims to cover the parts of C++ that programmers encounter on a daily basis. If you’vebeen away from C++ for a while and you’ve forgotten the syntax for a for loop, you’ll find that inthis chapter. If you’re fairly new to C++ and you don’t understand what a reference variable is,you’ll learn that here as well.

If you already have significant experience with C++, skim this chapter to make sure that therearen’t any fundamental parts of the language on which you need to brush up. If you’re new toC++, take the time to read this chapter carefully and make sure that you understand the examples.If you need additional introductory information, consult the titles listed in Appendix B.

The Basics of C++The C++ language is often viewed as a “better C” or a “superset of C.” Many of the annoyancesor rough edges of the C language were addressed when C++ was designed. Because C++ is basedon C, much of the syntax you’ll see in this section will look familiar to you if are an experiencedC programmer. The two languages certainly have their differences, though. As evidence, The C++Programming Language by C++ creator Bjarne Stroustrup weighs in at 911 pages, while Kernighanand Ritchie’s The C Programming Language is a scant 274 pages. So if you’re a C programmer, be onthe lookout for new or unfamiliar syntax!

04_574841 ch01.qxd 12/15/04 3:39 PM Page 1

COPYRIG

HTED M

ATERIAL

Page 2: A Crash Course in C++ - Wiley › images › db › pdf › ... · The main function main()is, of course, where the program starts. An intis returned from main(), indicating the result

The Obligatory Hello, WorldIn all its glory, the following code is the simplest C++ program you’re likely to encounter.

// helloworld.cpp

#include <iostream>

int main(int argc, char** argv){

std::cout << “Hello, World!” << std::endl;

return 0;}

This code, as you might expect, prints the message Hello, World! on the screen. It is a simple programand unlikely to win any awards, but it does exhibit several important concepts about the format of aC++ program.

CommentsThe first line of the program is a comment, a message that exists for the programmer only and is ignoredby the compiler. In C++, there are two ways to delineate a comment. In the preceding example, twoslashes indicate that whatever follows on that line is a comment.

// helloworld.cpp

The same behavior (this is to say, none) would be achieved by using a C-style comment, which is alsovalid in C++. C-style comments start with /* and end with */. In this fashion, C-style comments arecapable of spanning multiple lines. The code below shows a C-style comment in action (or, more appro-priately, inaction).

/* this is a multiline* C-style comment. The* compiler will ignore* it. */

Comments are covered in detail in Chapter 7.

Preprocessor DirectivesBuilding a C++ program is a three-step process. First, the code is run through a preprocessor, which recog-nizes metainformation about the code. Next, the code is compiled, or translated into machine-readableobject files. Finally, the individual object files are linked together into a single application. Directives thatare aimed at the preprocessor start with the # character, as in the line #include <iostream> in theprevious example. In this case, an include directive tells the preprocessor to take everything from theiostream header file and make it available to the current file. The most common use of header files is todeclare functions that will be defined elsewhere. Remember, a declaration tells the compiler how a func-tion is called. A definition contains the actual code for the function. The iostream header declares theinput and output mechanisms provided by C++. If the program did not include it, it would be unable toperform its only task of outputting text.

2

Chapter 1

04_574841 ch01.qxd 12/15/04 3:39 PM Page 2

Page 3: A Crash Course in C++ - Wiley › images › db › pdf › ... · The main function main()is, of course, where the program starts. An intis returned from main(), indicating the result

The table below shows some of the most common preprocessor directives.

Preprocessor Directive Functionality Common Uses

#include [file] The specified file is inserted into Almost always used to include the code at the location of the header files so that code can directive. make use of functionality that

is defined elsewhere.

#define [key] [value] Every occurrence of the specified Often used in C to define a key is replaced with the specified constant value or a macro. C++ value. provides a better mechanism

for constants. Macros are oftendangerous so #define is rarelyused in C++. See Chapter 12for details.

#ifdef [key] Code within the ifdef Used most frequently to protect #ifndef [key] (“if defined”) or ifndef against circular includes. Each #endif (“if not defined”) blocks are included file defines a value

conditionally included or initially and surrounds the rest omitted based on whether of its code with a #ifndef and the specified value has been #endif so that it won’t be defined with #define. included multiple times.

#pragma Varies from compiler to compiler. Because usage of #pragma is notOften allows the programmer to standard across compilers, we display a warning or error if the advocate not using it. directive is reached during preprocessing.

The main functionmain() is, of course, where the program starts. An int is returned from main(), indicating the resultstatus of the program. main() takes two parameters: argc gives the number of arguments passed to theprogram, and argv contains those arguments. Note that the first argument is always the name of theprogram itself.

I/O StreamsIf you’re new to C++ and coming from a C background, you’re probably wondering what std::cout isand what has been done with trusty old printf(). While printf() can still be used in C++, a muchbetter input/output facility is provided by the streams library.

In C, included files usually end in .h, such as <stdio.h>. In C++, the suffix is omit-ted for standard library headers, such as <iostream>. Your favorite standard head-ers from C still exist in C++, but with new names. For example, you can access thefunctionality from <stdio.h> by including <cstdio>.

3

A Crash Course in C++

04_574841 ch01.qxd 12/15/04 3:39 PM Page 3

Page 4: A Crash Course in C++ - Wiley › images › db › pdf › ... · The main function main()is, of course, where the program starts. An intis returned from main(), indicating the result

I/O streams are covered in depth in Chapter 14, but the basics of output are very simple. Think of anoutput stream as a laundry chute for data. Anything you toss into it will be output appropriately.std::cout is the chute corresponding to the user console, or standard out. There are other chutes,including std::cerr, which outputs to the error console. The << operator tosses data down the chute.In the preceding example, a quoted string of text is sent to standard out. Output streams allow multipledata of varying types to be sent down the stream sequentially on a single line of code. The followingcode outputs text, followed by a number, followed by more text.

std::cout << “There are “ << 219 << “ ways I love you.” << std::endl;

std::endl represents an end of line character. When the output stream encounters std::endl, it willoutput everything that has been sent down the chute so far and move to the next line. An alternate wayof representing the end of a line is by using the ‘\n’ character. The \n character is an escape character,which refers to a new-line character. Escape characters can be used within any quoted string of text. Thelist below shows the most common escape characters.

❑ \n new line

❑ \r carriage return

❑ \t tab

❑ \\ the backslash character

❑ \” quotation mark

Streams can also be used to accept input from the user. The simplest way to do this is to use the >> operator with an input stream. The std::cin input stream accepts keyboard input from the user.User input can be tricky because you can never know what kind of data the user will enter. SeeChapter 14 for a full explanation of how to use input streams.

NamespacesNamespaces address the problem of naming conflicts between different pieces of code. For example, youmight be writing some code that has a function called foo(). One day, you decide to start using a third-party library, which also has a foo() function. The compiler has no way of knowing which version offoo() you are referring to within your code. You can’t change the library’s function name, and it wouldbe a big pain to change your own.

Namespaces come to the rescue in such scenarios because you can define the context in which names aredefined. To place code in a namespace, simply enclose it within a namespace block:

// namespaces.h

namespace mycode {void foo();

}

4

Chapter 1

04_574841 ch01.qxd 12/15/04 3:39 PM Page 4

Page 5: A Crash Course in C++ - Wiley › images › db › pdf › ... · The main function main()is, of course, where the program starts. An intis returned from main(), indicating the result

The implementation of a method or function can also be handled in a namespace:

// namespaces.cpp

#include <iostream>#include “namespaces.h”

namespace mycode {

void foo() {std::cout << “foo() called in the mycode namespace” << std::endl;

}}

By placing your version of foo() in the namespace “mycode,” it is isolated from the foo() functionprovided by the third-party library. To call the namespace-enabled version of foo(), prepend thenamespace onto the function name as follows.

mycode::foo(); // Calls the “foo” function in the “mycode” namespace

Any code that falls within a “mycode” namespace block can call other code within the same namespacewithout explicitly prepending the namespace. This implicit namespace is useful in making the codemore precise and readable. You can also avoid prepending of namespaces with the using directive. Thisdirective tells the compiler that the subsequent code is making use of names in the specified namespace.The namespace is thus implied for the code that follows:

// usingnamespaces.cpp

#include “namespaces.h”

using namespace mycode;

int main(int argc, char** argv){

foo(); // Implies mycode::foo();}

A single source file can contain multiple using directives, but beware of overusing this shortcut. In theextreme case, if you declare that you’re using every namespace known to humanity, you’re effectivelyeliminating namespaces entirely! Name conflicts will again result if you are using two namespaces thatcontain the same names. It is also important to know in which namespace your code is operating so thatyou don’t end up accidentally calling the wrong version of a function.

You’ve seen the namespace syntax before — we used it in the Hello, World program. cout and endl areactually names defined in the std namespace. We could have rewritten Hello, World with the usingdirective as shown here:

5

A Crash Course in C++

04_574841 ch01.qxd 12/15/04 3:39 PM Page 5

Page 6: A Crash Course in C++ - Wiley › images › db › pdf › ... · The main function main()is, of course, where the program starts. An intis returned from main(), indicating the result

// helloworld.cpp

#include <iostream>

using namespace std;

int main(int argc, char** argv){

cout << “Hello, World!” << endl;

return 0;}

The using directive can also be used to refer to a particular item within a namespace. For example, if theonly part of the std namespace that you intend to use is cout, you can refer to it as follows:

using std::cout;

Subsequent code can refer to cout without prepending the namespace, but other items in the stdnamespace will still need to be explicit:

using std::cout;

cout << “Hello, World!” << std::endl;

VariablesIn C++, variables can be declared just about anywhere in your code and can be used anywhere in the cur-rent block below the line where they are declared. In practice, your engineering group should decidewhether variables will be declared at the start of each function or on an as-needed basis. Variables can bedeclared without being given a value. These undeclared variables generally end up with a semirandomvalue based on whatever is in memory at the time and are the source of countless bugs. Variables in C++can alternatively be assigned an initial value when they are declared. The code that follows shows bothflavors of variable declaration, both using ints, which represent integer values.

// hellovariables.cpp

#include <iostream>

using namespace std;

int main(int argc, char** argv){

int uninitializedInt;int initializedInt = 7;

cout << uninitializedInt << “ is a random value” << endl;cout << initializedInt << “ was assigned an initial value” << endl;

return (0);}

6

Chapter 1

04_574841 ch01.qxd 12/15/04 3:39 PM Page 6

Page 7: A Crash Course in C++ - Wiley › images › db › pdf › ... · The main function main()is, of course, where the program starts. An intis returned from main(), indicating the result

When run, this code will output a random value from memory for the first line and the number 7 for thesecond. This code also shows how variables can be used with output streams.

The table that follows shows the most common variable types used in C++.

Type Description Usage

int Positive and negative integers (range int i = 7;depends on compiler settings)

short Short integer (usually 2 bytes) short s = 13;

long Long integer (usually 4 bytes) long l = -7;

unsigned int Limits the preceding types to unsigned int i =2;unsigned short values >= 0 unsigned short s = 23;unsigned long unsigned long l = 5400;

float Floating-point and double precision float f = 7.2;double numbers double d = 7.2

char A single character char ch = ‘m’;

bool true or false (same as non-0 or 0) bool b = true;

Variables can be converted to other types by casting them. For example, an int can be cast to a bool.C++ provides three ways of explicitly changing the type of a variable. The first method is a holdoverfrom C, but is still the most commonly used. The second method seems more natural at first but is rarelyseen. The third method is the most verbose, but often considered the cleanest.

bool someBool = (bool)someInt; // method 1

bool someBool = bool(someInt); // method 2

bool someBool = static_cast<bool>(someInt); // method 3

The result will be false if the integer was 0 and true otherwise. In some contexts, variables can beautomatically cast, or coerced. For example, a short can be automatically converted into a long becausea long represents the same type of data with additional precision.

long someLong = someShort; // no explicit cast needed

When automatically casting variables, you need to be aware of the potential loss of data. For example,casting a float to an int throws away information (the fractional part of the number). Many compilers

C++ does not provide a basic string type. However, a standard implementation of astring is provided as part of the standard library as described later in this chapterand in Chapter 13.

7

A Crash Course in C++

04_574841 ch01.qxd 12/15/04 3:39 PM Page 7

Page 8: A Crash Course in C++ - Wiley › images › db › pdf › ... · The main function main()is, of course, where the program starts. An intis returned from main(), indicating the result

will issue a warning if you assign a float to an int without an explicit cast. If you are certain that theleft-hand-side type is fully compatible with the right-hand side type, it’s okay to cast implicitly.

OperatorsWhat good is a variable if you don’t have a way to change it? The table below shows the most commonoperators used in C++ and sample code that makes use of them. Note that operators in C++ can be binary(operate on two variables), unary (operate on a single variable), or even ternary (operate on three vari-ables). There is only one ternary operator in C++ and it is covered in the next section, “Conditionals.”

Operator Description Usage

= Binary operator to assign the value on the right to int ;the variable on the left. i = 3;

int j;j = i;

! Unary operator to negate the true/false (non-0/0) bool b = !true;status of a variable. bool b2 = !b;

+ Binary operator for addition. int i = 3 + 2;int j = i + 5;int k = i + j;

- Binary operators for subtraction, multiplication, int i = 5-1;* and division. int j = 5*2;/ int k = j / i;

% Binary operator for remainder of a division int remainder = 5 % 2;operation. Also referred to as the mod operator.

++ Unary operator to increment a variable by 1. If the i++;operator occurs before the variable, the result of ++i;the expression is the unincremented value. If the operator occurs after the variable, the result of the expression is the new value.

-- Unary operator to decrement a variable by 1. i--;--i;

+= Shorthand syntax for i = i + j i += j;

-= Shorthand syntax for i -= j;*= i = i – j; i *= j;/= i = i * j; i /= j;%= i = i / j; i %= j;

i = i % j;

& Takes the raw bits of one variable and performs a i = j & k;&= bitwise “and” with the other variable. j &= k;

| Takes the raw bits of one variable and performs a i = j | k;bitwise “or” with the other variable. j |= k;

8

Chapter 1

04_574841 ch01.qxd 12/15/04 3:39 PM Page 8

Page 9: A Crash Course in C++ - Wiley › images › db › pdf › ... · The main function main()is, of course, where the program starts. An intis returned from main(), indicating the result

Operator Description Usage

<< Takes the raw bits of a variable and “shifts” each i = i << 1;>> bit left (<<) or right (>>) the specified number of i = i >> 4;<<= places. i <<= 1;>>= i >>= 4;

^ Performs a bitwise “exclusive or” operation on i = i ^ j;^= the two arguments. i ^= j;

The following program shows the most common variable types and operators in action. If you’re unsureabout how variables and operators work, try to figure out what the output of this program will be, andthen run it to confirm your answer.

// typetest.cpp

#include <iostream>

using namespace std;

int main(int argc, char** argv){

int someInteger = 256;short someShort;long someLong;float someFloat;double someDouble;

someInteger++;someInteger *= 2;someShort = (short)someInteger;someLong = someShort * 10000;someFloat = someLong + 0.785;someDouble = (double)someFloat / 100000;

cout << someDouble << endl;}

The C++ compiler has a recipe for the order in which expressions are evaluated. If you have a compli-cated line of code with many operators, the order of execution may not be obvious. For that reason, it’sprobably better to break up a complicated statement into several smaller statements or explicitly groupexpressions using parentheses. For example, the following line of code is confusing unless you happento know the C++ operator precedence table by heart:

int i = 34 + 8 * 2 + 21 / 7 % 2;

Adding parentheses makes it clear which operations are happening first:

int i = 34 + (8 * 2) + ( (21 / 7) % 2 );

9

A Crash Course in C++

04_574841 ch01.qxd 12/15/04 3:39 PM Page 9

Page 10: A Crash Course in C++ - Wiley › images › db › pdf › ... · The main function main()is, of course, where the program starts. An intis returned from main(), indicating the result

Breaking up the statement into separate lines makes it even clearer:

int i = 8 * 2;int j = 21 / 7;j %= 2;i = 34 + i + j;

For those of you playing along at home, all three approaches are equivalent and end up with i equal to51. If you assumed that C++ evaluated expressions from left to right, your answer would have been 1.In fact, C++ evaluates /, *, and % first (in left to right order), followed by addition and subtraction, thenbitwise operators. Parenthesis let you explicitly tell the compiler that a certain operation should be eval-uated separately.

TypesIn C++, you can use the basic types (int, bool, etc.) to build more complex types of your own design.Once you are an experienced C++ programmer, you will rarely use the following techniques, which arefeatures brought in from C, because classes are far more powerful. Still, it is important to know aboutthe two most common ways of building types so that you will recognize the syntax.

Enumerated TypesAn integer really represents a value within a sequence — the sequence of numbers. Enumerated typeslet you define your own sequences so that you can declare variables with values in that sequence. Forexample, in a chess program, you could represent each piece as an int, with constants for the piecetypes, as shown in the following code. The integers representing the types are marked const to indicatethat they can never change.

const int kPieceTypeKing = 0;const int kPieceTypeQueen = 1;const int kPieceTypeRook = 2;const int kPieceTypePawn = 3;//etc.

int myPiece = kPieceTypeKing;

This representation is fine, but it can become dangerous. Since the piece is just an int, what wouldhappen if another programmer added code to increment the value of the piece? By adding one, a kingbecomes a queen, which really makes no sense. Worse still, someone could come in and give a piece avalue of -1, which has no corresponding constant.

Enumerated types resolve these problems by tightly defining the range of values for a variable. The fol-lowing code declares a new type, PieceT, that has four possible values, representing four of the chesspieces.

typedef enum { kPieceTypeKing, kPieceTypeQueen, kPieceTypeRook,kPieceTypePawn

} PieceT;

10

Chapter 1

04_574841 ch01.qxd 12/15/04 3:39 PM Page 10

Page 11: A Crash Course in C++ - Wiley › images › db › pdf › ... · The main function main()is, of course, where the program starts. An intis returned from main(), indicating the result

Behind the scenes, an enumerated type is just an integer value. The real value of kPieceTypeKing iszero. However, by defining the possible values for variables of type PieceT, your compiler can give youa warning or error if you attempt to perform arithmetic on PieceT variables or treat them as integers.The following code, which declares a PieceT variable then attempts to use it as an integer, results in awarning on most compilers.

PieceT myPiece;

myPiece = 0;

StructsStructs let you encapsulate one or more existing types into a new type. The classic example of a struct isa database record. If you are building a personnel system to keep track of employee information, youwill need to store the first initial, last initial, middle initial, employee number, and salary for eachemployee. A struct that contains all of this information is shown in the header file that follows.

// employeestruct.h

typedef struct {char firstInitial;char middleInitial;char lastInitial;int employeeNumber;int salary;

} EmployeeT;

A variable declared with type EmployeeT will have all of these fields built-in. The individual fields of astruct can be accessed by using the “.” character. The example that follows creates and then outputs therecord for an employee.

// structtest.cpp

#include <iostream>#include “employeestruct.h”

using namespace std;

int main(int argc, char** argv){

// Create and populate an employee.EmployeeT anEmployee;

anEmployee.firstInitial = ‘M’;anEmployee.middleInitial = ‘R’;anEmployee.lastInitial = ‘G’;anEmployee.employeeNumber = 42;anEmployee.salary = 80000;

// Output the values of an employee.

11

A Crash Course in C++

04_574841 ch01.qxd 12/15/04 3:39 PM Page 11

Page 12: A Crash Course in C++ - Wiley › images › db › pdf › ... · The main function main()is, of course, where the program starts. An intis returned from main(), indicating the result

cout << “Employee: “ << anEmployee.firstInitial << anEmployee.middleInitial <<anEmployee.lastInitial << endl;

cout << “Number: “ << anEmployee.employeeNumber << endl;cout << “Salary: $” << anEmployee.salary << endl;

return 0;}

ConditionalsConditionals let you execute code based on whether or not something is true. There are three main typesof conditionals in C++.

If/Else StatementsThe most common conditional is the if statement, which can be accompanied by else. If the conditiongiven inside the if statement is true, the line or block of code is executed. If not, execution continues tothe else case if present, or to the code following the conditional. The following pseudocode shows a cas-cading if statement, a fancy way of saying that the if statement has an else statement that in turn hasanother if statement, and so on.

if (i > 4) {// Do something.

} else if (i > 2) {// Do something else.

} else {// Do something else.

}

The expression between the parentheses of an if statement must be a Boolean value or evaluate to aBoolean value. Conditional operators, described below, provide ways of evaluating expressions to resultin a true or false Boolean value.

Switch StatementsThe switch statement is an alternate syntax for performing actions based on the value of a variable. Inswitch statements, the variable must be compared to a constant, so the greater-than if statementsabove could not be converted to switch statements. Each constant value represents a “case”. If the vari-able matches the case, the subsequent lines of code are executed until the break statement is reached.You can also provide a default case, which is matched if none of the other cases match.

switch statements are generally used when you want to do something based on the specific value of avariable, as opposed to some test on the variable. The following pseudocode shows a common use of theswitch statement.

switch (menuItem) {case kOpenMenuItem:

// Code to open a filebreak;

12

Chapter 1

04_574841 ch01.qxd 12/15/04 3:39 PM Page 12

Page 13: A Crash Course in C++ - Wiley › images › db › pdf › ... · The main function main()is, of course, where the program starts. An intis returned from main(), indicating the result

case kSaveMenuItem:// Code to save a filebreak;

default:// Code to give an error messagebreak;

}

If you omit the break statement, the code for the subsequent case will be executed whether or not itmatches. This is sometimes useful, but more frequently a source of bugs.

The Ternary OperatorC++ has one operator that takes three arguments, known as the ternary operator. It is used as a shorthandconditional expression of the form “if [something] then [perform action], otherwise [perform some otheraction]”. The ternary operator is represented by a ? and a :. The following code will output “yes” if thevariable i is greater than 2, and “no” otherwise.

std::cout << ((i > 2) ? “yes” : “no”);

The advantage of the ternary operator is that it can occur within almost any context. In the precedingexample, the ternary operator is used within code that performs output. A convenient way to rememberhow the syntax is used is to treat the question mark as though the statement that comes before it really isa question. For example, “Is i greater than 2? If so, the result is ‘yes’: if not, the result is ‘no.’”

Unlike an if statement or a switch statement, the ternary operator doesn’t execute code based on theresult. Instead, it is used within code, as shown in the preceding example. In this way, it really is an oper-ator (like + and -) as opposed to a true conditional, such as if and switch.

Conditional OperatorsYou have already seen a conditional operator without a formal definition. The > operator compares twovalues. The result is “true” if the value on the left is greater than the value on the right. All conditionaloperators follow this pattern — they all result in a true or false.

The table below shows other common conditional operators.

Operator Description Usage

< Determines if the left-hand side if (i <= 0) {<= is less than, less than or equal to, std::cout << “i is negative”;> greater than,or greater than or }>= equal to the right-hand side.

== Determines if the left-hand side if (i == 3) {equals the right-hand side. std::cout << “i is 3”;Don’t confuse this with the }= (assignment) operator!

Table continued on following page

13

A Crash Course in C++

04_574841 ch01.qxd 12/15/04 3:39 PM Page 13

Page 14: A Crash Course in C++ - Wiley › images › db › pdf › ... · The main function main()is, of course, where the program starts. An intis returned from main(), indicating the result

Operator Description Usage

!= Not equals. The result of if (i != 3) {the statement is true if the std::cout << “i is not 3”;left-hand side does not }equal the right-hand side.

! Logical not. Negates the if (!someBoolean) {true/false status of a std::cout << “someBoolean is false”;Boolean expression. }This is a unary operator.

&& Logical and. The result if (someBoolean && someOtherBoolean) {is true if both parts of the std::cout << “both are true”;expression are true. }

|| Logical or. The result is if (someBoolean || someOtherBoolean) {true if either part of the std::cout << “at least one is true”;expression is true. }

C++ uses short-circuit logic when evaluating an expression. That means that once the final result is cer-tain, the rest of the expression won’t be evaluated. For example, if you are doing a logical or of severalBoolean expressions as shown below, the result is known to be true as soon as one of them is found to betrue. The rest won’t even be checked.

bool result = bool1 || bool2 || (i > 7) || (27 / 13 % i + 1) < 2;

In the example above, if bool1 is found to be true, the entire expression must be true, so the other partsaren’t evaluated. In this way, the language saves your code from doing unnecessary work. It can, how-ever, be a source of hard-to-find bugs if the later expressions in some way influence the state of the pro-gram (for example, by calling a separate function). The following code shows a statement using && thatwill short-circuit after the second term because 1 always evaluates to true.

bool result = bool1 && 1 && (i > 7) && !done;

LoopsComputers are great for doing the same thing over and over. C++ provides three types of loopingstructures.

The While Loopwhile loops let you perform a block of code repeatedly as long as an expression evaluates to true. Forexample, the following completely silly code will output “This is silly.” five times.

int i = 0;while (i < 5) {

std::cout << “This is silly.” << std::endl;i++;

}

14

Chapter 1

04_574841 ch01.qxd 12/15/04 3:39 PM Page 14

Page 15: A Crash Course in C++ - Wiley › images › db › pdf › ... · The main function main()is, of course, where the program starts. An intis returned from main(), indicating the result

The keyword break can be used within a loop to immediately get out of the loop and continue execu-tion of the program. The keyword continue can be used to return to the top of the loop and reevaluatethe while expression. Both are often considered poor style because they cause the execution of a pro-gram to jump around somewhat haphazardly.

The Do/While LoopC++ also has a variation on the while loop called do/while. It works similarly to the while loop,except that the code to be executed comes first, and the conditional check for whether or not to continuehappens at the end. In this way, you can use a loop when you want a block of code to always be exe-cuted at least once and possibly additional times based on some condition. The example that followswill output “This is silly.” once even though the condition will end up being false.

int i = 100;do {

std::cout << “This is silly.” << std::endl;i++;

} while (i < 5);

The For LoopThe for loop provides another syntax for looping. Any for loop can be converted to a while loop andvice versa. However, the for loop syntax is often more convenient because it looks at a loop in terms ofa starting expression, an ending condition, and a statement to execute at the end of every iteration. In thefollowing code, i is initialized to 0, the loop will continue as long as i is less than 5, and at the end ofevery iteration, i is incremented by 1. This code does the same thing as the while loop example, but tosome programmers, it is easier to read because the starting value, ending condition, and per-iterationstatement are all visible on one line.

for (int i = 0; i < 5; i++) {std::cout << “This is silly.” << std::endl;

}

ArraysArrays hold a series of values, all of the same type, each of which can be accessed by its position in thearray. In C++, you must provide the size of the array when the array is declared. You cannot give a vari-able as the size — it must be a constant value. The code that follows shows the declaration of an array of10 integers followed by a for loop that initializes each integer to zero.

int myArray[10];

for (int i = 0; i < 10; i++) {myArray[i] = 0;

}

15

A Crash Course in C++

04_574841 ch01.qxd 12/15/04 3:39 PM Page 15

Page 16: A Crash Course in C++ - Wiley › images › db › pdf › ... · The main function main()is, of course, where the program starts. An intis returned from main(), indicating the result

The preceding example shows a one-dimensional array, which you can think of as a line of integers, eachwith its own numbered compartment. C++ allows multidimensional arrays. You might think of a two-dimensional array as a checkerboard, where each location has a position along the x-axis and a positionalong the y-axis. Three-dimensional and higher arrays are harder to picture and are rarely used. Thecode below shows the syntax for allocating a two-dimensional array of characters for a Tic-Tac-Toe boardand then putting an “o” in the center square.

char ticTacToeBoard[3][3];

ticTacToeBoard[1][1] = ‘o’;

Figure 1-1 shows a visual representation of this board with the position of each square.

Figure 1-1

FunctionsFor programs of any significant size, placing all the code inside of main() is unmanageable. To makeprograms easy to understand, you need to break up, or decompose, code into concise functions.

In C++, you first declare a function to make it available for other code to use. If the function is usedinside a particular file of code, you generally declare and define the function in the source file. If thefunction is for use by other modules or files, you generally put the declaration in a header file and thedefinition in a source file.

In C++, the first element of an array is always at position 0, not position 1! The lastposition of the array is always the size of the array minus 1!

ticTacToeBoard[0][0] ticTacToeBoard[0][1] ticTacToeBoard[0][2]

ticTacToeBoard[1][0] ticTacToeBoard[1][1] ticTacToeBoard[1][2]

ticTacToeBoard[2][0] ticTacToeBoard[2][1] ticTacToeBoard[2][2]

16

Chapter 1

04_574841 ch01.qxd 12/15/04 3:39 PM Page 16

Page 17: A Crash Course in C++ - Wiley › images › db › pdf › ... · The main function main()is, of course, where the program starts. An intis returned from main(), indicating the result

A function declaration is shown below. This example has a return type of void, indicating that the func-tion does not provide a result to the caller. The caller must provide two arguments for the function towork with — an integer and a character.

void myFunction(int i, char c);

Without an actual definition to match this function declaration, the link stage of the compilation processwill fail because code that makes use of the function myFunction() will be calling nonexistent code.The following definition simply prints the values of the two parameters.

void myFunction(int i, char c){

std::cout << “the value of i is “ << i << std::endl;std::cout << “the value of c is “ << c << std::endl;

}

Elsewhere in the program, you can make calls to myFunction() and pass in constants or variables forthe two parameters. Some sample function calls are shown here:

myFunction(8, ‘a’);myFunction(someInt, ‘b’);myFunction(5, someChar);

C++ functions can also return a value to the caller. The following function declaration and definition isfor a function that adds two numbers and returns the result.

int addNumbers(int number1, int number2);

int addNumbers(int number1, int number2) {

int result = number1 + number2;return (result);

}

Those Are the BasicsAt this point, you have reviewed the basic essentials of C++ programming. If this section was a breeze,skim the next section to make sure that you’re up to speed on the more advanced material. If you

In C++, unlike C, a function that takes no parameters just has an empty parameterlist. It is not necessary to use “void” to indicate that no parameters are taken.However, you should still use “void” to indicate when no value is returned.

Function declarations are often called “function prototypes” or “signatures” toemphasize that they represent how the function can be accessed, but not the codebehind it.

17

A Crash Course in C++

04_574841 ch01.qxd 12/15/04 3:39 PM Page 17

Page 18: A Crash Course in C++ - Wiley › images › db › pdf › ... · The main function main()is, of course, where the program starts. An intis returned from main(), indicating the result

struggled with this section, you may want to obtain one of the fine introductory C++ books mentionedin Appendix D before continuing.

Diving Deeper into C++Loops, variables, and conditionals are terrific building blocks, but there is much more to learn. The top-ics covered next include many features that are designed to help C++ programmers with their code aswell as a few features that are often more confusing than helpful. If you are a C programmer with littleC++ experience, you should read this section carefully.

Pointers and Dynamic MemoryDynamic memory allows you to build programs with data that is not of fixed size at compile time. Mostnontrivial programs make use of dynamic memory in some form.

The Stack and the HeapMemory in your C++ application is divided into two parts — the stack and the heap. One way to visual-ize the stack is as a deck of cards. The current top card represents the current scope of the program, usu-ally the function that is currently being executed. All variables declared inside the current function willtake up memory in the top stack frame, the top card of the deck. If the current function, which we’ll callfoo() calls another function bar(), a new card is put on the deck so that bar() has its own stack frameto work with. Any parameters passed from foo() to bar() are copied from the foo() stack frame intothe bar() stack frame. The mechanics of parameter passing and stack frames are covered in Chapter 13.Figure 1-2 shows what the stack might look like during the execution of a hypothetical function foo()that has declared two integer values.

Figure 1-2

Stack frames are nice because they provide an isolated memory workspace for each function. If a vari-able is declared inside the foo() stack frame, calling the bar() function won’t change it unless youspecifically tell it to. Also, when the foo() function is done running, the stack frame goes away, and allof the variables declared within the function no longer take up memory.

The heap is an area of memory that is completely independent of the current function or stack frame.You can put variables on the heap if you want them to exist even when the function in which they weredeclared has completed. The heap is less structured than the stack. You can think of it as just a pile ofbits. Your program can add new bits to the pile at any time or modify bits that are already in the pile.

int i

int j

7

11

foo()

main()

18

Chapter 1

04_574841 ch01.qxd 12/15/04 3:39 PM Page 18

Page 19: A Crash Course in C++ - Wiley › images › db › pdf › ... · The main function main()is, of course, where the program starts. An intis returned from main(), indicating the result

Dynamically Allocated ArraysDue to the way that the stack works, the compiler must be able to determine at compile time how bigeach stack frame will be. Since the stack frame size is predetermined, you cannot declare an array with avariable size. The following code will not compile because the arraySize is a variable, not a constant.

int arraySize = 8;int myVariableSizedArray[arraySize]; // This won’t compile!

Because the entire array must go on the stack, the compiler needs to know exactly what size it will be sovariables aren’t allowed. However, it is possible to specify the size of an array at run time by usingdynamic memory and placing the array in the heap instead of the stack.

To allocate an array dynamically, you first need to declare a pointer:

int* myVariableSizedArray;

The * after the int type indicates that the variable you are declaring refers to some integer memory inthe heap. Think of the pointer as an arrow that points at the dynamically allocated heap memory. It doesnot yet point to anything specific because you haven’t assigned it to anything; it is an uninitializedvariable.

To initialize the pointer to new heap memory, you use the new command:

myVariableSizedArray = new int[arraySize];

This allocates memory for enough integers to satisfy the arraySize variable. Figure 1-3 shows what thestack and the heap both look like after this code is executed. As you can see, the pointer variable stillresides on the stack, but the array that was dynamically created lives on the heap.

Figure 1-3

Stack

myVariableSizedArray

Heap

myVariableSizedArray[0]myVariableSizedArray[1]myVariableSizedArray[2]myVariableSizedArray[3]myVariableSizedArray[4]myVariableSizedArray[5]myVariableSizedArray[6]myVariableSizedArray[7]

Some C++ compilers actually do support the preceding declaration, but is not cur-rently a part of the C++ specification. Most compilers offer a “strict” mode that willturn off these nonstandard extensions to the language.

19

A Crash Course in C++

04_574841 ch01.qxd 12/15/04 3:39 PM Page 19

Page 20: A Crash Course in C++ - Wiley › images › db › pdf › ... · The main function main()is, of course, where the program starts. An intis returned from main(), indicating the result

Now that the memory has been allocated, you can work with myVariableSizedArray as though itwere a regular stack-based array:

myVariableSizedArray[3] = 2;

When your code is done with the array, it should remove it from the heap so that other variables can usethe memory. In C++, you use the delete command to do this.

delete[] myVariableSizedArray;

The brackets after delete indicate that you are deleting an array.

Working with PointersThere are other reasons to use heap memory besides dynamically allocating arrays. You can put anyvariable in the heap by using a similar syntax:

int* myIntegerPointer = new int;

In this case, the pointer points to just a single integer value. To access this value, you need to dereferencethe pointer. Think of dereferencing as following the pointer’s arrow to the actual value in the heap. Toset the value of the newly allocated heap integer, you would use code like the following:

*myIntegerPointer = 8;

Notice that this is not the same as setting myIntegerPointer to the value 8. You are not changing thepointer, you are changing the memory that it points to. If you were to reassign the pointer value, itwould point to the memory address 8, which is probably random garbage that will eventually makeyour program crash.

Pointers don’t always point to heap memory. You can declare a pointer that points to a variable on thestack, even another pointer. To get a pointer to a variable, you use the & “address of” operator:

int i = 8;int* myIntegerPointer = &i; // Points to the variable with the value 8

C++ has a special syntax for dealing with pointers to structures. Technically, if you have a pointer to astructure, you can access its fields by first dereferencing it with *, then using the normal . syntax, as inthe code that follows, which assumes the existence of a function called getEmployee().

EmployeeT* anEmployee = getEmployee();

cout << (*anEmployee).salary << endl;

The C++ commands new and delete are similar to malloc() and free() from C.The syntax of new and delete is simpler because you don’t need to know how manybytes of memory are required.

20

Chapter 1

04_574841 ch01.qxd 12/15/04 3:39 PM Page 20

Page 21: A Crash Course in C++ - Wiley › images › db › pdf › ... · The main function main()is, of course, where the program starts. An intis returned from main(), indicating the result

This syntax is a little messy. The -> (arrow) operator lets you perform both the dereference and the fieldaccess in one step. The following code is equivalent to the preceding code, but is easier to read.

EmployeeT* anEmployee = getEmployee();

cout << anEmployee->salary << endl;

Normally, when you pass a variable into a function, you are passing by value. If a function takes an inte-ger parameter, it is really a copy of the integer that you pass in. Pointers to stack variables are often usedin C to allow functions to modify variables in other stack frames, essentially passing by reference. Bydereferencing the pointer, the function can change the memory that represents the variable even thoughthat variable isn’t in the current stack frame. This is less common in C++ because C++ has a better mech-anism, called references, which is covered below.

Strings in C++There are three ways to work with strings of text in C++. There is the C-style, which represents strings asarrays of characters; the C++ style, which wraps that representation in an easier-to-use string type; andthe general class of nonstandard approaches.

C-Style StringsA string of text like “Hello, World” is internally represented as an array of characters with the character‘\0’ representing the end of the string. As you’ve seen, arrays and pointers are sometimes related. Youcould use either one to represent a string, as shown here:

char arrayString[20] = “Hello, World”;char* pointerString = “Hello, World”;

For the arrayString, the compiler allocates space for 20 characters on the stack. The first 13 charactersin the array are filled in with ‘H’, ‘e’, etc., ending with the character ‘\0’. The characters in positions13 to 19 contain whatever random values happen to be in memory. The ‘\0’ character tells code thatuses the string where the content of the string ends. Even though the array has a length of 20, functionsthat process or output the string should ignore everything after the ‘\0’ character.

For the pointerString, the compiler allocates enough memory on the stack just to hold the pointer.The pointer points to an area of memory that the compiler has set aside to hold the constant string“Hello, World.” In this string, there is also a ‘\0’ character after the ‘d’ character.

The C language provides a number of standard functions for working with strings, which are describedin the <cstring> header file. The details of the standard library are not covered here because C++ pro-vides a much cleaner and simpler way of working with strings.

C++ StringsC-style strings are important to understand because they are still frequently used by C++ programmers.However, C++ includes a much more flexible string type. The string type, described by the <string>header file, acts just like a basic type. Just like I/O streams, the string type lives in the “std” package.The example that follows shows how strings can be used just like character arrays.

21

A Crash Course in C++

04_574841 ch01.qxd 12/15/04 3:39 PM Page 21

Page 22: A Crash Course in C++ - Wiley › images › db › pdf › ... · The main function main()is, of course, where the program starts. An intis returned from main(), indicating the result

// stringtest.cpp

#include <string>#include <iostream>

using namespace std;

int main(int argc, char** argv){

string myString = “Hello, World”;

cout << “The value of myString is “ << myString << endl;

return 0;}

The magic of C++ strings is that you can use standard operators to work with them. Instead of using afunction, like strcat() in C to concatenate two strings, you can simply use +. If you’ve ever tried to usethe == operator to compare two C-style strings, you’ve discovered that it doesn’t work. == when used onC-style strings is actually comparing the address of the character arrays, not their contents. With C++strings, == actually compares two strings. The example that follows shows some of the standard opera-tors in use with C++ strings.

// stringtest2.cpp

#include <string>#include <iostream>

using namespace std;

int main(int argc, char** argv){

string str1 = “Hello”;string str2 = “World”;string str3 = str1 + “ “ + str2;

cout << “str1 is “ << str1 << endl;cout << “str2 is “ << str2 << endl;cout << “str3 is “ << str3 << endl;

if (str3 == “Hello World”) {cout << “str3 is what it should be.” << endl;

} else {cout << “Hmmm . . . str3 isn’t what it should be.” << endl;

}

return (0);}

The preceding examples show just a few of the many features of C++ strings. Chapter 13 goes into fur-ther detail.

22

Chapter 1

04_574841 ch01.qxd 12/15/04 3:39 PM Page 22

Page 23: A Crash Course in C++ - Wiley › images › db › pdf › ... · The main function main()is, of course, where the program starts. An intis returned from main(), indicating the result

Nonstandard StringsThere are several reasons why many C++ programmers don’t use C++-style strings. Some programmerssimply aren’t aware of the string type because it was not always part of the C++ specification. Othershave discovered over the years that the C++ string doesn’t provide the behavior they need and havedeveloped their own string type. Perhaps the most common reason is that development frameworks andoperating systems tend to have their own way of representing strings, such as the CString class inMicrosoft’s MFC. Often, this is for backward compatibility or legacy issues. When starting a project inC++, it is very important to decide ahead of time how your group will represent strings.

ReferencesThe pattern for most functions is that they take in zero or more parameters, do some calculations, andreturn a single result. Sometimes, however, that pattern is broken. You may be tempted to return twovalues or you may want the function to be able to change the value of one of the variables that werepassed in.

In C, the primary way to accomplish such behavior is to pass in a pointer to the variable instead of thevariable itself. The only problem with this approach is that it brings the messiness of pointer syntax intowhat is really a simple task. In C++, there is an explicit mechanism for “pass-by-reference.” Attaching &to a type indicates that the variable is a reference. It is still used as though it was a normal variable, butbehind the scenes, it is really a pointer to the original variable. Below are two implementations of anaddOne() function. The first will have no effect on the variable that is passed in because it is passed byvalue. The second uses a reference and thus changes the original variable.

void addOne(int i){

i++; // Has no real effect because this is a copy of the original}

void addOne(int& i){

i++; // Actually changes the original variable}

The syntax for the call to the addOne() function with an integer reference is no different than if the func-tion just took an integer.

int myInt = 7;addOne(myInt);

ExceptionsC++ is a very flexible language, but not a particularly safe one. The compiler will let you write codethat scribbles on random memory addresses or tries to divide by zero (computers don’t deal well withinfinity). One of the language features that attempts to add a degree of safety back to the language isexceptions.

23

A Crash Course in C++

04_574841 ch01.qxd 12/15/04 3:39 PM Page 23

Page 24: A Crash Course in C++ - Wiley › images › db › pdf › ... · The main function main()is, of course, where the program starts. An intis returned from main(), indicating the result

An exception is an unexpected situation. For example, if you are writing a function that retrieves a Webpage, several things could go wrong. The Internet host that contains the page might be down, the pagemight come back blank, or the connection could be lost. In many programming languages, you wouldhandle this situation by returning a special value from the function, such as the NULL pointer. Exceptionsprovide a much better mechanism for dealing with problems.

Exceptions come with some new terminology. When a piece of code detects an exceptional situation, itthrows an exception. Another piece of code catches the exception and takes appropriate action. The fol-lowing example shows a function, divideNumbers(), that throws an exception if the caller passes in adenominator of zero.

#include <stdexcept>

double divideNumbers(double inNumerator, double inDenominator){

if (inDenominator == 0) {throw std::exception();

}

return (inNumerator / inDenominator);}

When the throw line is executed, the function will immediately end without returning a value. If thecaller surrounds the function call with a try-catch block, as shown in the following code, it will receivethe exception and be able to handle it.

#include <iostream>#include <stdexcept>

int main(int argc, char** argv) {

try {std::cout << divideNumbers(2.5, 0.5) << std::endl;std::cout << divideNumbers(2.3, 0) << std::endl;

} catch (std::exception exception) { std::cout << “An exception was caught!” << std::endl;

}}

The first call to divideNumbers() executes successfully, and the result is output to the user. The secondcall throws an exception. No value is returned, and the only output is the error message that is printedwhen the exception is caught. The output for the preceding block of code is:

5An exception was caught!

Exceptions can get tricky in C++. To use exceptions properly, you need to understand what happens tothe stack variables when an exception is thrown, and you have to be careful to properly catch and han-dle the necessary exceptions. The preceding example used the built-in std::exception exception type,but it is preferable to write your own exception types that are more specific to the error being thrown.Unlike the Java language, the C++ compiler doesn’t force you to catch every exception that might occur.

24

Chapter 1

04_574841 ch01.qxd 12/15/04 3:39 PM Page 24

Page 25: A Crash Course in C++ - Wiley › images › db › pdf › ... · The main function main()is, of course, where the program starts. An intis returned from main(), indicating the result

If your code never catches any exceptions but an exception is thrown, it will be caught by the programitself, which will be terminated. These trickier aspects of exceptions are covered in much more detail inChapter 15

The Many Uses of constThe keyword const can be used in several different ways in C++. All of its uses are related, but there aresubtle differences. One of the authors has discovered that the subtleties of const make for excellentinterview questions! In Chapter 12, you will learn all of the ways that const can be used. The followingsections outline the most frequent uses.

Const ConstantsIf you assumed that the keyword const has something to do with constants, you have correctly uncov-ered one of its uses. In the C language, programmers often use the preprocessor #define mechanism todeclare symbolic names for values that won’t change during the execution of the program, such as theversion number. In C++, programmers are encouraged to avoid #define in favor of using const todefine constants. Defining a constant with const is just like defining a variable, except that the compilerguarantees that code cannot change the value.

const float kVersionNumber = “2.0”;const string kProductName = “Super Hyper Net Modulator”;

Const to Protect VariablesIn C++, you can cast a non-const variable to a const variable. Why would you want to do this? Itoffers some degree of protection from other code changing the variable. If you are calling a function thata coworker of yours is writing, and you want to ensure that the function doesn’t change the value of aparameter you pass in, you can tell your coworker to have the function take a const parameter. If thefunction attempts to change the value of the parameter, it will not compile.

In the following code, a char* is automatically cast to a const char* in the call tomysteryFunction(). If the author of mysteryFunction() attempts to change the values within thecharacter array, the code will not compile. There are actually ways around this restriction, but usingthem requires conscious effort. C++ only protects against accidentally changing const variables.

// consttest.cppvoid mysteryFunction(const char* myString);

int main(int argc, char** argv){

char* myString = new char[2];myString[0] = ‘a’;myString[1] = ‘\0’;

mysteryFunction(myString);

return (0);}

25

A Crash Course in C++

04_574841 ch01.qxd 12/15/04 3:39 PM Page 25

Page 26: A Crash Course in C++ - Wiley › images › db › pdf › ... · The main function main()is, of course, where the program starts. An intis returned from main(), indicating the result

Const ReferencesYou will often find code that uses const reference parameters. At first, that seems like a contradiction.Reference parameters allow you to change the value of a variable from within another context. constseems to prevent such changes.

The main value in const reference parameters is efficiency. When you pass a variable into a function,an entire copy is made. When you pass a reference, you are really just passing a pointer to the originalso the computer doesn’t need to make the copy. By passing a const reference, you get the best of bothworlds — no copy is made but the original variable cannot be changed.

const references become more important when you are dealing with objects because they can be largeand making copies of them can have unwanted side effects. Subtle issues like this are covered inChapter 12.

C++ as an Object-Oriented LanguageIf you are a C programmer, you may have viewed the features covered so far in this chapter as convenientadditions to the C language. As the name C++ implies, in many ways the language is just a “better C.”There is one major point that this view overlooks. Unlike C, C++ is an object-oriented language.

Object-oriented programming (OOP) is a very different, arguably more natural, way to write code.If you are used to procedural languages such as C or Pascal, don’t worry. Chapter 3 covers all the back-ground information you need to know to shift your mindset to the object-oriented paradigm. If youalready know the theory of OOP, the rest of this section will get you up to speed (or refresh your mem-ory) on basic C++ object syntax.

Declaring a ClassA class defines the characteristics of an object. It is somewhat analogous to a struct except a class definesbehaviors in addition to properties. In C++, classes are usually declared in a header file and fullydefined in a corresponding source file.

A basic class definition for an airline ticket class is shown below. The class can calculate the price of theticket based on the number of miles in the flight and whether or not the customer is a member of the“Elite Super Rewards Program.” The definition begins by declaring the class name. Inside a set of curlybraces, the data members (properties) of the class and its methods (behaviors) are declared. Each datamember and method is associated with a particular access level: public, protected, or private. Theselabels can occur in any order and can be repeated.

// AirlineTicket.h

#include <string>

class AirlineTicket{

public:AirlineTicket();

26

Chapter 1

04_574841 ch01.qxd 12/15/04 3:39 PM Page 26

Page 27: A Crash Course in C++ - Wiley › images › db › pdf › ... · The main function main()is, of course, where the program starts. An intis returned from main(), indicating the result

~AirlineTicket();

int calculatePriceInDollars();

std::string getPassengerName();void setPassengerName(std::string inName);int getNumberOfMiles();void setNumberOfMiles(int inMiles);bool getHasEliteSuperRewardsStatus();void setHasEliteSuperRewardsStatus(bool inStatus);

private:std::string mPassengerName;int mNumberOfMiles;bool fHasEliteSuperRewardsStatus;

};

The method that has the same name of the class with no return type is a constructor. It is automaticallycalled when an object of the class is created. The method with a tilde (~) character followed by the classname is a destructor. It is automatically called when the object is destroyed.

The sample program that follows makes use of the class declared in the previous example. This exampleshows the creation of a stack-based AirlineTicket object as well as a heap-based object.

// AirlineTicketTest.cpp

#include <iostream>#include “AirlineTicket.h”

using namespace std;

int main(int argc, char** argv){

AirlineTicket myTicket; // Stack-based AirlineTicket

myTicket.setPassengerName(“Sherman T. Socketwrench”);myTicket.setNumberOfMiles(700);int cost = myTicket.calculatePriceInDollars();cout << “This ticket will cost $” << cost << endl;

AirlineTicket* myTicket2; // Heap-based AirlineTicket

myTicket2 = new AirlineTicket(); // Allocate a new objectmyTicket2->setPassengerName(“Laudimore M. Hallidue”);myTicket2->setNumberOfMiles(2000);myTicket2->setHasEliteSuperRewardsStatus(true);int cost2 = myTicket2->calculatePriceInDollars();cout << “This other ticket will cost $” << cost2 << endl;delete myTicket2;

return 0;}

27

A Crash Course in C++

04_574841 ch01.qxd 12/15/04 3:39 PM Page 27

Page 28: A Crash Course in C++ - Wiley › images › db › pdf › ... · The main function main()is, of course, where the program starts. An intis returned from main(), indicating the result

The definitions of the AirlineTicket class methods are shown below.

// AirlineTicket.cpp

#include <iostream>#include “AirlineTicket.h”

using namespace std;

AirlineTicket::AirlineTicket(){

// Initialize data membersfHasEliteSuperRewardsStatus = false; mPassengerName = “Unknown Passenger”;mNumberOfMiles = 0;

}

AirlineTicket::~AirlineTicket(){

// Nothing much to do in terms of cleanup}

int AirlineTicket::calculatePriceInDollars(){

if (getHasEliteSuperRewardsStatus()) {// Elite Super Rewards customers fly for free!return 0;

}

// The cost of the ticket is the number of miles times// 0.1. Real airlines probably have a more complicated formula!return static_cast<int>((getNumberOfMiles() * 0.1));

}

string AirlineTicket::getPassengerName(){

return mPassengerName;}

void AirlineTicket::setPassengerName(string inName){

mPassengerName = inName;}

int AirlineTicket::getNumberOfMiles(){

return mNumberOfMiles;}

void AirlineTicket::setNumberOfMiles(int inMiles){

mNumberOfMiles = inMiles;}

28

Chapter 1

04_574841 ch01.qxd 12/15/04 3:39 PM Page 28

Page 29: A Crash Course in C++ - Wiley › images › db › pdf › ... · The main function main()is, of course, where the program starts. An intis returned from main(), indicating the result

bool AirlineTicket::getHasEliteSuperRewardsStatus(){

return (fHasEliteSuperRewardsStatus);}

void AirlineTicket::setHasEliteSuperRewardsStatus(bool inStatus){

fHasEliteSuperRewardsStatus = inStatus;}

The preceding example exposes you to the general syntax for creating and using classes. Of course, thereis much more to learn. Chapters 8 and 9 go into more depth about the specific C++ mechanisms fordefining classes.

Your First Useful C++ ProgramThe following program builds on the employee database example used earlier when discussing structs.This time, you will end up with a fully functional C++ program that uses many of the features discussedin this chapter. This real-world example includes the use of classes, exceptions, streams, arrays, names-paces, references, and other language features.

An Employee Records SystemA program to manage a company’s employee records needs to be flexible and have useful features. Thefeature set for this program includes the following.

❑ The ability to add an employee

❑ The ability to fire an employee

❑ The ability to promote an employee

❑ The ability to view all employees, past and present

❑ The ability to view all current employees

❑ The ability to view all former employees

The design for this program divides the code into three parts. The Employee class encapsulates theinformation describing a single employee. The Database class manages all the employees of the com-pany. A separate UserInterface file provides the interactivity of the program.

The Employee ClassThe Employee class maintains all the information about an employee. Its methods provide a way toquery and change that information. Employees also know how to display themselves on the console.Methods also exist to adjust the employee’s salary and employment status.

29

A Crash Course in C++

04_574841 ch01.qxd 12/15/04 3:39 PM Page 29

Page 30: A Crash Course in C++ - Wiley › images › db › pdf › ... · The main function main()is, of course, where the program starts. An intis returned from main(), indicating the result

Employee.hThe Employee.h file declares the behavior of the Employee class. The sections of this file are describedindividually in the material that follows.

// Employee.h

#include <iostream>

namespace Records {

The first few lines of the file include a comment indicating the name of the file and the inclusion of thestream functionality.

This code also declares that the subsequent code, contained within the curly braces, will live in theRecords namespace. Records is the namespace that is used throughout this program for application-specific code.

const int kDefaultStartingSalary = 30000;

This constant, representing the default starting salary for new employees, lives in the Records names-pace. Other code that lives in Records can access this constant simply as kDefaultStartingSalary.Elsewhere, it must be referenced as Records::kDefaultStartingSalary.

class Employee{

public:

Employee();

void promote(int inRaiseAmount = 1000);void demote(int inDemeritAmount = 1000);void hire(); // Hires or rehires the employeevoid fire(); // Dismisses the employeevoid display(); // Outputs employee info to the console

// Accessors and settersvoid setFirstName(std::string inFirstName);std::string getFirstName();void setLastName(std::string inLastName);std::string getLastName();void setEmployeeNumber(int inEmployeeNumber);int getEmployeeNumber();void setSalary(int inNewSalary);int getSalary();bool getIsHired();

The Employee class is declared, along with its public methods. The promote() and demote() methodsboth have integer parameters that are specified with a default value. In this way, other code can omit theinteger parameters and the default will automatically be used.

30

Chapter 1

04_574841 ch01.qxd 12/15/04 3:39 PM Page 30

Page 31: A Crash Course in C++ - Wiley › images › db › pdf › ... · The main function main()is, of course, where the program starts. An intis returned from main(), indicating the result

A number of accessors provide mechanisms to change the information about an employee or query thecurrent information about an employee:

private: std::string mFirstName;std::string mLastName;int mEmployeeNumber;int mSalary;bool fHired;

};}

Finally, the data members are declared as private so that other parts of the code cannot modify themdirectly. The accessors provide the only public way of modifying or querying these values.

Employee.cppThe implementations for the Employee class methods are shown here:

// Employee.cpp

#include <iostream>

#include “Employee.h”

using namespace std;

namespace Records {

Employee::Employee(){

mFirstName = “”;mLastName = “”;mEmployeeNumber = -1;mSalary = kDefaultStartingSalary;fHired = false;

}

The Employee constructor sets the initial values for the Employee’s data members. By default, newemployees have no name, an employee number of -1, the default starting salary, and a status of nothired.

void Employee::promote(int inRaiseAmount){

setSalary(getSalary() + inRaiseAmount);}

void Employee::demote(int inDemeritAmount){

setSalary(getSalary() - inDemeritAmount);}

31

A Crash Course in C++

04_574841 ch01.qxd 12/15/04 3:39 PM Page 31

Page 32: A Crash Course in C++ - Wiley › images › db › pdf › ... · The main function main()is, of course, where the program starts. An intis returned from main(), indicating the result

The promote() and demote() methods simply call the setSalary() method with a new value. Notethat the default values for the integer parameters do not appear in the source file. They only need toexist in the header.

void Employee::hire(){

fHired = true;}

void Employee::fire(){

fHired = false;}

The hire() and fire() methods just set the fHired data member appropriately.

void Employee::display(){

cout << “Employee: “ << getLastName() << “, “ << getFirstName() << endl;cout << “-------------------------” << endl;cout << (fHired ? “Current Employee” : “Former Employee”) << endl;cout << “Employee Number: “ << getEmployeeNumber() << endl;cout << “Salary: $” << getSalary() << endl;cout << endl;

}

The display() method uses the console output stream to display information about the currentemployee. Because this code is part of the Employee class, it could access data members, such asmSalary, directly instead of using the getSalary() accessor. However, it is considered good style tomake use of accessors when they exist, even within the class.

// Accessors and setters

void Employee::setFirstName(string inFirstName){

mFirstName = inFirstName;}

string Employee::getFirstName(){

return mFirstName;}

void Employee::setLastName(string inLastName){

mLastName = inLastName;}

string Employee::getLastName(){

return mLastName;}

32

Chapter 1

04_574841 ch01.qxd 12/15/04 3:39 PM Page 32

Page 33: A Crash Course in C++ - Wiley › images › db › pdf › ... · The main function main()is, of course, where the program starts. An intis returned from main(), indicating the result

void Employee::setEmployeeNumber(int inEmployeeNumber){

mEmployeeNumber = inEmployeeNumber;}

int Employee::getEmployeeNumber(){

return mEmployeeNumber;}

void Employee::setSalary(int inSalary){

mSalary = inSalary;}

int Employee::getSalary(){

return mSalary;}

bool Employee::getIsHired(){

return fHired;}

}

A number of accessors and setters perform the simple task of getting and setting values. Even thoughthese methods seem trivial, it’s better to have trivial accessors and setters than to make your data mem-bers public. In the future, you may want to perform bounds checking in the setSalary() method, forexample.

EmployeeTest.cppAs you write individual classes, it is often useful to test them in isolation. The following code includes amain() function that performs some simple operations using the Employee class. Once you are confi-dent that the Employee class works, you should remove or comment-out this file so that you don’tattempt to compile your code with multiple main() functions.

// EmployeeTest.cpp

#include <iostream>

#include “Employee.h”

using namespace std;using namespace Records;

int main (int argc, char** argv){

cout << “Testing the Employee class.” << endl;

33

A Crash Course in C++

04_574841 ch01.qxd 12/15/04 3:39 PM Page 33

Page 34: A Crash Course in C++ - Wiley › images › db › pdf › ... · The main function main()is, of course, where the program starts. An intis returned from main(), indicating the result

Employee emp;

emp.setFirstName(“Marni”);emp.setLastName(“Kleper”);emp.setEmployeeNumber(71);emp.setSalary(50000);emp.promote();emp.promote(50);emp.hire();emp.display();

return 0;}

The Database ClassThe Database class uses an array to store Employee objects. An integer called mNextSlot is used as amarker to keep track of the next unused array slot. This method for storing objects is probably not idealbecause the array is of a fixed size. In Chapters 4 and 21, you will learn about data structures in the C++standard library that you can use instead

Database.h// Database.h

#include <iostream>#include “Employee.h”

namespace Records {

const int kMaxEmployees = 100;const int kFirstEmployeeNumber = 1000;

Two constants are associated with the database. The maximum number of employees is a constantbecause the records are kept in a fixed-size array. Because the database will also take care of automati-cally assigning an employee number to a new employee, a constant defines where the numbering begins.

class Database{

public:Database();~Database();

Employee& addEmployee(std::string inFirstName, std::string inLastName);Employee& getEmployee(int inEmployeeNumber);Employee& getEmployee(std::string inFirstName, std::string inLastName);

The database provides an easy way to add a new employee by providing a first and last name. For con-venience, this method will return a reference to the new employee. External code can also get an

34

Chapter 1

04_574841 ch01.qxd 12/15/04 3:39 PM Page 34

Page 35: A Crash Course in C++ - Wiley › images › db › pdf › ... · The main function main()is, of course, where the program starts. An intis returned from main(), indicating the result

employee reference by calling the getEmployee() method. Two versions of this method are declared.One allows retrieval by employee number. The other requires a first and last name.

void displayAll();void displayCurrent();void displayFormer();

Because the database is the central repository for all employee records, it has methods that will outputall employees, the employees who are currently hired, and the employees who are no longer hired.

protected:Employee mEmployees[kMaxEmployees];int mNextSlot;int mNextEmployeeNumber;

};}

The mEmployees array is a fixed-size array that contains the Employee objects. When the database iscreated, this array will be filled with nameless employees, all with an employee number of -1. Whenthe addEmployee() method is called, one of these blank employees will be populated with real data.The mNextSlot data member keeps track of which blank employee is next in line to be populated. ThemNextEmployeeNumber data member keeps track of what employee number will be assigned to thenew employee.

Database.cpp// Database.cpp

#include <iostream>#include <stdexcept>

#include “Database.h”

using namespace std;

namespace Records {

Database::Database(){

mNextSlot = 0;mNextEmployeeNumber = kFirstEmployeeNumber;

}

Database::~Database(){}

The Database constructor takes care of initializing the next slot and next employee number members totheir starting values. mNextSlot is initialized to zero so that when the first employee is added, it will gointo slot 0 of the mEmployees array.

35

A Crash Course in C++

04_574841 ch01.qxd 12/15/04 3:39 PM Page 35

Page 36: A Crash Course in C++ - Wiley › images › db › pdf › ... · The main function main()is, of course, where the program starts. An intis returned from main(), indicating the result

Employee& Database::addEmployee(string inFirstName, string inLastName){

if (mNextSlot >= kMaxEmployees) {cerr << “There is no more room to add the new employee!” << endl;throw exception();

}

Employee& theEmployee = mEmployees[mNextSlot++];theEmployee.setFirstName(inFirstName);theEmployee.setLastName(inLastName);theEmployee.setEmployeeNumber(mNextEmployeeNumber++);theEmployee.hire();

return theEmployee;}

The addEmployee() method fills in the next “blank” employee with actual information. An initial checkmakes sure that the mEmployees array is not full and throws an exception if it is. Note that after theiruse, the mNextSlot and mNextEmployeeNumber data members are incremented so that the nextemployee will get a new slot and number.

Employee& Database::getEmployee(int inEmployeeNumber){

for (int i = 0; i < mNextSlot; i++) {if (mEmployees[i].getEmployeeNumber() == inEmployeeNumber) {

return mEmployees[i];}

}

cerr << “No employee with employee number “ << inEmployeeNumber << endl;throw exception();

}

Employee& Database::getEmployee(string inFirstName, string inLastName){

for (int i = 0; i < mNextSlot; i++) {if (mEmployees[i].getFirstName() == inFirstName &&

mEmployees[i].getLastName() == inLastName) {return mEmployees[i];

}}

cerr << “No match with name “ << inFirstName << “ “ << inLastName << endl;throw exception();

}

Both versions of getEmployee() work in similar ways. The methods loop over all nonblank employeesin the mEmployees array and check to see if each Employee is a match for the information passed to themethod. If no match is found, an error is output and an exception is thrown.

36

Chapter 1

04_574841 ch01.qxd 12/15/04 3:39 PM Page 36

Page 37: A Crash Course in C++ - Wiley › images › db › pdf › ... · The main function main()is, of course, where the program starts. An intis returned from main(), indicating the result

void Database::displayAll(){

for (int i = 0; i < mNextSlot; i++) {mEmployees[i].display();

}}

void Database::displayCurrent(){

for (int i = 0; i < mNextSlot; i++) {if (mEmployees[i].getIsHired()) {

mEmployees[i].display();}

}}

void Database::displayFormer(){

for (int i = 0; i < mNextSlot; i++) {if (!mEmployees[i].getIsHired()) {

mEmployees[i].display();}

}}

}

The display methods all use a similar algorithm. They loop through all nonblank employees and telleach employee to display itself to the console if the criterion for display matches.

DatabaseTest.cppA simple test for the basic functionality of the database follows:

// DatabaseTest.cpp

#include <i0stream>

#include “Database.h”

using namespace std;using namespace Records;

int main(int argc, char** argv){

Database myDB;

Employee& emp1 = myDB.addEmployee(“Greg”, “Wallis”);emp1.fire();

Employee& emp2 = myDB.addEmployee(“Scott”, “Kleper”);emp2.setSalary(100000);

37

A Crash Course in C++

04_574841 ch01.qxd 12/15/04 3:39 PM Page 37

Page 38: A Crash Course in C++ - Wiley › images › db › pdf › ... · The main function main()is, of course, where the program starts. An intis returned from main(), indicating the result

Employee& emp3 = myDB.addEmployee(“Nick”, “Solter”);emp3.setSalary(10000);emp3.promote();

cout << “all employees: “ << endl;cout << endl;myDB.displayAll();

cout << endl;cout << “current employees: “ << endl;cout << endl;myDB.displayCurrent();

cout << endl;cout << “former employees: “ << endl;cout << endl;myDB.displayFormer();

}

The User InterfaceThe final part of the program is a menu-based user interface that makes it easy for users to work withthe employee database.

UserInterface.cpp// UserInterface.cpp

#include <i0stream>#include <stdexcept>

#include “Database.h”

using namespace std;using namespace Records;

int displayMenu(); void doHire(Database& inDB);void doFire(Database& inDB);void doPromote(Database& inDB);void doDemote(Database& inDB);

int main(int argc, char** argv){

Database employeeDB;bool done = false;

while (!done) {int selection = displayMenu();

switch (selection) {

38

Chapter 1

04_574841 ch01.qxd 12/15/04 3:39 PM Page 38

Page 39: A Crash Course in C++ - Wiley › images › db › pdf › ... · The main function main()is, of course, where the program starts. An intis returned from main(), indicating the result

case 1:doHire(employeeDB);break;

case 2:doFire(employeeDB);break;

case 3:doPromote(employeeDB);break;

case 4:employeeDB.displayAll();break;

case 5:employeeDB.displayCurrent();break;

case 6:employeeDB.displayFormer();break;

case 0:done = true;break;

default:cerr << “Unknown command.” << endl;

}}

return 0;}

The main() function is a loop that displays the menu, performs the selected action, then does it allagain. For most actions, separate functions are defined. For simpler actions, like displaying employees,the actual code is put in the appropriate case.

int displayMenu(){

int selection;

cout << endl;cout << “Employee Database” << endl;cout << “-----------------” << endl;cout << “1) Hire a new employee” << endl;cout << “2) Fire an employee” << endl;cout << “3) Promote an employee” << endl;cout << “4) List all employees” << endl;cout << “5) List all current employees” << endl;cout << “6) List all previous employees” << endl;cout << “0) Quit” << endl;cout << endl;cout << “---> “;

cin >> selection;

return selection;}

39

A Crash Course in C++

04_574841 ch01.qxd 12/15/04 3:39 PM Page 39

Page 40: A Crash Course in C++ - Wiley › images › db › pdf › ... · The main function main()is, of course, where the program starts. An intis returned from main(), indicating the result

The displayMenu() function simply outputs the menu and gets input from the user. One importantnote is that this code assumes that the user will “play nice” and type a number when a number isrequested. When you read about I/O in Chapter 14, you will learn how to protect against bad input

void doHire(Database& inDB){

string firstName;string lastName;

cout << “First name? “;cin >> firstName;cout << “Last name? “;cin >> lastName;

try {inDB.addEmployee(firstName, lastName);

} catch (std::exception ex) { cerr << “Unable to add new employee!” << endl;

}}

The doHire() function simply gets the new employee’s name from the user and tells the database toadd the employee. It handles errors somewhat gracefully by outputting a message and continuing.

void doFire(Database& inDB){

int employeeNumber;

cout << “Employee number? “;cin >> employeeNumber;

try {Employee& emp = inDB.getEmployee(employeeNumber);emp.fire();cout << “Employee “ << employeeNumber << “ has been terminated.” << endl;

} catch (std::exception ex) cerr << “Unable to terminate employee!” << endl;

}}

void doPromote(Database& inDB){

int employeeNumber;int raiseAmount;

cout << “Employee number? “;cin >> employeeNumber;

cout << “How much of a raise? “;cin >> raiseAmount;

40

Chapter 1

04_574841 ch01.qxd 12/15/04 3:39 PM Page 40

Page 41: A Crash Course in C++ - Wiley › images › db › pdf › ... · The main function main()is, of course, where the program starts. An intis returned from main(), indicating the result

try {Employee& emp = inDB.getEmployee(employeeNumber);emp.promote(raiseAmount);

} catch (std::exception ex) {cerr << “Unable to promote employee!” << endl;

}}

doFire() and doPromote() both ask the database for an employee by their employee number and thenuse the public methods of the Employee object to make changes.

Evaluating the ProgramThe preceding program covers a number of topics from the very simple to the more obscure. There are anumber of ways that you could extend this program. For example, the user interface does not expose allof the functionality of the Database or Employee classes. You could modify the UI to include those fea-tures. You could also change the Database class to remove fired employees from the mEmployees array,potentially saving space.

If there are parts of this program that don’t make sense, consult the preceding sections to review thosetopics. If something is still unclear, the best way to learn is to play with the code and try things out.For example, if you’re not sure how to use the ternary operator, write a short main() function that triesit out.

SummaryNow that you know the fundamentals of C++, you are ready to become a professional C++ programmer.The next five chapters will introduce you to several important design concepts. By covering design at ahigh-level without getting into too much actual code, you will gain an appreciation for good programdesign without getting bogged down in the syntax.

When you start getting deeper into the C++ language later in the book, refer back to this chapter to brushup on parts of the language that you may need to review. Going back to some of the sample code in thischapter may be all you need to see to bring a forgotten concept back to the forefront of your mind.

41

A Crash Course in C++

04_574841 ch01.qxd 12/15/04 3:39 PM Page 41

Page 42: A Crash Course in C++ - Wiley › images › db › pdf › ... · The main function main()is, of course, where the program starts. An intis returned from main(), indicating the result

04_574841 ch01.qxd 12/15/04 3:39 PM Page 42