Você está na página 1de 80

C++ Tutorials

Introduction: Welcome! Chapter 1: Pascal to C++, Part 1 Chapter 2: Hello, World! Chapter 3: Functions Chapter 4: Pointers Chapter 5: Pascal to C++, Part 2 Chapter 6: Passing Variables Chapter 7: Classes Chapter 8: Advanced Class Uses Chapter 9: Operator Overloading

C++, like Pascal, breaks instructions up into blocks called functions. When a program is first run, a function named "main" is executed. One big difference between Pascal and C++ is how functions are defined. Take a look at this very small program:
void main(void) { }

Let's go over each part. The first line, "void main(void)", is the function heading. This is the equivalent of saying "procedure main;" in Pascal. Note that there's no semicolon in the C++ version; this is because what must come immediately after main is an instruction. Of course, one instruction is not nearly enough, so we can define a block and put as many instructions as we want in it. In the above example, the block is the area between the { and the }. The { and } are C++'s equivalents of Pascal's Begin and End -- In fact, they are nearly identical. As with Pascal, you can use the { and } to fill in as many lines as we want and have them used as one big instruction. You've probably done this with a for loop before; the for loops only want one instruction to follow it, but if you used begin and end, you could put as many instructions in the loop as you wanted.

Comments in C++ are only a little different than the ones you've used in Pascal. The big difference is that instead of { and } or (* and *) as the beginning and end of comments, you use /* and */. Let's try it out!
/* This is a big comment */ /* This is a small comment */

C++ also defines another way to comment out a line. If you say /, everything to its right on that line only is commented out. So, if you had:
/* This is a comment */ /* This is a comment, too */ /* And Yes, I'm a comment. Are you a comment? */

You could turn it into:


/ This is a comment / This is a comment, too / And Yes, I'm a comment. Are you a comment?

This is sometimes easier when you want to just put a small comment off to the right. Feel free to use either one.

At the heart of every program is its variables. In this respect, though, C++ has many differences when compared to Pascal. For instance, in Pascal, when you declare a variable, you say the name and then the type (ie, "Burrito : Integer"), but in C++, it's the other way around! Let's go over the names of the data types in Pascal versus C++:
Pascal Boolean Char Integer Real C++ bool char int double Description "TRUE" or "FALSE" only Single Character ('A', 'g', '1', etc) Integer (10, -53, 5524, 0, etc) Real Number (0.3, 2.123, -121.1, etc)

Note that the names of the C++ equivalent are both shorter and all lowercase. Now, let's look at how you declare these variables in C++ versus Pascal: Pascal:
a b c d : : : : Boolean; Char; Integer; Real;

C++:

bool a; char b; int c; double d;

Note the way characters are represented: 'A', 'g', and so on. Anything you put between single quotes is considered a character. This is different from Pascal, where the single quotes were used for strings. In C++, the " (double quotes) character is used for strings, which are really just arrays of characters. Note that the way C++ declares variables is backwards from the way Pascal does it, and no colon is involved. It may take a little getting used to, but it's really not so bad.

One thing that's different in C++ is how you declare arrays. You probably remember that this is how it's done in Pascal:
somearray : array[1..10] of integer;

C++ makes it easier to create arrays - to create the same array as shown above, you simply say:
int somearray[10];

Wasn't that easy? One big difference is that, unlike Pascal, C++ requires that all of your arrays start at 0. So, if we wanted to access element 5 of our array, we'd say:
somearray[4];

Confused? Remember that we're starting the array at 0. The first element is "somearray[0]", then the second is "somearray[1]", and so on. This may take some getting used to; while you're getting started, you can just subtract 1 mentally when you're using arrays. "Let's see, the fifth element, that's somearray[4]" That may feel kind of silly, but hopefully what we're about to say will make up for it. In C++, variables can be declared nearly anywhere inside a program! What does this mean? Well, consider this code:
void main(void) { int a; int b; } / / / / / In In In In In Pascal: Pascal: Pascal: Pascal: Pascal: "procedure main;" "begin" " a: integer;" " b: integer;" "end"

The variables are being declared right in the middle of a program! That's right -- you can say "int b;" anywhere inside that block! Because there's no special section where you declare variables in C++, you can forget about the "var" keyword you used in Pascal to say you wanted to declare variables.

Now that we've declared variables, we need to be able to assign values to them and operate on them. For the most part, the syntax is the same as Pascal, but with a few differences that will probably haunt you for at least a few chapters of this tutorial. Don't worry, though -- like learning anything, practice makes perfect, and once you've written some small programs, you'll get it down. Here is a list of common operators in C++:
Pascal + / * MOD numbers := C++ + / * % = Meaning Adds two numbers Subtracts two numbers Divides one number by another Multiplies one number by another Gives you the remainder of division between two Assigns one number to another

The two that will be giving you the most problems are the assignment operator and the equality operator. For instance, if you want to set a variable salsa to 3, you would say: Pascal:
salsa := 3;

C++:

salsa = 3;

Note that C++ uses "=" to assign values and not ":=", which Pascal uses! While you'll probably come to the conclusion (once you've become a C++ person) that this is actually better, it should be pretty confusing right now. So, let's try making a small program with this knowledge!
void main(void)/ Declare the main function { double a; /* Declare a double named a */ a = 5.2; a = a+2; int b; of int B; } / everything.. Is this really a good idea? /* Remember, C++ is case sensitive! */ /* Assign 5.2 to a */ / Assign 7.2 to a (5.2 + 2) / Wow! We just declared a variable right in the middle

b = B = 10; /* Assign 10 to b and B */

Slowly go over the example above. For the most part, you shouldn't have any trouble understanding it. You may have taken a double take on the last statement in the procedure, "b = B = 10;". How can this be? Well, when this program is run, that

statement is run right-to-left. First, the statement "B = 10" is executed, which assigns 10 to B. That statement then returns the value 10, leaving only "b = 10", which of course assigns 10 to b. You may have better luck thinking of the whole statement as "b = (B = 10);" instead. Did you notice that we declared b and B right in the middle of the program? While this may seem really neat at first, it does get confusing. We suggest keeping them at the top of your functions, where a is, in the future. You may have also been confused by the line "int B;". Didn't you just declare "b"? Remember, C++ is case sensitive. "B" is a completely separate variable from "b". Don't mix up your variables!

Having a program make choices is one of the simplest actions you can do. As you might have expected, C++ has if statements just like Pascal. Let's start by using an if statement to see if a variable named fajita is larger than 10, and if so, let's set it to 3.
if (fajita > 10) then fajita := 3;

Pascal:

C++:

if (fajita > 10) fajita = 3;

Immediately you should see two things: that the "then" is missing from the C++ version, and that C++ uses = to assign values instead of := as Pascal does. You'll find that C++ cuts off a lot of the fat of Pascal. Where you said "then" after an if statement and "do" after a for loop, you now say nothing. You may be sorry to see them go now, but soon you'll feel silly for having to type out all those extra words. Another thing to note is that in C++ the parentheses are required. The operators you use to say "less than" and "equal to" are for the most part the same. Let's look at them:
C++ < > <= >= ! == != || && Pascal < > <= >= NOT = <> or and Meaning Less-Than Greater-Than Less-Than or Equal-To Greater-Than or Equal-To NOT Equal-To NOT Equal-To Or And

Because we now use "=" to assign values, we must use something else. Fitting with C++'s often cryptic nature, AND as well as OR have been replaced with && and ||. Let's try a program that uses an if statement:
void main(void) { int a; int b; a = 10; b = 5; if (a > 5) / If a is greater than 5..

a = a + 4; if (a <= 14) / If a is less than or equal-to 14.. if (b == 5) / And if b is equal to 5.. a = 0; if (b < a) b = a; }

Let's step through that example. First, two integers, a and b are created. Then, a is assigned 10 and b is given 5. Next, an if statement checks to see if a is greater than 5. It is, so the instruction "a = a + 4;" is executed, and a becomes "a+4", or 14. After that, another if statement checks to see if a is less than or equal to 14. It is, so another if statement is run to see if b is equal to 5. It is, so the statement "a = 0" is used, and a becomes 0. The final statement checks to see if b, which is 5, is less than a, which is 0. Since 5 is greater than 0, the if statement fails, and nothing is run.

Let's talk a little bit more about how if statements work. How do they figure out if a statement is TRUE or if it is FALSE? The answer is simple: Anything that simplifies to 0 is false. Everything else is true. What does this mean? Well, it means that you don't have to stick to comparisons like "is a less than 4?" in your if statements -- you can have if statements that simply have a variable; if the variable is zero, the result is the same as a FALSE, but if not, it's a TRUE. Take a look at the following example:
void main(void) { int a; int b; a = 0; b = 1; / Same as FALSE / Same as TRUE

if (a) a = 500; if (b) b = 500; }

Look at how the if is without any operators. All it consists of is a single variable! While this may feel a little strange, think about how your programs really work. Take this statement, for example:
if (a > 5)

In that piece of code, you have the statement "a > 5". When the program runs, this statement is ran before the if statement. If a was set to 6, the statement would simplify to TRUE, which is the same as 1. So, the new, simplified statement is:
if (1)

Which, because it's non-zero, is a TRUE, and the statement following it runs.

Of course, if you have an if, you've got to be able to have an else. C++ handles this else like Pascal does, with one critical difference. Try and find it in the example!
void main(void) { double a; a = 0.5; /* Not 0, so it's TRUE! */

if (a) a = 10000; else a = 10; }

