AL MA TE RI A Crash Course in C++ GH TE D 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 difference between = and ==) are not covered. The very esoteric points (remember what a union is? how about the volatile keyword?) are also omitted.
Chapter 1 The Obligatory Hello, World In all its glory, the following code is the simplest C++ program you’re likely to encounter. // helloworld.cpp #include 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 program and unlikely to win any awards, but it does exhibit several important concepts about the format of a C++ program.
A Crash Course in C++ In C, included files usually end in .h, such as . In C++, the suffix is omitted for standard library headers, such as . Your favorite standard headers from C still exist in C++, but with new names. For example, you can access the functionality from by including . The table below shows some of the most common preprocessor directives.
Chapter 1 I/O streams are covered in depth in Chapter 14, but the basics of output are very simple. Think of an output 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.
A Crash Course in C++ The implementation of a method or function can also be handled in a namespace: // namespaces.cpp #include #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() function provided by the third-party library. To call the namespace-enabled version of foo(), prepend the namespace onto the function name as follows.
Chapter 1 // helloworld.cpp #include 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.
A Crash Course in C++ When run, this code will output a random value from memory for the first line and the number 7 for the second. 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++.
Chapter 1 will issue a warning if you assign a float to an int without an explicit cast. If you are certain that the left-hand-side type is fully compatible with the right-hand side type, it’s okay to cast implicitly. Operators What good is a variable if you don’t have a way to change it? The table below shows the most common operators used in C++ and sample code that makes use of them.
A Crash Course in C++ Operator Description Usage << >> <<= >>= Takes the raw bits of a variable and “shifts” each bit left (<<) or right (>>) the specified number of places. i i i i ^ ^= Performs a bitwise “exclusive or” operation on the two arguments. i = i ^ j; i ^= j; = i = i <<= >>= << 1; >> 4; 1; 4; The following program shows the most common variable types and operators in action.
Chapter 1 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 to 51. 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, then bitwise operators.
A Crash Course in C++ Behind the scenes, an enumerated type is just an integer value. The real value of kPieceTypeKing is zero. However, by defining the possible values for variables of type PieceT, your compiler can give you a 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 a warning on most compilers.
Chapter 1 cout << “Employee: “ << anEmployee.firstInitial << anEmployee.middleInitial << anEmployee.lastInitial << endl; cout << “Number: “ << anEmployee.employeeNumber << endl; cout << “Salary: $” << anEmployee.salary << endl; return 0; } Conditionals Conditionals let you execute code based on whether or not something is true. There are three main types of conditionals in C++. If/Else Statements The most common conditional is the if statement, which can be accompanied by else.
A Crash Course in C++ case kSaveMenuItem: // Code to save a file break; default: // Code to give an error message break; } If you omit the break statement, the code for the subsequent case will be executed whether or not it matches. This is sometimes useful, but more frequently a source of bugs. The Ternary Operator C++ has one operator that takes three arguments, known as the ternary operator.
Chapter 1 Operator Description Usage != Not equals. The result of the statement is true if the left-hand side does not equal the right-hand side. if (i != 3) { std::cout << “i is not 3”; } ! Logical not. Negates the true/false status of a Boolean expression. This is a unary operator. if (!someBoolean) { std::cout << “someBoolean is false”; } && Logical and. The result is true if both parts of the expression are true.
A Crash Course in C++ The keyword break can be used within a loop to immediately get out of the loop and continue execution of the program. The keyword continue can be used to return to the top of the loop and reevaluate the while expression. Both are often considered poor style because they cause the execution of a program to jump around somewhat haphazardly. The Do/While Loop C++ also has a variation on the while loop called do/while.
Chapter 1 The preceding example shows a one-dimensional array, which you can think of as a line of integers, each with its own numbered compartment. C++ allows multidimensional arrays. You might think of a twodimensional array as a checkerboard, where each location has a position along the x-axis and a position along the y-axis. Three-dimensional and higher arrays are harder to picture and are rarely used.
A Crash Course in C++ Function declarations are often called “function prototypes” or “signatures” to emphasize that they represent how the function can be accessed, but not the code behind it. A function declaration is shown below. This example has a return type of void, indicating that the function does not provide a result to the caller. The caller must provide two arguments for the function to work with — an integer and a character.
Chapter 1 struggled with this section, you may want to obtain one of the fine introductory C++ books mentioned in Appendix D before continuing. Diving Deeper into C++ Loops, variables, and conditionals are terrific building blocks, but there is much more to learn. The topics covered next include many features that are designed to help C++ programmers with their code as well as a few features that are often more confusing than helpful.
A Crash Course in C++ Dynamically Allocated Arrays Due to the way that the stack works, the compiler must be able to determine at compile time how big each stack frame will be. Since the stack frame size is predetermined, you cannot declare an array with a variable size. The following code will not compile because the arraySize is a variable, not a constant.
Chapter 1 Now that the memory has been allocated, you can work with myVariableSizedArray as though it were 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 use the memory. In C++, you use the delete command to do this. delete[] myVariableSizedArray; The brackets after delete indicate that you are deleting an array. The C++ commands new and delete are similar to malloc() and free() from C.
A Crash Course in C++ This syntax is a little messy. The -> (arrow) operator lets you perform both the dereference and the field access 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 integer parameter, it is really a copy of the integer that you pass in.
Chapter 1 // stringtest.cpp #include #include 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 a function, like strcat() in C to concatenate two strings, you can simply use +.
A Crash Course in C++ Nonstandard Strings There are several reasons why many C++ programmers don’t use C++-style strings. Some programmers simply aren’t aware of the string type because it was not always part of the C++ specification. Others have discovered over the years that the C++ string doesn’t provide the behavior they need and have developed their own string type.
Chapter 1 An exception is an unexpected situation. For example, if you are writing a function that retrieves a Web page, several things could go wrong. The Internet host that contains the page might be down, the page might come back blank, or the connection could be lost. In many programming languages, you would handle this situation by returning a special value from the function, such as the NULL pointer. Exceptions provide a much better mechanism for dealing with problems.
A Crash Course in C++ If your code never catches any exceptions but an exception is thrown, it will be caught by the program itself, which will be terminated. These trickier aspects of exceptions are covered in much more detail in Chapter 15 The Many Uses of const The keyword const can be used in several different ways in C++. All of its uses are related, but there are subtle differences.
Chapter 1 Const References You 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. const seems 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.
A Crash Course in C++ ~AirlineTicket(); int calculatePriceInDollars(); std::string void int void bool void private: std::string int bool getPassengerName(); setPassengerName(std::string inName); getNumberOfMiles(); setNumberOfMiles(int inMiles); getHasEliteSuperRewardsStatus(); setHasEliteSuperRewardsStatus(bool inStatus); mPassengerName; mNumberOfMiles; fHasEliteSuperRewardsStatus; }; The method that has the same name of the class with no return type is a constructor.
Chapter 1 The definitions of the AirlineTicket class methods are shown below. // AirlineTicket.cpp #include #include “AirlineTicket.
A Crash Course in C++ 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, there is much more to learn. Chapters 8 and 9 go into more depth about the specific C++ mechanisms for defining classes.
Chapter 1 Employee.h The Employee.h file declares the behavior of the Employee class. The sections of this file are described individually in the material that follows. // Employee.h #include namespace Records { The first few lines of the file include a comment indicating the name of the file and the inclusion of the stream functionality. This code also declares that the subsequent code, contained within the curly braces, will live in the Records namespace.
A Crash Course in C++ A number of accessors provide mechanisms to change the information about an employee or query the current information about an employee: private: std::string std::string int int bool mFirstName; mLastName; mEmployeeNumber; mSalary; fHired; }; } Finally, the data members are declared as private so that other parts of the code cannot modify them directly. The accessors provide the only public way of modifying or querying these values. Employee.
Chapter 1 The promote() and demote() methods simply call the setSalary() method with a new value. Note that the default values for the integer parameters do not appear in the source file. They only need to exist 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.
A Crash Course in C++ 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.
Chapter 1 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 Class The Database class uses an array to store Employee objects. An integer called mNextSlot is used as a marker to keep track of the next unused array slot. This method for storing objects is probably not ideal because the array is of a fixed size.
A Crash Course in C++ 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 void void displayAll(); displayCurrent(); displayFormer(); Because the database is the central repository for all employee records, it has methods that will output all employees, the employees who are currently hired, and the employees who are no longer hired.
Chapter 1 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.
A Crash Course in C++ 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.
Chapter 1 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 Interface The final part of the program is a menu-based user interface that makes it easy for users to work with the employee database. UserInterface.
A Crash Course in C++ 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 all again. For most actions, separate functions are defined.
Chapter 1 The displayMenu() function simply outputs the menu and gets input from the user. One important note is that this code assumes that the user will “play nice” and type a number when a number is requested. 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.
A Crash Course in C++ 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 then use the public methods of the Employee object to make changes. Evaluating the Program The preceding program covers a number of topics from the very simple to the more obscure.