You may have missed it. Take a look at the statement "a = 10000;". Note that, even though an else comes right after it, it has a semicolon! This is due to a fundamental difference between how semicolons work in C++ versus Pascal. In Pascal, the semicolon was a separator, while in C++, the semicolon is a terminator. This means that in Pascal, you have:
(statement) ; (statement) ; (statement)

Notice how the semicolons are just acting as a boundary between where one statement ends and one statement begins. However, in C++, you have:
(statement) ; (statement) ; (statement) ;

Look at how there's a semicolon after each statement. Because the semicolon terminates each statement, it must be placed at the end of every single statement. For this reason, even though else comes after the if statement, you still have to use the semicolon. This has a little to do with why there's no "then" in an if statement anymore; since we've removed it from the if statement, C++ uses the parentheses to determine exactly where the if statement ends and the lines it should execute begin.

One of the last points of C++ we haven't covered is the switch statement. What is it? A revamp of Pascal's case statement. The works are pretty similar, but there are small differences, both in its syntax, and its workings. Let's start off by showing a switch in C++ versus a case in Pascal: Pascal:
case Grade of 'A' : Writeln('Yay, 'B' : Writeln('Hmm, 'C' : Writeln('A C. 'D' : Writeln('A D? 'F' : Writeln('This end;

you got an A!'); a B. Not bad.'); Oh well.'); Argh.'); is not happening..');

C++:

switch(Grade) { case 'A' : cout << break; case 'B' : cout << break; case 'C' : cout << break; case 'D' : cout << break; case 'F' : cout << break; }

"Yay, I got an A!" << endl; "Hmm, a B. Not bad." << endl; "A C. Oh well." << endl; "A D? Argh." << endl; "This is not happening.." << endl;

Note: Don't worry about the weird cout thing above -- that's just C++'s equivalent of Write. All will be revealed in Chapter 2. The first thing you should notice is that every line has a statement under it called "break". What's it for? Well, in C++, the label case on each line is just that -- a label that tells it where to start running statements. What does this mean? Well, you can place many lines in a row. In fact, if you don't put a break in, the program will keep going down in the case statements, into other case labels, until it reaches the end of a break. Think of the break as the only thing that stops a case statement from continuing all the way down through each case label under it. For instance, look at this piece of code:
switch (borp) { case 1 : cout case 2 : cout case 3 : cout default: cout }

<< << << <<

"One." << endl; "Two." << endl; "Three." << endl; "Huh?" << endl;

Suppose that borp was given the value 2. Because there are no break's to stop the execution, the program would keep going, giving the output:
Two. Three. Huh?

Of course, this is probably not what you wanted. Simply adding a break to each case statement will clear that up. Now, you might be wondering what that default part is. You might remember that in Pascal, you could put an else at the end of a case statement, and if a value didn't match the ones you listen in the statement, it would use that one instead. Well, this is C++'s version.
case statement be a string. This is not in the official Pascal standard, and it isn't in the C++ standard either. The reason? The switch statement in C++ only allows for an integer. Since a char (ie 'A' and so on above) can be converted to a number inside the

One big note: In many variants of Pascal, it was possible to have one of your labels in a

program, they're allowed, but there's no way to turn "Burritos!" into a single number, so it can't be used.

Now that we've gone over making choices in a program, it's time to think about making a program that can loop. Let's start with the while loop. You may remember this from Pascal, where you would say something like:
a := 0; while (a < 20) do a := a + 1;

This would of course loop 20 times, each time incrementing a by one. C++, in a similar manner as with if, removes some of the fat and makes you add parentheses to the statement used to determine if the loop should keep going (called the conditional statement). Take a look at the above statement in C++ form:
a = 0; while (a < 20) a = a + 1;

Notice how the conditional statement, "a < 20", is surrounded in perentheses, just like you had to do with the if statement. Also, note that the do keyword was removed. You may be noticing a trend away from Pascal's English-like syntax into a more cryptic, terse programming language. This is very much the case. Let's try using while in a program!
void main(void) { float taco; int chimichanga;

/ mmm...chimichangas..

taco = 22.2; chimichanga = 5524; /* This next part will keep adding 10 to taco until taco is no longer less than chimichanga */ while (taco < chimichanga) taco = taco + 10; }

The above program is pretty simple -- just two variables that get assigned two values and then are used in a while loop. You should note that, like Pascal, the order of a while loop is always: 1. Test the conditional statement that controls the loop.

2. If it's TRUE (ie, non-zero), execute the statement under the conditional. 3. If not, exit the while loop. 4. If we haven't exited the while loop yet, start back on step one.

You may remember Pascal's repeat..until loop that let you run essentially a while loop backwards; first the code that it should run, and then the conditional statement would be checked. Here's an example of what we're talking about:
a := 44; repeat a := a + 1; until a > 50;

This loop would run once, then check the conditional statement "a > 50". If it was TRUE, the loop would stop. If it wasn't, the loop would keep going. Simple, eh? C++ has a fairly similar version of repeat..until called do..while. As the name suggests, the words do and while take the place of repeat and until. Another major difference is that only one statement goes between the do/while pair. Obviously, you can expand the amount of commands by using { and } to make a block of code.
a = 44; do { / Notice the brace! a = a + 1; } while (a <= 50);

One thing you might be looking strangely at is the conditional statement, "a <= 50". Why is it "less than or equal to" instead of "greater than" in the Pascal example above it? Well, the repeat..until loop goes through UNTIL the conditional statement becomes TRUE, when it exits. The do..while loop, on the other hand, is completely opposite; it continues the looping WHILE the conditional statement is TRUE. If you're at first a little confused by this sudden reversal of how it works, just read the last line over to yourself when you write your code the first couple times. Make sure it makes sense. Think of the above do..while loop as "do stuff while a is less than or equal to fifty", and it may suddenly become easier to follow.

Any well-written program has constants that are used throughout it. Say you were managing an enchilada packaging company, and you were always putting the weight into different parts of the program. By placing it at the top of the code as a constant, an unchangeable variable, you would only have to change the one constant if your enchiladas started weighing more. In Pascal, there was a section at the beginning of each file named const where all constants had to be declared. C++ is a lot more flexible than Pascal was; there's no special section where your constants have to go. If you want them to be global (that is, usable by everything), you have to put them outside of a function. The best place is probably the very top of a program. Constants are declared just like you're declaring a regular variable and initializing it to a value, but you add the const keyword in front of it. For instance, to make a constant with the value 14, you say:
const int taco = 14; /* Create a constant named taco with the value 14 */

Note that you have to put the type of variable it is in addition to a name and value. This may feel a little wierd; it's better to think of these constants as variables you aren't allowed to change rather than constants. Let's try using constants in a program:
const int taco = 14; const int burrito = 15; void main(void) { int chimichanga; chimichanga = taco; if (chimichanga > 10) chimichanga = 1; else chimichanga = 5; chimichanga = chimichanga + burrito; if (burrito > taco) chimichanga = 400; }

Notice how we're able to use taco and burrito all throughout the program. We can't, however, give them a new value, because of the const keyword in front of them. If, for some reason, we needed to change taco to 50, it would just mean changing one place at the top, saving potential programming energy for other tasks.

You may have been wondering about where the for loop has gone to. Don't worry, it's still alive and well. Unfortunately, it's changed a lot in C++. It may look very strange at first, but once you get used to it, you'll find it very powerful. Before we get into C++'s version, let's review how Pascal does it. Take a look at this example:
for i := 1 to 10 do begin foo := foo + 1; end;

In the above example, there are 3 critical steps: 1. i is set at 1. 2. The block it runs is loop, and i is incremented by 1 each time. 3. When i reaches 10, the for loop exits. If you think about a for loop in this way, the following shouldn't be too hard to learn. Let's look at how the above loop would be done in C++:
for (i = 0 ; i < 10 ; i = i + 1) { foo = foo + 1; }

That should probably be very confusing; Let's go over what is going on. Inside the parentheses after the for keyword, there are 3 parts. The first part is where you initialize a counter. In our case, we're setting i to 0. This section is only run once, when the for loop starts. The second part is the conditional statement that determines whether or not the loop will be run again. It is checked after the code under the for statement is executed. In Pascal, there was a high and low value, and that was the only way you could do it. Now, you can do anything to determine whether or not a for loop exits, as long as it uses the concept of TRUE (non-zero) or FALSE (zero). The third part is the section that increments values. It is run right before the conditional statement. In our case above, we simply added 1 to i. You could, if you wanted, add 2 every loop, or 3, or multiply by 4, and so on. In short, the sequence of events is:

1. The Initializing Statement is ran. (Above, "i = 0") 2. The Conditional Statement is checked. If it's FALSE (aka zero), the loop ends. (Above, "i < 10") 3. The block of code inside the for loop is ran. 4. The Incrementing Statement is ran. (Above, "i = i + 1;") 5. Start back on step 2. (ie, run the code again)

Let's show you some examples of the for loop. Let's say you had an array of ten integers, and you wanted to assign 500 to each integer. You could ten assignment statements, but it's easier just to say:
for (i = 0; i < 10 ; i = i + 1) { taco[i] = 500; }

First, in the initializing statement is executed, and i is set to 0. Then, the loop begins, each time incremented by 1. First, the statement is "taco[0] = 500", then the next time through it's "taco[1] = 500", then "taco[2] = 500", and so on, until it has looped ten times. At that point, when i is set to 10, it checks the statement "i < 10". Since 10 isn't less-than 10, the statement is FALSE, and the for loop exits. Let's say we had two arrays of 50 integers, burrito and salsa, that we wanted to add together into a third array, chimichanga. Since it's alot of repetition, it's the perfect candidate for a for loop! Look at the code below:
for (i = 0 ; i < 50 ; i = i + 1) { chimichanga[i] = burrito[i] + salsa[i]; }

This is much easier than writing out:


chimichanga[0] = burrito[0] + salsa[0]; chimichanga[1] = burrito[1] + salsa[1]; chimichanga[2] = burrito[2] + salsa[2]; ...

And so on, 50 times! Hopefully you understand how the for loop works now. If you're still a little confused, please, experiment on your own. If you're still having problems, just remember the form:
int i; for (i = (START VALUE) ; i < (END VALUE) ; i = i + 1) { (LOOP) }

Which will loop i from (START VALUE) to (END VALUE), each time executing (LOOP).

Write a program that creates a int, a double, a char, and a bool. Create a program that assigns a value to an int and a double. Write a program to calculate the number of seconds in a year. Your local taco factory just went to the metric system! Convert the current size of your 5 inch tacos to centimeters. Hint: 1 inch = 2.54 Centimeters Write a loop that executes 10 times, each time printing out how many times it has looped. Create an array of 100 integers, setting each to their number in the array (ie, set the 5th element is set to 5, and so on), and then print out each one. Recall that to print out a number, you can say :
cout << burrito << endl;

Where burrito is a variable inside a program. (More on this next chapter)

MegaTaco Inc, makers of the world's best tacos, have decided to replace all of their current 10 ounce tacos with 10.5 tacos. Their current computer system stored the size of their tacos as an int. Think of a way to change the int 10 into 10.5 inside a program. Create a program that multiples an array of 5 integers (try using a for loop) and then multiplies them each by a constant. Modify the above program to print out the array before and after multiplying.

Throughout the ages, tutorials have always used the phrase "Hello, World!" to signify the first example program. Keeping with tradition, we'll be showing you how to print out lines, starting with the above, during the course of this chapter. We cannot, unfortunately, help you learn how to read in characters in this chapter -while our Java C++ tools are nice, they do not have the ability to open up a live session to the C++ compiler, they only spit out its results. We hope to someday expand the tutorial to things like this; in the mean time, please use a C++ compiler of your own, if you have one. If you don't, you should think about purchasing one, as you really can get a lot more out of C++ if you can make your own programs that you can give out to others. For similar reasons, we can't also help you learn file access. Our C++ compiler runs in a special fashion to make sure you can't blow up a computer when you're running buggy programs;think of it as putting a raging bull in a padded room and letting him bounce around. We have others to consider on the system we use, so we can't allow you to create or read files. Sorry. However, most of the concepts there are really very simple, and should be almost identical to the concepts you'll learn for printing out text. We will offer (through the "more info" icons) the tutorials on how to do file access and how to read in characters, however, to curious minds. Please, do not try running those programs in our Java editor -- it won't work. Now that we've gotten those ground rules down, let's get going.

Let's start off by talking about the C++ Pre-Processor. What is it? It's a way of telling the C++ Compiler to manipulate your program before it compiles it. For instance, say your program had grown so big that you wanted to have it split into two files. You could then tell the Pre-Processor to add one file to the beginning of the other during the compile. The compiler would see them as one big file, even though they were really two. The way you communicate with this Pre-Processor is by using # as the first character in a line, followed by a command to send to it. Let's try using the
include

option, which adds in another file at that point:


#include "nacho"

This command adds a file named "nacho" to the program where you put this line. So, if the file you had the #include in looked like:
I want to eat #include "nacho" tonight!

And the file named "nacho" had in it:


some good, yummy nachos

The output the compiler would see would be:


I want to eat some good, yummy nachos tonight!

The Pre-Processor's main use, you'll find, is in including headers. What are they? Headers are like units in Turbo Pascal for MSDOS. The idea is that whenever you want to call functions that are built into the language (like printing out to the screen), you #include the file that defines these functions. In this tutorial, we'll only be using these header files:
Header Name iostream.h math.h Use Printing out to the screen and reading the keyboard Math functions, like square roots and logarithms

These files are called system headers, because they are not just files you created, they are part of the compiler. To #include them, you put them in between a < and a >; iostream.h would be included by saying "#include <iostream.h>". This tells the PreProcessor that you want it to look where it keeps the compiler's system headers, and not where you keep your personal files. So let's try including both of them in a file:
#include <iostream.h> #include <math.h>

Pretty easy, eh? Notice that each one is on it's own line. This is a must, because it's very important that the # be at the very beginning of each line you want to use it in.

Now that we know how to include the headers for printing to the screen and reading from the keybord, we're ready to talk about cout, the black box. Why do we say that? Well, cout (pronounced "see-out") is an object in C++ that we can't really say how it works. All we know is that if we give it data, it can put it on the screen. Because of this lack of knowledge about what's "inside the box", we say it's a black box. So how do we give this cout thing data, you ask? This is the neat part. You use a syntax that really looks like what it does. Let's try using cout (which is defined in iostream.h) in a small program. Take a look:
#include <iostream.h> void main(void) { cout << "Hello, World!"; }

Note: You might not recognize a bit of the stuff here. Don't worry about it, all will be revealed in chapter 3. Think of the stuff you don't recognize as the "Begin" and "End" of C++. Notice the << symbols? They are symbolic of arrows, and might give the impression that the string "Hello, World!" is pointing to cout. This is exactly what's happening! The symbol means to pass data from one thing to another, in this case, passing "Hello, World!" to cout, which somehow manages to print out that string. The end result is the same as this Pascal statement:
write('Hello, World!');

Of course, as the above Pascal may have tipped you off, this statement does not do a carriage return at the end to go down to the next line. How can we do that? Luckily, C++ defines another mystery object, called endl(short for end-line, as in "end the line"), that we can pass to cout to move the cursor down to the next line. So, let's try it!
cout << "Hey World! It's me again. Got any Tacos?"; cout << endl;

Notice that we can send endl to cout, even though it isn't a string. Remember that cout can be given every standard type of data that there is in C++, be it a string, a number, a character, or the special cursor-movers (such as endl). For instance, look at this use of cout:
int a; float b; a = 4; b = 52.2 cout cout cout cout cout cout cout cout << << << << << << << << "Hey World, it's me. Again."; endl; "World, do you like the number "; a; " or "; b; " better?"; endl;

Hopefully that was fairly easy to understand. However, please take a moment to go through it slowly; Although it may seem too easy to waste time on, cout is what you'll use more than anything else in C++, so don't short-change your knowledge of it to save a few minutes. To help you out, here's its output:
Hey World, it's me. Again. World, do you like the number 4 or 52.2 better?

Here's the cool part -- you don't have to put each of those pieces of the second line in different statements! You can combine them all by simply using << between the pieces of data. Here's an example of this trick:
cout << "Hey World, it's me. Again." << endl;

Neat, huh? The way this works is that the C++ compiler runs this in two steps. First, it executes "cout << "Hey World, it's me. Again."", which you might find easier at this point to think of as a function in Pascal. Then, the statement returns the value of cout; this means that the entire block of "cout << "Hey World, it's me. Again."" turns into "cout", which of course means that the remaining line looks like "cout << endl", which is run just as if it had been on a different line. Using this feature of C++, let's reduce the program at the top of the page to a couple lines:
int a; double b; a = 4; b = 52.2;

cout << "Hey World, it's me. Again." << endl; cout << "World, do you like the number " << 4 << " or "; cout << 52.2 << " better?" << endl;

See how much easier that is? We hope you'll recognize that it's kind of like Pascal's Write and Writeln's ability to list variables in-between text. One thing that's neat about the way C++ does it, though, is that you can put many carriage returns in a single statement. Take this line, for example:
cout << "World, what's up?" << endl << endl << endl << endl << endl << endl;

Of course, if there's an out, there has to be an in, and if there's a cout, there has to be a cin. cin is another "black box" as we talked about earlier -- we don't know how it manages to read in from the keyboard, but it does, and we're thankful for it. cin is remarkably similar to cout, so let's just jump in and use it:
#include <iostream.h> void main(void) { int pepper; cin >> pepper; }

Notice the >> operator? It is, obviously, the opposite of the << operator, in that it takes data from cin and assigns it to pepper. Since pepper is an int, cin will automatically convert whatever you type into an integer, if it can; if you type in something like "Nachos", don't expect it to be able to turn that into a number.

What does the #include <iostream.h> do? What is the difference between #include <iostream.h> and #include "iostream.h"? Create a for loop that prints out the numbers 1 through 100. Add an if statement to the above program that prints out "I like Nachos" instead of any number greater than 80. Create a while loop that multiples the number 6.2 by itself until it is learger than a million. Have the program print out the number of times it had to loop. Rewrite the above program, declaring 6.2 and 1 million as constants. Write a program to print out all the odd numbers from 1 to 100. Hint: for loops usually jump ahead 1 integer... Money conversion Mexican Peso to US Dollar Current exchange rates are about $.133 to 1 Peso or 7.48 Pesos per $1.00 A microwave burrito costs $.69 at the grocery store, write a program to tell the cost in pesos. Write a program (Not in CERD!) to read in a number from the keyboard, and then display every number between 1 and that number.

You may have been wondering what the "void" thing means. In fact, you probably were wondering what the deal with "main" is. Man, do we have to answer everything for you? ;) C++ gets rid of the "function or procedure" decision entirely -- since they're almost the same anyway, C++ just has one! Call it a function or a procedure, it's really not important; for our purposes, though, we'll call them functions. You've already seen this piece of code from the last chapter :
void main(void) { cout << "Hello World!\n"; }

Let's start off with the first line, which defines the function (or procedure) "main":
void main(void)

Here's how that statement works. The first word, "void", describes what the function returns. "void" is a term C++ uses to say "nothing"; when you use void, it's a lot like procedures, as nothing is returned. If you wanted to have the function return an integer, you would say something like:
int main(void)

Now that you've seen how to declare what your function is going to return, how do you actually return a variable? It's actually pretty easy. Anywhere in your function, just say "return" and then the name of your variable. For instance, say you had a function that returned the number of doritos you felt like eating, and inside the function you had a variable named "yum" you wanted it to return. You'd say:
return yum;

At that point, the function stops and that variable is returned. Be careful, this is unlike Pascal, where you could assign the value you would return and the function would keep going. For example, if you had the function say "return yum;", then had it print out "I hate doritos!", it would never get to the part where it prints that messages out. Here's a full example of a function that returns a value:
int number_of_doritos(void) { int yum; yum = 523; return yum; } /* That's a lot of doritos! */ /* Returns the value in yum, stops the function */

cout << "I hate doritos!" << endl; /* Nobody ever sees this */

Passing variables to functions is just as easy! Let's take another look at everyone's favorite example code:
void hello_world(void) { cout << "Hello World!\n"; }

What if you wanted to pass variables to this function, so you could change what it said each time you ran it? You'll be happy to know that it's almost exactly the same as how you did it in Pascal. As you know, you declare an integer named "foo" by saying "int foo". To create a function that gets passed an integer named "foo", all you do is say the same thing in the parenthesis:
void hello_world(int foo) { cout << "Hello " << foo << "!\n"; }

How do you pass more than one variable, you ask? It's just as easy! All you do is separate the variable declarations with commas. Here's an example:
void hello_world(int foo, float boo, char taco) { cout << "Hello " << foo << ", have you seen "; cout << boo << "? I know he's around here somewhere.\n"; cout << "Also, where's " < taco << "?\n"; }

Note that for every parameter in that, a type was given. Unlike Pascal, C++ requires that you say what kind of variable each parameter is.

You know how to pass parameters, you know how to return values -- what's left? Nothing! You're ready to use it! Calling functions in C++ is exactly the same as with Pascal, with one key difference -- if you're not passing any variables to a function when you're calling it, you still need to use the parentheses. Here's an example :
int taco, warehouse; warehouse = Get_Warehouse(); taco = Get_Number_of_Tacos(warehouse); cout << "I found " << taco << " tacos in the warehouse. Yum!\n";

The above example starts by declaring two integers, taco and warehouse. The fictional function Get_Warehouse is then called, and its return value is assigned to warehouse. On the next line, Get_Number_of_Tacos with warehouse as its argument. It's return value is placed in taco, which is then printed out.

One neat thing you can do in C++ is declare two different functions that have the same name. How can this be? By passing different variables, C++ can tell that you want to use one versus another. This might let you make a function that can handle both strings and numbers; just write separate functions with the same name for each type of variable. Sound neat? Well, let's try it out:
#include <iostream.h> void burrito(int nacho) { cout << "You sent an int!" << endl; } void burrito(char foo) { cout << "You sent a char!" << endl; } void main(void) { burrito(42); burrito('A'); burrito(452.2); }

Neat, huh? The first time you call the function burrito, it sees that you're passing an int, so it calls the one that was declared to have an int, and the second time, it sees you're passing a char, so it uses the one that declared a char. But what happens the third time? Unfortunately, since it can't decide to use the one that uses int versus the one that uses char, it won't work. The solution is to cast the call to a function to a type you know has a function defined for it. For instance, we'd change the third line to say:
burrito((int)452.2);

Which would convert the number 452.2 to an int, thereby making it choose the one that uses int as its parameter. This is similar to how you could change things into integers in Pascal by saying:
integer(52.1);

Which would return 52.

C++ has one more neat trick up it's sleeve for functions -- defining Default Parameters. What are they? Well, they're a way of saying what value should be passed to a function if you don't pass anything or have less arguments than are defined. Here's how you define a function to have default values in its argument list:
void salsa(int yum=2)

Note that you're setting the parameter yum to 2. What this is doing is defining a value, 2, that will be put into yum if you don't pass anything. So let's say we call salsa:
salsa();

Even though there was no argument passed, the function still works. Because no value was passsed, the variable yum is set to 2, and the function executes. If we wanted to pass a value, though, it would work just like functions always have. For instance,
salsa(231);

Would set yum, sure enough, to 231. Neat, huh? Now here's the tricky part. If you have a long list of parameters in a function, you have to put the ones with default values at the end. For instance,
void burrito(int taco, int nacho, int chimichanga=0, int beans=0)

is good, but
void burrito(int taco, int nacho=0, int chimichanga=0, int beans)

is bad, and won't work. Why not? Well imagine if you tried calling this function with 3 arguments. Did you want to send values for taco, nacho, and beans, or did you want to send values for taco,chimichanga, and beans? It gets much too confusing and could be interpreted many ways, so it's not allowed in C++.

Write a function that is passes an int and returns a double. Write a function that returns the number of seconds in a year. Use the number it returns to figure out how many seconds there are in a century. Write a function that is passed an integer and returns that integer multiplied by a number. Use constants. Create a for loop goes from 1 to 50, each time calling a function which prints the number out. Create a if statement that calls a function. Have the funtion return 1. What happens? Create a function that converts Ounces to Pounds. Figure out how many pounds a 5 ounce taco is. Try, inside a function, modifying one of its parameters. What happened to the variable you passed to the function after the function ended? Did it change? Why do you think this is? (The answer is in Chapter 6!)

C++ uses pointers very much like Pascal does; The differences, more often than not, are very small. Let's look at how to declare pointers in both Pascal and C++: Pascal :
p : ^Integer;

C++ :

int *p;

In both cases, the difference between declaring an integer and a pointer that points to an integer (we'll say "pointer-to-int" from now on) is a single character. It is important that you notice that in Pascal, you're declaring p to be of type pointer-to-int, while in C++, you're declaring a pointer whose type is int. The difference? If you declare many pointers on one line in C++, you must make sure to put a * by each of the variables. Also, you can put ints next to pointers-to-ints in a declaration by not putting a * next to the int. Confused? Try reading some of the next examples, and see if they help visualize the concepts. Here are some more examples of declaring pointers:
int *taco, *nacho; char burrito, *salsa; float *chimichanga, margarita;

Notice that you can put both variables and pointers-to-variables on the same line? On the second line, both a character (burrito) and a pointer-to-character (salsa) were both declared. On the third line, a pointer-to-float (chimichanga) and a float (margarita) were both declared. Watch Out! It's easy to see the line
float * chimichanga, margarita;

and think that you are declaring chimichanga and margarita both to be of type pointer-tofloat. This is NOT the case, however. The * only applies to the variable it's right in front of, in this case chimichanga. By making your *'s touch the front of your variables, you can avoid this mistake. Here's what the improved, easier-to-understand version looks like:
float *chimichanga, margarita;

However, if you wanted to declare two pointers-to-float, this is what it looks like:
float *chimichanga, *margarita;

Notice that they both must have *'s next to them, so C++ knows they are pointers. Here's what it looks like in Pascal:
chimichanga, margarita : ^real;

Let's try using pointers in a small program. Take a look at this piece of code:
void main(void) { int *nacho;

/* Declare the pointer-to-int

*/

nacho = new int; /* Give nacho something to point at */ *nacho = 42; /* Assign what nacho points to 42 */ cout << "I feel like I could eat " << *nacho << " nachos!" << endl; }

Let's go over what each line does. First, we say "int *nacho;", creating a pointer-to-int named "nacho". Then, we say "nacho = new int;". What does that do? Well, the part that says "new int" is creating an int in memory, and then, much like a function would, it returns the location of the integer it created. This location is then assigned to "nacho". The equivalent statement in Pascal would be :
new(nacho);

Now that nacho has the location of the new integer we've created, we can start assigning it values. The third line, "*nacho = 42;", is almost the same as saying "assign the integer pointed to by nacho 42". Remember, nacho is the location of the integer, and *nacho is the actual integer. Don't get them mixed up! The last line is another example of working with the value that's pointed at. Notice that we're printing *nacho, the integer, not nacho, the location of the integer.

Pointers are very different from other kinds of variables. Instead of holding actual data, they hold directions for getting to variables. Because of this, you can have a bunch of pointers that all are pointing to the same variable. When you change the variable in one, you're changing it in all of them! Take a look at this piece of code:
void main(void) { int *nacho, *taco; nacho = new int; *nacho = 58; taco = nacho; cout << "I could eat " << *taco << " tacos!" << endl; }

What do you think the output of that program is? Well, besides making the programmer hungry, the program spits out this message :
I could eat 58 tacos!

How did that work? Well, look at what the program is doing. After creating two pointersto-int, it creates an int and assigns its location to nacho. ("nacho = new int") Then, the int pointed to by nacho is given the value 58. Now, here's the tricky part. The next line, "taco = nacho", is giving taco the location of nacho. Once you've assigned the location to taco, either of them can deal with the int you've created.

Variables that you create with new also have to be destroyed when you're done using them. To do this, you say "delete" and then the name of the pointer. (Or, if you created an array, you use "delete[]" and then the name of the pointer to the array) For instance:
int *burrito; int *enchilada; burrito = new int[3]; enchilada = new int; burrito[0] = 4; burrito[1] = 8; burrito[2] = 12; delete enchilada; delete[] burrito;

Seem easy enough, right? Remember that delete works just like free did in Pascal -- The contents pointed to are removed, but not the pointer. You can create more variables and give their location to the same pointer, if you want. You probably noticed that the code created a pointer to "int[3]", and then started using burrito as though it was an array. How can this be? Well, first a quick explanation of what an array really is. Say you create an array of ten integers using the declaration "int salsa[10];". Inside your computer's memory, the program makes a location big enough to hold ten integers, and gives the variable "salsa" the location of the first one. When you say "salsa[5]", it's taking the location of the first part and looking 5 locations ahead. Don't worry if that's a little confusing. The important part is that you know that if you want to create arrays using new, you can. In fact, the whole purpose of new, really, is to create arrays whose size can be determined while the program is running!

Sometimes you might be doing something where you're not sure if the pointer is actually pointing to anything. The answer isn't that different than what you would do in Pascal, really. There's a constant, called NULL, which is assigned to pointers to mean that they don't point anywhere. You may remember Pascal's version of NULL, nil. There really isn't any difference between the two. Here's an example of a check you might do in the middle of a program:
if (taco != NULL) cout << "I feel like I could eat " << *taco << " tacos!" << endl;

Create a pointer, use new to give it something to point to, and assign the pointedto variable a number. Consider the following program:
#include <iostream.h> void main(void) { int *taco; int *burrito; taco = new int; burrito=taco; *taco = 10; cout << "Taco is set to " << *taco << endl; cout << "Burrito is set to = " << *burrito << endl; }

What do you think the output of the above program is? Why do you think that happened?

You didn't think you'd actually learned everything there was to know about the core of C++, did you? Well, you're in for a shock -- there's still a whole chapter of syntax and functions to pour through! Not to worry though. This is critical stuff, we know; and if you take your time reading it, we'll take our time writing it. You might have been wondering how to make records in C++ (Or maybe you haven't, but smile and nod). It's really not that different than in Pascal; in fact, the biggest difference is probably going to be what it's called : a Structure. Let's start by comparing the record in Pascal with the structure in C++: Pascal:
Mexican = RECORD Tasty : Boolean; Color : Integer; Rating: Integer; CookTime : Real; END;

C++
struct mexican { bool tasty; int color; int rating; float cooktime; };

Take a good look at both, and notice how very similar they really are. When you consider the differences in the way the code is written, structures in C++ really do seem as if they're only slightly different from the way Pascal does things. Now that you've seen how to declare them, let's try using them in a program:
void main(void) { mexican lunch; lunch.tasty = false; lunch.color = 0; lunch.rating = 0; lunch.cooktime = 5542.2; cout << "Status of my lunch:" << endl; if (lunch.cooktime > 5000) cout << "I wouldn't know, I'm waiting for it!\n"; else { if (lunch.tasty)

cout << "Yum!\n"; else cout << "Yuck! *Barf* Yech eeww!\n"; } }

Let's go over what that program does. In the first line, it creates lunch, of type mexican. Then, it assigns values to each of variables inside the structure. Luckily, this is exactly how you'd do it in Pascal. The next couple of statements check the values that have been assigned, and print out a message depending on what you have the variables set to. If you have a huge cooktime value, the program prints out "I wouldn't know, I'm waiting for it!"; if you don't, it checks to see whether or not the food is tasty. Yes, not the most useful program, but you can never be too careful when it comes to checking your lunch.

Structures are fairly easy to grasp, but they do have one other small trick to them -- when you're using Pointers-to-structures. Say we create a pointer-to-structure named enchilada. After creating memory and assigning it to enchilada, we're ready to play around with it. Here's where the weird part comes in -- when you're accessing variables from a pointer-to-structure, you use ">" instead of ".". To access a variable named tasty inside the structure pointed to by enchilada, you say:
enchilada->tasty

The -> tells C++ that you want to access the element tasty, which is in a struct that enchilada points to. This is a replacement for the long and very icky version, shown below:
(*enchilada).tasty

If you're a little unsure of that code, heres what it's saying in a breakdown: 1. enchilada is a pointer to the structure. 2. (*enchilada) is the structure. 3. (*enchilada).tasty is the field tasty inside the structure. The key point is that "->" saves you time and confusion.

Before we move on, take a look at some examples and we'll step through them so you can be sure you're learning all this. Here we go..
#include <iostream.h> struct food { int rating; double weight; int ttc; int calories; }; /* /* /* /* Rating, Weight, Time To Seconds out of ten */ in Pounds */ Cook */ it takes to cook */

void main(void) { food good; /* A can of Jolt Cola */ food *bad; /* A school "lunch" */ bad = new food; good.rating = good.weight = good.ttc = good.calories bad->rating = bad->weight = bad->ttc = bad->calories /* Create the school "food" */

10; /* Fill in Jolt Cola's stats */ .2; 0; = 150; 1; /* Fill in School "Food"'s stats */ 5.0; 30; = 1400;

if (good.rating > bad->rating) cout << "I like Jolt Cola more than that icky pseudo-food." << endl; else cout << "I like watching my food glow!" << endl; }

Here's the breakdown: First, a structure named food is defined, detailing a bunch of variables I'd use to describe a food. Don't forget that semicolon at the end of the structure's definition! Inside the main procedure, a variable good is defined of type food, and a variable bad is defined to be of type pointer-to-food. Right afterwards, bad is filled is given something to point at. Note that saying "bad = new food" is just like you've done in the past, nothing's changed. Next, the variables are all given values. Finally, a comparison of good.rating and bad->rating is done; if good.rating is higher (in this code, it is), it spits out a message saying so. If not, is spits out a message saying how much the program likes school lunch. (Only a sick, sick person would change the rating of school food so that it was higher than Jolt Cola, but go ahead and try it for educational value)

Up until now, the only way you've seen to move down a line is by using endl, the mystical-move-down-a-line object. What if we told you there was another, perhaps even better, way to do it? Well, there is, and it's the magic of escape codes. What's an escape code? Well, they are a bunch of codes you can put in the middle of a string that represent actions. They can produce a tab on the screen, move the cursor down a line, back the cursor up, even make the computer beep. They best part is, you put them right inside your strings, so it saves a little work. Escape codes always begin with a "\" followed by a letter. The first one we'll try out is "\n", which moves the cursor down to the next line.
#include <iostream.h> void main(void) { cout << "Hello World!\n"; }

Notice how the "\n" takes the place of having to say "<< endl". Isn't that so much easier? Let's try using some more ones:
#include <iostream.h> void main(void) { cout << "Here cout << "Here cout << "Here cout << "Here cout << "Here cout << "Here }

is is is is is is

a a a a a a

Return (\n) " Tab (\t) " Backspace (\b)" Beep (\a) " Slash (\\) " Quote (\") "

<< << << << << <<

endl; endl; endl; endl; endl; endl;

The above code should explain itself, but here is a list of escape codes you can use and what they mean:
\n \t \b \a \\ \? \' \" Newline Tab Backspace Beep Backslash Question Mark Single Quote Double Quote

Throughout your programming experience you've probably been doing things like adding and subtracting 1 to a variable. C++, in its infinite wisdom, has shortcuts that make it easier to do things like this. Let's look at them. Consider this statement (you've probably seen it a thousand times, in one form or another) :
burrito = burrito + 1;

You've used that every time you needed to add 1 to a variable. Now, behold the easier way!
burrito += 1;

Isn't that easy? It doesn't stop there, though. You can do the same thing with subtraction, multiplication, division, and almost any other operator! Here's a list of commonly used ones: Old Way New Way
i = i + 1 i += 1 i = i - 1 i -= 1 i = i / 2 i /= 2 i = i * 2 i *= 2

What it's doing 1 is added to i 1 is subtracted from i i is divided by 2 i is multiplied by 2

Those should help you out. Let's try using them in a small program:
#include <iostream.h> void main(void) { int fajita; double taco; fajita = 0; fajita = fajita + 4; / Old Way fajita += 4; / New Way! fajita = fajita - 4; / Old Way fajita -= 4; / New Way taco = 5; taco = taco / 2; taco /= 2; / Old Way / New Way!

taco = taco * 2; taco *= 2; }

/ Old Way / New Way!

In that example, we execute the new way right after each old way. Next time you write a program, try using a couple of these. Once you get the hang of them, they'll become very useful, and you'll appreciate whoever was lazy enough to ask for them in the first place. One of the neatest shortcuts allows you to take the "i = i + 1" and "i = i - 1" statements down even farther. If all you want to do is add or subtract 1 to a variable, you can say:
i++; / Add 1 to i

Or
i--; / Remove 1 from i

You'll have to play with those two -- they're really useful, especially inside for loops as the incrementing statement. Here's an example of what we mean:
for (i=0;i<10;i++) { cout << "I is " << i << "\n"; }

The Coalition for the Protection of Nachos wants you to create a structure that defines all the great things about nachos. Create variables named nacho and fajita that list their favorite qualities, and then compare each of the two's qualities, each time giving one of the structures a tally mark (held inside the structure). At the end of the comparisons, figure out which is really better, a nacho, or a fajita. Create a pointer to the structure from the problem above , and then use new to give it something to point at. Fill each of the attributes of the structure with a value and, at the end, print the value out. Try passing a structure to a function. Write a function that returns a structure. What are the advantages of returning a structure? Take some of the examples from Chapter 2 and rewrite them to use \n instead of endl. Write a program that moves the cursor down 10 lines. Write a for using "i++" instead of "i = i + 1". Also, try using "i += 1" after that.

Parameter passing in C++ can be one the easiest things to do, and can also be one of the most confusing aspects of the language. More than any other section in this tutorial, is is very important that you understand how passing works, in all its weird forms. Why? Well, your concepts of how a program runs and keeps track of variables are going to be greatly expanded, hopefully helping you write better code that you can really understand. Let's apply a fictional situation to the problems we'll be facing ahead. Imagine you've found the world's largest burrito in Costa Rica, weighing in at over 80 tons. You meet with a shipping company to get them to move the burrito to New York, where it can be sold. Unfortunately, it's much too heavy to just bring the burrito to their office, so you give them directions where they can find the burrito. Of course, the situation we speak of really is talking about passing huge amounts of data to a function. What if you wanted to pass a structure that you could barely fit in your computer's memory to another function? Just like in the above situation with the superburrito, functions need a way of not being given these gigantic pieces of data. They need directions to the data.

Here's a little background info on passing to function. When you call a function, all the parameters you send to it are copied and given to the function to use. This means that if a function makes changes to the variables it is given, they won't be changed anywhere but inside that function. For instance, look at the following code:
#include <iostream.h> void change_values(int a, int b) { a = 4; b = 5; } void main(void) { int a; int b; a = 1; b = 2; change_values(a,b); cout << "A is " << a << ", B is " << b << "\n"; }

Here's the output of this program:


A is 1, B is 2

Note that the call to change_values did not change the variables sent to it. Why? Because the function changes copies of what was passed to it. So, the question is, how do we get functions to be able to change things we pass to them? The answer is:

Don't give a function data, give a function pointers to data.


So how can we do that? Well, remember that the & operator gives you the address of where a variable is inside your computer; or more to the point, it gives you a pointer to the data. Armed with this knowledge, let's redo the above program:
#include <iostream.h> void change_values(int *a, int *b) { *a = 4; *b = 5; } void main(void)

{ int a; int b; a = 1; b = 2; change_values(&a,&b); cout << "A is " << a << ", B is " << b << "\n"; }

And behold! The gods of C++ smile, and you are presented with:
A is 4, B is 5

Take a look at the above code, and make sure you understand what's going on. The main function passes the address of a and b this time, so the function change_values is passed a copy of the addresses. Using the addresses of a and b, change_values can access their data directly. Think of this concept as calling someone you to give directions to where they left their lunch. Using those directions, you could pick up their tasty enchiladas, and using the same idea, change_values can get to those tasty variables, a and b. You may remember this whole idea as using the VAR parameter in Pascal to pass the real variable instead of a copy.

Let's try another, more practical example. What if you wanted to pass an array of integers to a function? The solution, of course, lies in passing pointers. As you may or may not know, the name of an array is a pointer to the first element of an array. So, if you had int taco[10] as an array in a program of yours, taco would point to your array. If we know how to pass the function the address of the array, the problem is: How do we declare that we're passing the array to a function? There are actually two ways to do it, we'll start with the first. Here's how it looks to pass an array of ints:
void eat_at_joes(int guacamole[])

Take a look at how the array of ints is defined. Notice that there is no number between the brackets -- it's just []. Why is that? Well, using this syntax, you can allow ANY size array of ints to be passed to the function. Let's try passing an array in a program:
#include <iostream.h> void eat_at_joes(int guacamole[]) { guacamole[0] = 1; guacamole[1] = 2; guacamole[2] = 3; } void main(void) { int taco[3]; int nacho[2]; eat_at_joes(taco); eat_at_joes(nacho); }

Notice any problems with the example? Take a look at the first call. First, it defines nacho and taco, both arrays of ints. Then it passes "taco", which is actually the address of the array taco, to eat_at_joes. Baving been passed the address of where the array is, it can now access it directly. Did you notice that the second array, nachos, has only 2 elements? What do you think happens when you pass it to eat_at_joes? The answer, unfortunately, is that it will eventually try to access the third element of the array, which doesn't actually exist. Since arrays are just many variables one after another inside your computer's memory, it will try and access the variable after the second element of the array, which of course doesn't exist.

To add insult to injury, the function might run and compile completely flawlessly. Surprised? Well, remember that C++ is based on C, who was of course famous for letting you read or write into a computer's memory without actually knowing if you actually have variables there. Be careful of cases like this, because if you don't catch them, your program will either:

Run flawlessly, and you will be happy Crash and drive you crazy trying to find the bug

The problem where you are accessing memory that you shouldn't be is sometimes referred to as a "segmentation violation" or a "memory leak" -- either way, it spells trouble. So how can we make sure this never happens? Well, in this example program, we can add a second parameter that tells it how big the array is. As long as we never use more of an array than it says, and always pass the right size, we should be pretty good! Here's the new program with the second parameter:
#include <iostream.h> void eat_at_joes(int guacamole[], int size) { if (size > 0) guacamole[0] = 1; if (size > 1) guacamole[1] = 2; if (size > 2) guacamole[2] = 3; } void main(void) { int taco[3]; int nacho[2]; eat_at_joes(taco, 3); eat_at_joes(nacho, 2); }

By adding the second parameter to eat_at_joes, we can check to make sure we don't do any damage.

When passing pointers, it can often become annoying to constantly add * to every variable whose address you're passing. And now, behold -- It's time to learn how you can pass addresses and have them seem to be a normal variable! C++ has a special kind of variable called a reference variable. This variable must be given an variable when it's created that it can point at. However, once this is done, it acts just like a pointer; since it just points to another variable, when you change that variable, you're changing this one, and vice-versa. So, how do we use this marvelous super-variable, you ask? Simple! This is how it's declared in a program:
int fajita; int &beans=fajita; void taco(double &nacho)

Notice that we declared a regular int before declaring the reference-to-int beans? The reason for this is that references variables must always be assigned a value to point at when they are declared; so, we gave it something to make a reference to. Also you may note that we don't give nacho a value when it's declared. That's ok, because we give it a value when we pass parameters to its function. Let's put the pieces together and try using a reference variable in a program:
#include <iostream.h> /* Improves a taco's rating */ void enhance_taco(int &taco) { taco = 10; /* Mmm, tacos */ } void main(void) { int unyummytaco; int yummytaco; int &taco=yummytaco; unyummytaco = 1; yummytaco = 9; cout << "Yummy Taco is " << yummytaco << "\n"; cout << "Un-Yummy Taco is " << unyummytaco << endl; cout << "Reference Variable Taco is " << taco << endl; cout << "\nRunning the Magic Taco Enhancer..\n\n";

enhance_taco(yummytaco); enhance_taco(unyummytaco); cout << "Yummy Taco is " << yummytaco << "\n"; cout << "Un-Yummy Taco is " << unyummytaco << endl; cout << "Reference Variable Taco is " << taco << endl; }

Here's what the program prints out:


Yummy Taco is 9 Un-Yummy Taco is 1 Reference Variable Taco is 9 Running the Magic Taco Enhancer.. Yummy Taco is 10 Un-Yummy Taco is 10 Reference Variable Taco is 10

Look at the output -- the reference variable has the same as the yummy taco variable! By saying "int &taco=yummytaco", you were able to create taco as a reference to yummytaco; and because of this, taco simply points at yummytaco. The end result is a variable that looks and feels just like a separate variable, but is really a pointer! Also note how the function enhance_taco uses its argument taco just like a regular variable, yet is actually modifying the variables you passed it directly! Once again, the power of reference variables let us do this. You may see this as markedly similar to value parameters in Pascal. It is, and if you are having troubles with pointers in C++, think of int & burrito as the same as var burrito : integer was.

What is the difference between:


void chimichanga(int taco, int nacho)

and
void chimichanga(int *taco, int *nacho)

What happens if you modify a variable in the first? What about the second? Why does this happen?

Your office has asked you to come up with a way to pass an array to a function and have the function multiply everything in the array by 5. Luckily, you've read this chapter, so impress your boss and try it! Write a function that is passed a pointer-to-int and have it return a value inside the integer. Try doing the above example with reference variables. Which one do you like better? Try creating an array of pointers to a struct. Write a for loop that runs new on every cell of the array to fill it up with pointers to real structures. Pass the array to another function and have it print out the contents of each structure.

One of the most important, if not THE most important, differences between C++ and Pascal is that C++ is an Object-Oriented Language. Object-Oriented Languages allow you to organize your code in a more intuitive way than you can in other languages. The main principle in an object-oriented language is that you can create objects which hold data and the methods to manipulate and extract that data. Also, you can decide how visible to make those methods and data to the rest of your program. In C++, these objects are implemented using classes. Classes are very similar in syntax to structs. Here is an example of how to declare a class in C++:
class Salsa { / Methods and data go here };

Notice that the class declaration is marked off by a { and a }, like a struct or any other block in C++. Another important things to notice is that the } is followed by a semicolon. Without that semicolon, most compilers will go bezerk (like a nacho-deprived man) and create all sorts of odd looking errors.

So now you've seen how to declare a class. However, a class with nothing in it isn't a very interesting class. So first we'll add some data about salsa to our salsa class.
class Salsa { public: int chunkiness; int spiciness; };

In the above class, we define variables to store two very important pieces of data, the chunkiness and spiciness of salsa. Information in classes is stored in variables which are declared the same way as you would declare any other variable in C++. (And for those of you wondering about that line which says "public:", don't fret. All will be revealed in time.) But of course, salsa isn't much good to us unless we are able to use it. To puts some salsa in our program, we need to declare a object of the Salsa class, and then use that object. Here's a quick example:
#include <iostream.h> / Insert code from above here void main(void) { Salsa picante; picante.chunkiness = 100; if (picante.chunkiness > 90) { cout << "This is very chunky salsa!" << endl; } }

Data members in a class are accessed like data in a struct: the name of the struct/class variable followed by the data member, with a "." separating the two.

So now you've seen how to use a class in a program. But right now I bet you're asking "What's so special about classes? They look exactly like structs." However, objects in an object-oriented language not only allow you to store information, they also allow you to access that information. This is where methods come in. A method is simply a function defined within a class which can act upon data in that class. Here's one example:
class Salsa { public: int GetChunkiness(void) { return chunkiness; } int GetSpiciness(void) { return spiciness; } int GetQuality(void) { return ((chunkiness + spiciness) / 2); } void SetChunkiness(int chunky) { chunikiness = chunky; } void SetSpiciness(int spicy) { spiciness = spicy; } int chunkiness; int spiciness; };

Here we see our new salsa class with five methods in adition to the two data variables we saw before. These methods provide an interfce with which to manipulate the data stored in the Salsa class. Using these methods, we can manipulate and extract data from a Salsa object without having to know what data types are used to store the data. This is known as data encapsulation, which is an important concept in object-oriented programming. An example of some code which uses the new Salsa class is below.
#include <iostream.h> / Insert Salsa here void main(void) { Salsa riogrande; riogrande.SetSpiciness(75); riogrande.chunkiness = 85; cout << "RioGrande Salsa has a quality rating of "; cout << riogrande.GetQuality() << endl; }

Here we see that even though we have defined methods to access the data in a class, we can still access the data directly like we did before.

Now you've been able to define a class which can contain, modify, and extract data about salsa. But lets say you're the president of a new chimichanga manufacturing company, and you'd like to make this class available to the public for world wide consumption, but you'd like to keep the internal workings of your chmichanga top secret so that those New Yorkers don't go stealing your secret recipe. How would you do this? The last example wouldn't quite work because allthough you provided methods to access the class data, the data itself was still just as accessible without using any methods. This is where public and private come in. Here is a class which will protect the top secret proprietary information:
class Chimichanga { public: void SetChunkiness(int chunky) { chunkiness = chunky; } void SetSpiciness(int spicy) { spiciness = spicy; } char* GetRecipe(void) { return strdup("Haha, Nice try buddy."); } int GetQuality(void) { return ((chunkiness + spiciness) / 2); } private: int chunkiness; int spiciness; char* recipe = "Top Secret"; };

In the previous examples of classes that we've shown you, each class has had only one section, labeled as public. In the above class however, there are two sections, one labeled as public and one labeled as private. This has the effect that you can probably guess at: anything defined in the public section can be accessed anywhere in your program, but anything defined in the private section can only be accessed from other methods within that same class. Note that if you don't label a public or private section in your class, then everything defaults to private, which is easy to forget if you're just making a small class with all public members (and in that case, you should probably use a struct anyway).

Now that you've seen how a class with public and private sections is defined, lets take a look at what you can and can't do to use our Chimichanga class. Do's
Chimichanga specialblend; specialblend.SetChunkiness(95); specialblend.SetSpiciness(85); cout << "SpecialBlend's Rating O' Quality: "; cout << specialblend.GetQuality() << endl; cout << "The Top Secret Recipe is: "; cout << specialblend.GetRecipe() << endl;

All of the class members called in the above class are methods from the public section of the class, so it is okay to call them. The output from the above code would have been:
SpecialBlend's Rating O' Quality: 90 The Top Secret Recipe is: Haha, Nice try buddy!

Now for some Don'ts


Chimichanga specialblend; specialblend.chunkiness = 70; cout << "Special Blend's Chunkiness: "; cout << specialblend.chunkiness << endl; cout << "The Top Secret Recipe is: "; cout << specialblend.recipe << endl;

All three of the uses of specialblend above are illegal, because they try to directly access members which were declared as being private in the class definition. If you were to try and compile this code, the compiler would give you an error like "member `chunkiness' is a private member of class `Chimichanga'". When using classes, a good strategy to use is "If it doesn't HAVE to be public, then it should be private". In most cases it is a good idea to make all data private, and the methods to access that data public. However, you can have public data and private methods as well. And there you have it, a class which will protect Special Blend Chimichanga's secret recipe from evil New York mega-corporations.

And just like any other data type, you can have pointers to classes, pointers to pointers to classes, pointers to pointers to pointers to classes, etc (get the point?). To see how they are implemented, lets take a look at the classic example, the linked-enchilada-list.
#include <iostream.h> class EnchiladaNode { public: int data; EnchiladaNode* next; }; void main(void) { EnchiladaNode *top = new EnchiladaNode; top->data = 5; top->next = new EnchiladaNode; top->next->data = 6; cout << "First there's a "; cout << top->data; cout << " then there's a "; cout << top->next->data << endl; delete top->next; delete top; }

In the above example there are a few important things to notice and remember. First of all there is the sytax for accessing class members from a pointer to a class which is the same as how to access struct members from a pointer to a struct, using the -> notation. also notice that like other forms of pointers, we had to allocate the memory for the class using a new, and then deallocate it at the end using a delete.

Create a Nacho class. Store data members in it to represent your favorite aspects of the nacho, their saltiness, their crispness, their refreshing zing, etc. Create a class which represents your own favorite food, storing any important information about it in private variables with public Set and Get methods. Create a date class which contains a month, day, and year with methods to access the information. Then use that date class as a data member of another Inventory class for your local grocery store to keep information about products, such as expiration date, product name, etc. Create a linked list class with methods to add, delete, and search for nodes in the list. Create a binary tree class with features similar to the linked list class. If you don't know what a binary tree or a linked list is, don't worry about it.

As any fan of Mexican food knows, whenever you make yourself a burrito, you always go through the same sequence of steps to build your burrito out of prime beef, a tortilla, and any other toppings you choose. And when using classes in your programs, you will probably find that whenever you create a new instance of a class, you always go through the same steps of calling a couple of methods to initialize the data in the object. While this works all well and good, it does get on ones nerves to have to type the same thing over and over again. As you may have figured out by now, the fact that we're talking about this means that yep, there is a nice solution to this problem in C++. In C++, you can define a special method in a class called a constructor which is called when you create a new instance of a class. This constructor can take parameters just like any other method. Here's a comparison of a class with a constructor and a class without a constructor:

Without Constructor
class Taco { public: void SetBeefAmount(int ounces) { beefamt = ounces; } void SetToppingAmount(int ounces) { toppingamt = ounces; } private: int beefamt; int toppingamt; }; void main(void) { Taco supreme; supreme.SetBeefAmount(10); supreme.SetToppingAmount(1); }

With Constructor
class Taco { public: Taco(int beefounces, int toppingounces) { beefamt = beefounces; toppingamt = toppingounces; } private: int beefamt; int toppingamt; }; void main(void) { Taco supreme(10, 1);

Although this is a fairly simple example, it shows some of the keys of how to declare and use constructors. There are a couple of key things to note in the above example:

The constructor method has the same name as the class type. (i.e. the Taco class's constructor is called Taco, the Salsa class's constructor would be called Salsa, etc) The constructor does not have any return type. The arguments to the constructor are passed in the instance declaration. (i.e. the line Taco supreme(10,1); creates a new Taco object and calls the constructor with the parameters 10 and 1).

Also, note that the constructor is called as soon as the class is created. In the above example, that would be on the line containing the class declaration. However, if you were to have a pointer to a class, it's constructor would not be called until you allocate memory for what that pointer points to, when you call new.

It's only human nature to destroy that which we build, and programming with classes is no different. Just like there is a set of actions that you do in a class every time you initialize it, there is often a set of actions that you do when you are done using it. Just as we constructed our burrito in the previous example, we go on to the next step of burrito eating, the destruction process where we clean up the mess we left while eating our tasty treat. And similarly, whenever we finish using a class we have to clean up after ourselves by freeing up any memory which we might have allocated earlier while constructing or using the class. This is where destructors come in.
#include <iostream.h> class Taco { public: Taco(int hard) { hardness = new int; *hardness = hard; } ~Taco() { cout << "Destroying taco with hardness "; cout << *hardness << endl; delete hardness; } private: int* hardness; }; void main(void) { Taco hard(10); Taco* soft = new Taco(0); delete soft; }

In the above example, notice that destructor methods have the same name as the class, with a ~ added to the front. The other key point to remember from the example is when destructors are called: with pointers to classes, like soft in the above example, the destructor is called when you delete the pointer (and if you don't delete the pointer in your code, then the destructor will never get called, and you will have what is known as a memory leak). With classes declared staticly, such as Taco hard above, the destructor is called at the end of the function where the object is declared. In the above example, hard's destructor would be called at the end of the main function. C++ does this for you automatically so you don't have to worry about it. This is known as garbage collection.

In all of our previous examples of classes, we have included the actual code for our functions inside the class definition. This is okay for short 1-2 line functions, but once you start getting to long functions, this can get quite cumbersome with class definitions which go on for pages and pages. So, for these longer functions, C++ allows us to define them outside of the class definition.
class Nacho { public: void Prompt(); private: int num; }; void Nacho::Prompt() { cout << "Would you like that nacho with or without cheese?"; cin >> num; if (num > 10) cout << "Wow, that's a lot of nachos, you must be hungry!"; }

Instead of actually declaring the entire function inside the class definition, we just have a prototype which acts as a placeholder. The actual method definition looks just like any other function, with the added "Nacho::" to indicate which class this Prompt method is for (in case you have two classes with the same method names, this is used to differentiate between the two). Inside the method definition, we can access private variables within a class just as we could when the function was defined in the class definition.

As your final lesson on classes, we'd like to diverge from the syntax to teach about a bit of what is considered good programming style when you use classes. After all, what good is a mouth-watering enchilada if it isn't served with a bit of flair? First of all, there is the golden rule of classes: "If it doesn't HAVE to be public, then make it private". Following this will prevent a lot of mistakes where you try to go around a data member's Get and Set methods. Doing so may not have any effect at first, but if you later decide to change how the data is represented in the class, then it is much simpler if you only have to change the code of the Get and Set methods than go through your code and change every mention of that data member. And now that we've seen how to define class methods outside of the class definition, we can introduce another key stylistic point, the separation of .h and .cpp files. The basic idea is simple: put all of your class definitions in one header file, and then put the method definitions in a another file which includes the header file. This reduces clutter and separates the implementation of the class from the definition of its interface. Using our last class as an example, here is how you would split a class up into two files.
nacho.h: class Nacho { public: void Prompt(); private: int num; }; nacho.cpp: #include <nacho.h> void Nacho::Prompt() { cout << "Would you like that nacho with or without cheese?"; cin >> num; if (num > 10) cout << "Wow, that's a lot of nachos, you must be hungry!"; } / The rest of your code, including main, goes here

Create a basic Tortilla class with a constructor for attributes such as crispiness, freshness, etc. The attributes should be stored in private data members. Use the Tortilla class as a data member of a Taco class, along with other members such as amount of meat, toppings, etc. All of these members should be initialized through a constructor which takes all of the data from parameters sent to it. Create a Taco class similar to the last one, but with multiple constructors (remember function overloading?) which can take different parameters (You could say have one constructor for a meatless taco, and one for a very meatful taco). Create yet another Taco class, this time using default parameters in your constructor so that if just a Taco() is created, then the user will get a generic Taco Belle style Taco. With the advent of double decker Tacos, one data member to store the Tortilla just isn't enough. Modify the Taco class of your choosing to contain a linked list of Tortillas (you'll need to create a class for that too). Be sure to properly use new and delete on the linked list in the Taco constructor and destructor.

After you've been programming for a while, you get used to being able to add two numbers together with the "+" operator, subtract them with "-" operator, etc. But when you start creating your own classes, you've found that you can no longer do that, at least from what you know now. For example, lets say that you have a burrito class, and in this burrito class you have an add_burrito method which combines the toppings from another burrito into the current burrito, to create one super burrito. However, as you begin using this class in a program, you find that you are often combining burritos in an attempt to find the supreme burrito. But typing add_burito every time is beginning to get on your nerves. You really wish you could just add them together using a "+" operator like you can with numbers, but you can't. Or can you? This is where operator overloading comes in, which we'll delve into a bit more in the next section. Operator overloading, like classes, has no real equivalent in Pascal. It allows you to "redefine" how certain operators, such as "+" and "-", work when used with your own classes. It is called operator overloading because you are "overloading", or reusing, the same operator with a number of different possible uses, and then the compiler decides how to use that operator depending on what operands it has.

So now you ask, what is this operator overloading stuff, how will it help me make the supreme burrito, and what the heck does "binary operator overloading" mean? Lets take this one step at a time. First, a quick example of operator overloading.
#include <iostream.h> class Burrito { private: int amtbeef, amtbean; public: Burrito(int beef, int bean) { amtbeef = beef; amtbean = bean; } Burrito operator + (Burrito newburrito) { int newbeef = amtbeef + newburrito.amtbeef; int newbean = amtbean + newburrito.amtbean; return Burrito(newbeef, newbean); } }; void main(void) { Burrito b1(5,10), b2(10,5), b3; b3 = b1 + b2; }

Notice a couple things about the method which defines the "+" operator for the Burrito class:

The method is called from the class which precedes the operator, and the object which comes after the operator is sent as the parameter. In the above example, this means that the operator called is b1's "+" operator, and the parameter (newburrito) is b2. The operator method can access private data members of the parameter which it is sent. (For example, newburrito.amtbeef and newburrito.amtbean in the code above) The above is an example of a binary overloaded operator, because we are overloading an operator which has two operands, also known as a binary operator (as opposed to a unary operator with only one operand, like the postfix/prefix operators ++ and --). The operand which is called is the one defined in the object before the operator, and the parameter is the object after the operator. For example, in the above code, the operator used is b1's "+" operator, and the parameter which it is sent (newburrito) is b2.

So now we can go use this class to make gratuitous use of the overloaded "+" operator in our pgram to find the supreme burrito, without having to type addburrito a lot. So we can program faster, and thus find the supreme burrito faster. A win-win situation!

In the last section we breifly mentioned overloading unary operators, such as ++ and --. It really isn't too different from overloading a binary operator such as +. Here's a quick example which will incremenet the data in our burrito variable by one and return the new burrito.
class Burrito { private: int amtbeef, amtbean; public: Burrito(int newbeef, newbean) { amtbeef = newbeef; amtbean = newbean; } Burrito operator ++() { amtbeef++; amtbean++; return Burrito(amtbeef, amtbean); } };

In the above example, we see many similarities to our previous example of a binary overloaded operator. In fact the only real difference is that there is no parameter passed to the operator method, which makes sense since we are only concerned with one operand, which is the object whose operator is being used. However, there is one small caveat that you must keep in mind specifically when overloading the ++ and -- operators. As you saw earlier, the statement b = ++a; does something slightly different from b = a++; if both a and b are ints. The first is the same as a = a + 1; b = a; , the second is the same as b = a; a = a + 1; . However, when overloading the ++ (or --) operator, you cannot make any distinction between whether the operator was used as a++ or ++a if a is a Burrito (or some other user-defined type). Both uses of the operator have the same effect.

Not only can we overload operators such as + and ++ in our own user-defined classes, we can also overload typecasting functions such float() and int() to convert our own classes into basic types (for example, for turning a custom String class into a character array). This is very similar to the other operator overloaders we have seen.
class Burrito { private: int amtbeef, amtbean; public: Burrito(int newbeef, int newbean) { amtbeef = newbeef; amtbean = newbean; } operator int() { return (amtbeef + amtbean); } };

The above class contains an int() operator, which we can use similarly to any other type cast, such as:
void main(void) { Burrito b1(10,6); int i1 = int(b1); cout << i1 << endl; }

That short example would print out the number 16, and demonstrates how to use operator overloading to convert a user-defined class to a basic type. To go the other way (from a basic-type to a user defined class), you simply use a constructor, like we saw when learning about constructors.

Overloading operators can be very useful in making your programs easier to read, write, maintian, and understand. However, they can also just as easily obscure the meaning of your code if not used carefully. Here are some things to watch out for:

Conflicting meanings. It is entirely possible to overload the ++ operator for a class and make it do anything you want it to. However, someone reading your code later is goign to assume that the ++ operator does something to the class which is analogous to incrementing it by one. Multiple overloaders for one class. It is also possible to create more than one operator overloader method in a class as long as each one has a different parameter type. For example, you could create a String class, and then have multiple versions of the + operator, one which takes a single character as a parameter, one which takes another String class, etc. Again, you just need to be careful that your use of overloaded operators makes your code clearer, not more complex. Not all operators can be overloaded. Most operators can be overloaded, but there are a few exceptions, which are: o The ternary operator ?: o The class/struct member access operator . o The scope resolution operator ::

Create an Int class which represents and int, and then overload the + and operators so that you can add and subtract two Ints. Make the Int class even more useful by overloading more operators of your choosing (++, --, /, *, %, etc). Be sure that if you overload divison that you truncate correctly. Create an Int class with multiple versions of the + operator so that you can add an Int to another Int, a regular int, a float, etc. Support any types that come to mind, but be sure to truncate floating point types. Create conversion overloaders for the Int class so that it can be converted to an int, a float, etc. Choose whatever types you like. If you get bored, find a way to convert an Int into a Taco. Create a Taco class which uses this brand new Int class to store any attributes which previously were ints. Create a Taco class (you can make a basic one or use one from before) and overload the + operator for it. If yo've created a Taco class which supports the linked list of Tortillas in the last chapter, then overload the + operator for the Taco class, making sure that the linked lists of Tortillas are added together correctly (so that by adding two Tacos, you get a double decker Taco).

Você também pode gostar