What exactly is a programming language? As a loose definition, a programming language is a tool used by a programmer to give the computer very specific instructions in order to serve some purpose for the user. A program is like a recipe. It outlines exactly the steps needed to create something or perform a certain task. For, example, when baking chocolate chip cookies, there are certain steps that need to be followed:
mix eggs, butter, sugar in a bowl
add flour, baking soda, and flavorings
mix until creamy
add chocolate chips
bake in the oven.
For a person who has made cookies before and knows the amounts of each ingredient to use, this recipe is sufficient, however, for a person who has never baked cookies before, this recipe will not do. That person would need a recipe like the following:
place two eggs in a bowl
add 1.5 c. butter to the eggs
...
bake cookies for 10-12 minutes at 375 degrees or until brown
There is still a problem with the preceding recipe. The first instruction says to put two eggs in the bowl, but it doesn't say to shell them first! This may seem like common sense, but it illustrates a fundamental concept: computers do exactly what they are told, no more, no less. When writing a program, a programmer must outline every possible step and scenario that could occur.
The first programming languages that emerged, were assembly languages. These languages are exactly the instruction set of a specific processor. These languages are very low-level and hard to understand. For example, say we wanted to add two numbers, 3 and 4 and get a result:
| in C++: | in assembly: | |
int a = 3 + 4; |
ldl 3, R1 |
The version in C++ is easier to understand and simpler to write. This is analagous to the differences in the first recipe presented and the second recipe presented. The first recipe expressed the method of baking cookies on a high level, while the second method went more in depth on how to actually mix and bake the cookies. Programmers write their code in a high level language and then use a compiler to translate their code into an assembly language and then into a machine language that will run on the machine they are using.
Programs consist of algorithms. An algorithm is just a well-outlined method for completing a task. The above recipes could be called algorithms for the task of baking cookies. A high level algorithm for adding two numbers could be as follows:
ask the user for the first number
ask the user for the second number
add the two numbers
display the result on the screen
This high-level abstraction is not actual code. However, it does express the ideas of a program, and is called pseudo-code. Often, programmers will design their programs in pseudo-code, and then use this to write their actual code.
So, why is there more than one programming language? It may seem that a standard language should be agreed on, since all languages are translated using a compiler anyways. However, languages are often designed with a specific use in mind, and some are better than others for dealing with certain problems. So if a programmer is capable of writing a compiler (which is a very complex piece of software) then they can design and create a language.
The most important thing to remember about programming languages is that they are only an abstraction! Programming languages were created so developers could express their ideas on a higher level than a computer can understand. Once a user has a good concept of how computers work, and has learned a few computer languages, it becomes much easier to pick up new languages.
A programming language is a tool used by programmers in order to specifically outline a series of steps that a computer is to take in a certain instance. High-level programming languages allow a programmer to express ideas on an abstract level, and forces the compiler to worry about the low-level implementation details. This allows for faster development of applications, since applications are easier to write. There are even fourth generation languages emerging as viable programming languages. Recall that machine code is considered first generation, assembly languages are second generation, compiled languages are third generation. Fourth generation languages are actually code-generating environments, such as Microsoft's Visual Basic. These fourth generation languages allow programmers to express their ideas visually, and the environment then writes the code to implement these ideas.
Why Program in C++?
what is so special about C++? Why should you use C++ to develop your applications? First, C++ is not the best language to use in every instance. C++ is a great choice in most instances, but some special circumstances would be better suited to another language.
There are a few major advantages to using C++:
1. C++ allows expression of abstract ideas
C++ is a third generation language that allows a programmer to express their ideas at a high level as compared to assembly languages.
2. C++ still allows a programmer to keep low-level control
Even though C++ is a third generation language, it has some of the "feel" of an assembly language. It allows a programmmer to get down into the low-level workings and tune as necessary. C++ allows programmers strict control over memory management.
3. C++ has national standards (ANSI)
C++ is a language with national standards. This is good for many reasons. Code written in C++ that conforms to the national standards can be easily integrated with preexisting code. Also, this allows programmers to reuse certain common libraries, so certain common functions do not need to be written more than once, and these functions behave the same anywhere they are used.
4. C++ is reusable and object-oriented
C++ is an object-oriented language. This makes programming conceptually easier (once the object paradigm has been learned) and allows easy reuse of code, or parts of code through inheritance.
5. C++ is widely used and taught
C++ is a very widely used programming language. Because of this, there are many tools available for C++ programming, and there is a broad base of programmers contributing to the C++ "community".
A Brief History of C++
The C++ Programming Language is basically an extension of the C Programming Language. The C Programming language was developed from 1969-1973 at Bell labs, at the same time the UNIX operating system was being developed there. C was a direct descendant of the language B, which was developed by Ken Thompson as a systems programming language for the fledgling UNIX operating system. B, in turn, descended from the language BCPL which was designed in the 1960s by Martin Richards while at MIT.
In 1971 Dennis Ritchie at Bell Labs extended the B language (by adding types) into what he called NB, for "New B". Ritchie credits some of his changes to language constructs found in Algol68, although he states "although it [the type scheme], perhaps, did not emerge in a form that Algol's adherents would approve of" After restructuring the language and rewriting the compiler for B, Ritchie gave his new language a name: "C".
In 1983, with various versions of C floating around the computer world, ANSI established a committee that eventually published a standard for C in 1989.
In 1983 Bjarne Stroustrup at Bell Labs created C++. C++ was designed for the UNIX system environment, it represents an enhancement of the C programming language and enables programmers to improve the quality of code produced, thus making reusable code easier to write.
![]()
Bjarne Stroustrup
What is a Variable?
A variable is a place to store a piece of information. Just as you might store a friend's phone number in your own memory, you can store this information in a computer's memory. Variables are your way of accessing your computer's memory.
Of course, your memory changes over time. Your friend moves across country and has a new phone number, and your friend's new phone number will replace the old one in your memory. Over time, as you acquire new friends, your memory will keep changing to store different pieces of information. Likewise, a computer's memory can change over time, if you tell it to. Since variables are your access point to your computer's memory, it makes sense that you'd be able to change the information in a computer's memory; otherwise, they wouldn't be called variables (they'd be called statics).
Why should you care about variables? Variables are the essence of any computer program! Without variables, computers would be useless. Imagine a program which asks the user for two numbers and adds them together, and prints the result.
# AddTwoNumbersSounds simple, right? But let's do a little role-playing to see what the computer has to do to execute this program. Instead of this interaction between a person and a computer, let's imagine the same kind of conversation between two people, Sol and Frank.
Enter the first number: 2 Enter the second number: 5 The sum of 2 and 5 is 7. #Sol: Hey Frank, I just learned how to add two numbers together.After Frank says "2", Sol has to store that number in his memory somewhere. It may be stored in short-term memory, but he has to store it somewhere before Frank gives him the second number. Even if Frank were to give him two numbers in the same sentence, Sol would have to store the numbers somewhere in his memory to add them together.
Frank: Cool!
Sol: Give me the first number.
Frank: 2.
Sol: Ok, and give me the second number.
Frank: 5.
Sol: Ok, here's the answer: 2 + 5 = 7.
Frank: Sheesh! This guy is unbelievable!In the sample program described above, the computer would most likely store "2" in a variable, then store "5" in a variable, and then calculate the sum by calculating the sum of the numbers store in the two variables.
Although there are similarities between a person's memory and a computer's memory, there are some pretty big differences. In C++, you need to grab a little piece of the computer's memory before you can use it. In other words, you have to tell the computer that you're planning to store a number in a variable before you can actually do it. This is called declaring a variable. To declare a variable, you need to know what kind of information it will store (i.e., will it store a number, or a text-string, or something else) and how you plan to refer to the variable (i.e., the variable's name). C++ imposes fairly strict rules on how you can name your variables:
- variable names must begin with a letter
- variable names are "case-sensitive" (i.e., the variable "myNumber" is different from the variable "MYNUMBER" which is different from the variable "mYnUmBeR")
- variable names can't have spaces
- variable names can't have special characters (typographic symbols)
What can you name your variables? In general, variable names can be composed of letters, numbers, and underscores (_). However, C++ reserves certain keywords which have special meaning to the language, and you are not allowed to use any of these keywords as variables names. Some examples of C++ keywords are
int,for,else, andclass. You can, however, use keywords in the middle of a variable name, such as "foreign" or "classical". For a complete list of C++ keywords, please see Appendix B.
What is a Control Statement?
The flow of control
When a programmer is crafting a program, it is good practice to break the program down into pieces that can be thought of independently. Once the program has been completed, we can think of its execution as being a series of these pieces that work together in a certain sequence. These pieces then pass the control of the program between each other. While one piece has the control, the other pieces are inactive. This is known as the flow of control in a program. If our program had three parts, called Start, Middle, and End, the flow of control could look like:
![]()
control statements
Control Statements, then, are ways for a programmer to control what pieces of the program are to be executed at certain times. The syntax of Control statements are very similar to regular english, and are very similar to choices that we make every day. There are two basic types of control statements: branching statements and loops.
branching statements
We will first look at branching statements. Let's say Julien is shopping at a mall and he finds a CD that he wants to buy. Julien then checks his pocket to see if he has enough money to pay for the CD. When he pulls his money out of his pocket Julian may be thinking: "if I have more money than the price of the CD then I will buy the CD." In pseudocode that thought could be translated into:if (my_money > cost_of_CD) then
buy_CD
else
get_a_job
end if;Note that the pseudocode statement end if means "end the previous if statement." This is to make it clear what statements are inside the if statement and what statements are outside of the if statement.
Depending on a certain condition a certain series of events will be executed. Another type of branching statement is called a switch statement. A switch statement is just a shorter way of writing a lot of if statements. Switch statements will be explained in more detail in the next subsection.
nesting control statements
In the preceding situation, if Julien doesn't have enough money, before going out to get a job, he could look for a friend to borrow the money from. Now the pseudocode for this could be:if (my_money > cost_of_CD) thenNow there is one control statement that is inside of another control statement. This is known as nesting.
buy_CD
else
if (see_a_friend) then
borrow_money
else
get_a_job
end if;
end if;
loops
Let's pretend now that Julien was buying a house instead of a CD. If Julien wanted to buy the house without taking a loan from the bank, he would have to wait until he had enough money to buy the house. The pseudocode for this could be:if (my_money > cost_of_house) thenBut this means that Julien would only check once if he had enough money to buy the house. What we want to describe is the fact that Julien needs to keep waiting until he has enough money to buy the house.
buy_house
end if;while (my_money < cost_of_house)This is a loop statement. Another loop statement is the for command. Let's say Julien wanted to add up how much money he would make over the next year. Let's say Julien is paid $500 twice each month. The pseudocode to figure this out could be:
work_more
end while;
buy_house;int total=0;A for statement execute a specified number of times. In this instance it executes 24 times (12 months * 2 pay periods per month). In this example, it would actually be easier to write this code as:
for x = 1 to 24
total = total + 500
next x;
output total;total = 24 * 500;But, what if Julien earns interest on any money that he saves? Now a for statement will be a handy tool. Let's decide that Julien spends $400 a month on rent, $75 a month on food, and $100 a month on other expenses. Let's also assume that Julien earns 2% per month on any money that he saves. Now our pseudocode could look like:
output total;int monthly_expenses= 400 + 75 + 100;
int monthly_income = 1000;
float interest_rate = .02
// compute the amount Julien will have saved after one year
int total = 0;
int interest_earned =0;
for x = 1 to 12
interest_earned = total * interest_rate;
total = total + interest_earned + monthly_income - monthly_expenses
next x;
// display the value
output total;Control statements allow a programmer to craft a program so that certain parts of code execute multiple times, or not at all based on the current state of the program. Control statements are the most basic form of logical control within a program.
Branching Statements (if, else, switch)
the if statement
The first type of branching statement we will look at is the if statement. An if statement has the form:
In an if statement, condition is a value or an expression that is used to determine which code block is executed, and the curly braces act as "begin" and "end" markers.if (condition)
{
// code to execute if condition is true
}
else
{
// code to execute if condition is false
}Here is a full C++ program as an example:
//include this file for cout
#include <iostream.h>
int main() {
// define two integers
int x = 3;
int y = 4;
//print out a message telling which is bigger
if (x > y) {
cout << "x is bigger than y" << endl;
}
else {
cout << "x is smaller than y" << endl;
}
return 0;
}In this case condition is equal to "(x > y)" which is equal to "(3 > 4)" which is a false statement. So the code within the else clause will be executed. The output of this program will be:
x is smaller than yIf instead the value for x was 6 and the value for y was 2, then condition would be "(6 > 2)" which is a true statement and the output of the program would be:x is bigger than ythe switch statement
The next branching statement is called a switch statement. A switch statement is used in place of many if statements.
Let's consider the following case: Joel is writing a program that figures interest on money that is held in a bank. The amount of interest that money earns in this bank depends on which type of account the money is in. There are 6 different types of accounts and they earn interest as follows:
account type interest earned personal financial 2.3% personal homeowner 2.6% personal gold 2.9% small business 3.3% big business 3.5% gold business 3.8% One way for Joel to write this program is as follows: (assuming also that Joel has assigned numbers to the account types starting with personal financial and ending with gold business.)
// declare a variable to keep track of the interest
float interest = 0.0;
// decide which interest rate to use.
if (account_type == 1){
interest = 2.3;
}
else {
if (account_type == 2) {
interest = 2.6;
}
else {
if (account_type == 3){
interest = 2.9;
}
else {
if (account_type == 4){
interest = 3.3;
}
else {
if (account_type == 5){
interest = 3.5;
}
else {
// account type must be 6
interest = 3.8;
}
}
}
}
}That code is hard to read and hard to understand. There is an easier way to write this, using the switch statement. The preceding chunk of code could be written as follows:
switch (account_value){
case 1:
interest = 2.3;
break;
case 2:
interest = 2.6;
break;
case 3:
interest = 2.9;
break;
case 4:
interest = 3.3;
break;
case 5:
interest = 3.5;
break;
case 6:
interest = 3.8;
break;
default:
interest = 0.0;
}The switch statement allows a programmer to compound a group of if statements, provided that the condition being tested is an integer. The switch statement has the form:
switch(integer_val){
case val_1:
// code to execute if integer_val is val_1 break;
...
case val_n:
// code to execute if integer_val is val_n break;
default:
// code to execute if integer_val is none of the above
}The default clause is optional, but it is good programming practice to use it. The default clause is executed if none of the other clauses have been executed. For example, if my code looked like:
switch (place) {
case 1:
cout << "we're first" << endl;
break;
case 2:
cout << "we're second" << endl;
break;
default:
cout << "we're not first or second" << endl;
}This switch statement will write "we're first" if the variable place is equal to 1, it will write "we're second" if place is equal to 2, and will write "we're not first or second" if place is any other value.
The break keyword means "jump out of the switch statement, and do not execute any more code." To show how this works, examine the following piece of code:
int value = 0;
switch(input){
case 1:
value+=4;
case 2:
value+=3;
case 3:
value+=2;
default:
value++;
}If input is 1 then 4 will be added to value. Since there is no break statement, the program will go on to the next line of code which adds 3, then the line of code that adds 2, and then the line of code that adds 1. So value will be set to 10! The code that was intended was probably:
int value = 0;
switch(input){
case 1:
value+=4;
break;
case 2:
value+=3;
break;
case 3:
value+=2;
break;
default:
value++;
}This feature of switch statements can sometimes be used to a programmers' advantage. In the example with the different types of bank accounts, say that the interest earned was a follows:
account type interest earned personal financial 2.3% personal homeowner 2.6% personal gold 2.9% small business 2.6% big business 2.9% gold business 3.0% Now, the code for this could be written as:
switch (account_value){
case 1:
interest = 2.3;
break;
case 2:
case 4:
interest = 2.6;
break;
case 3:
case 5:
interest = 2.9;
break;
case 6:
interest = 3.8;
break;
default:
interest = 0.0;
}Loops (for, while, do)
the for statement
the for statement has the form:for(initial_value,test_condition,step){
// code to execute inside loop
};
- initial_value sets up the initial value of the loop counter.
- test_condition this is the condition that is tested to see if the loop is executed again.
- step this describes how the counter is changed on each execution of the loop.
Here is an example:
// The following code adds together the numbers 1 through 10
// this variable keeps the running total
int total=0;
// this loop adds the numbers 1 through 10 to the variable total
for (int i=1; i < 11; i++){
total = total + i;
}So in the preceding chunk of code we have:
- initial_condition is
int i=0;- test_condition is
i < 11;- step is
i++;So, upon initial execution of the loop, the integer variable
iis set to 1. The statementtotal = total + i;is executed and the value of the variabletotalbecomes 1. The step code is now executed andiis incremented by 1, so its new value is 2.The test_condition is then checked, and since
iis less than 11, the loop code is executed and the variabletotalgets the value 3 (sincetotalwas 1, andiwas 2.iis then incremented by 1 again.The loop continues to execute until the condition
i<11fails. At that pointtotalwill have the value 1+2+3+4+5+6+7+8+9+10 = 55.the while statement
The while statement has the form:while(condition) {
// code to execute
};
- condition is a boolean statement that is checked each time after the final "}" of the
whilestatement executes. If the condition is true then thewhilestatement executes again. If the condition is false, thewhilestatement does not execute again.As an example, let's say that we wanted to write all the even numbers between 11 and 23 to the screen. The following is a full C++ program that does that.
// include this file for cout
#include <iostream.h>
int main(){
// this variable holds the present number
int current_number = 12;
// while loop that prints all even numbers between
// 11 and 23 to the screen
while (current_number < 23){
cerr << current_number << endl;
current_number += 2;
}
cerr << "all done" << endl;
}The preceding example prints the value of
current_numberto the screen and then adds 2 to its value. As soon as the value of the variablecurrent_numbergoes above 23, the while loop exits and the next line is executed.The output of the preceding program would be:
12
14
16
18
20
22
all doneWhat is a Function?
Up until this point, every line of code we've shown you has done a simple task, such as performing an arithmetic operation, or checking a boolean condition, or assigning to a variable. Functions allow you to do a whole lot in one line of code. Instead of performing a simple task, a single line of code can display a menu of choices, or compute complicated three-dimensional transformations, or even play Tetris!
How is this possible? Functions allow you to group a series of steps under one name. Remember in Section 1.1 when we were baking chocolate chip cookies? We had to perform the following steps:
place two eggs in a bowlIn C++, and in most programming languages, you can give a name to a series of steps. Let's say we want to call this procedure "bake cookies". Then, our algorithm for baking cookies becomes:
add 1.5 c. butter to the eggs
...
bake cookies for 10-12 minutes at 375 degrees or until brownbake cookiesWe've just created a function to do the work for us. Don't get too excited - you still need to know how to bake the cookies. You still need to know that the first step is placing two eggs in a bowl, and that the second step is adding butter to the eggs. In this example, what you would do is write a function calledbakeCookies(C++ won't let you put spaces in the names of functions or variables) that performs the series of steps above, and then whenever you wanted to bake cookies, you would call the functionbakeCookies, which would execute the lines of code necessary to carry out the procedure.Note: When we say you are calling the function
bakeCookies, we do not mean that you are giving it the namebakeCookies- you've already done that by writing the function. We mean you are executing the code in the functionbakeCookies. "Calling a function" really means "telling a function to execute".What are functions good for?
At this point, we've seen one reason why functions are useful. Functions let us create logical groupings of code. If someone is reading your code, and she sees that you call a function
bakeCookies, she knows immediately that you are baking cookies. If, on the other hand, she sees that your code places eggs in a bowl, then adds butter, etc., it will not be clear right away that you are trying to bake cookies. Lots of recipes start out with putting eggs in a bowl, and lots of recipes add butter to the eggs. By the time she reads the last line, she might realize that you are baking cookies, but only if she is familiar with the recipe. It's possible that she won't realize that you are baking cookies at all! The point is, functions make your code much easier to read.There is an even better reason to use functions: they can make your code shorter. Fewer lines of code is not always desirable, but every time you write a line of code, there's the possibility that you are introducing a bug. Functions start to reduce the number of lines of code when you call them repeatedly.
Suppose that you want to mail out invitations to eight of your friends for a cocktail party. Let's assume that you need to do the following procedure in order to invite your friend Hank.
write Hank's name on the invitationIt takes five lines of pseudo-code to invite one friend, so it takes 40 lines of pseudo-code to invite eight friends. It would look like this:
write Hank's name and address on the envelope
place the invitation in the envelope
seal and stamp the envelope
drop the envelope in the mailwrite Hank's name on the invitationThat's a lot of repeated code, and any time you repeat code like this, you are more likely to add a bug to your program. For example, look at what we're doing with Flavio's invitation - we are placing it on, not in, the envelope! We sealed his envelope and dropped it in the mail, but there was no invitation inside. Flavio will receive an empty envelope and he'll be mighty confused. That's a mistake that resulted from having to type the same lines of code over and over again.
write Hank's name and address on the envelope
place the invitation in the envelope
seal and stamp the envelope
drop the envelope in the mail
write Ann's name on the invitation
write Ann's name and address on the envelope
place the invitation in the envelope
seal and stamp the envelope
drop the envelope in the mail
write Alicia's name on the invitation
write Alicia's name and address on the envelope
place the invitation in the envelope
seal and stamp the envelope
drop the envelope in the mail
write Whitney's name on the invitation
write Whitney's name and address on the envelope
place the invitation in the envelope
seal and stamp the envelope
drop the envelope in the mail
write Greg's name on the invitation
write Greg's name and address on the envelope
place the invitation in the envelope
seal and stamp the envelope
drop the envelope in the mail
write Mi Young's name on the invitation
write Mi Young's name and address on the envelope
place the invitation in the envelope
seal and stamp the envelope
drop the envelope in the mail
write Flavio's name on the invitation
write Flavio's name and address on the envelope
place the invitation on the envelope
seal and stamp the envelope
drop the envelope in the mail
write Brian's name on the invitation
write Brian's name and address on the envelope
place the invitation in the envelope
seal and stamp the envelope
drop the envelope in the mailFunctions can substantially reduce the amount of pseudo-code you need to write to invite your eight friends to the party. It seems unlikely that you'd be able to reduce this at all - each of your friends has got to have their own personally addressed invitation, and all of the envelopes have to be sealed and stamped and placed in the mail. How are we going to reduce the number of lines of code? Let's create a function called
inviteToPartywhich does the following procedure:write Hank's name on the invitationNow that we have this function, we can call it eight times to invite our eight friends:
write Hank's name and address on the envelope
place the invitation in the envelope
seal and stamp the envelope
drop the envelope in the mailinviteToPartyYou probably noticed a problem with doing it this way. We're inviting Hank eight times, and none of our other friends are going to receive invitations! Hank will get invited eight times because the function invites Hank to the party, and the function is being called eight times. The solution is to modify the function so that it invites friend to the party, where friend can be any of your friends. We'll change our function so that it looks like this:
inviteToParty
inviteToParty
inviteToParty
inviteToParty
inviteToParty
inviteToParty
inviteToPartywrite friend's name on the invitationand then we'll change the way in which we call the function:
write friend's name and address on the envelope
place the invitation in the envelope
seal and stamp the envelope
drop the envelope in the mailinviteToParty (friend = Hank)Now, each time we call the function,
inviteToParty (friend = Ann)
inviteToParty (friend = Alicia)
inviteToParty (friend = Whitney)
inviteToParty (friend = Greg)
inviteToParty (friend = Mi Young)
inviteToParty (friend = Flavio)
inviteToParty (friend = Brian)friendis a different person, and each of our eight friends will be invited. We've just reduced the number of lines of pseudo-code from 40 to 13 by using a function, and our code became much easier to read. (We also got rid of that bug whereby Flavio received an empty envelope.)All of the examples on this page were written in pseudo-code, but the next page describes how to write functions in C++.
Summary
Think of a function as a black box.
A "black box" is a convenient analogy for something that happens by magic. How does the black box work? It takes some inputs, and swirls them around inside the box, and produces some kind of output. Each function can swirl around the inputs in a different way, however that function so chooses. How a function will use the inputs to come up with the outputs is the essence of the function.
We just said that functions are like black boxes because we throw in some inputs, and something happens by magic, and some output comes flying out. The black box metaphor is really only appropriate when you are using other people's functions. When you write the function yourself, you have to know exactly how the function swirls up the inputs. It's not magical for you, because you decided how the function works. However, if you give your function to someone else for them to use, you can tell them it's a black box.
Function Basics
Now that you know what a function is, let's look at function syntax. We've already seen that a function can take some inputs, do some stuff, and then produce an output.
The basic form of a function definition is this:
It's called a function definition because we are defining the function. We are saying, "This is a function named function_name, whose inputs are input_1, input_2, etc., and whose output is output. When it is called, the function will execute the code in between its curly braces (output function_name (input_1, input_2, input_3, input_...) {
// code to execute inside function
}{}).At this point, let's refine our sample function definition. When programmers talk about functions, instead of the word input they usually use the word parameter. A parameter to a function is nothing more than an input to a function. At the same time, instead of using the word output, programmers generally refer to the return of a function. A particular function "returns" a value. So, here is our updated function definition:
return_type function_name (parameter_1, parameter_2, parameter_3, parameter_...) {
// code to execute inside function
}Notice that in place of
output, the function definition says return_type. That's because when we are actually writing a function definition, we'll put the return type there, immediately preceding the name of the function. The return type is nothing more than a plain old variable type, such asint, ordouble, etc.Similarly, parameters use variable types also. If the first input to a function is an
int, then the first parameter will be something likeint my_number. We'll see whatmy_numberdoes in just a moment.A Real Function!
Enough dilly-dally, let's see a real, working, C++ function that actually does something! Suppose we need a function that, converts a temperature from Celsius to Fahrenheit. Here it is:
What is an Object?
Objects defined
So what is an object? An object is a component of a program that knows how to perform certain actions and to interact with other pieces of the program. Functions have previously been described as "black boxes" that take an input and spit out an output. Objects can be thought of as "smart" black boxes. That is, objects can know how to do more than one specific task, and they can store their own set of data. Designing a program with objects allows a programmer to model the program after the real world. A program can be broken down into specific parts, and each of these parts can perform fairly simple tasks. When all of these simple pieces are meshed together into a program, it can produce a very complicated and useful application.
Let's say that we are writing a text-based medieval video game. Our video game will have two types of characters: the players and the monsters. A player has to know the values of certain attributes: health, strength, and agility. A player must also know what type of weapon and what type of armor they possess. A player must be able to move through a maze, attack a monster, and pick up treasure. So, to design this "player object", we must first separate data that the player object must know from actions that the player must know how to execute. The definition for a player object could be:
Player Object:
data:
health
strength
agility
type of weapon
type of armor
actions:
move
attack monster
get treasure
END;Member Data and Member Functions
Data that an object keeps track of is called member data and actions that an object knows how to do are called member functions. Member data is very similar to variables in a regular function in the sense that no other object can get access to that data (unless given permission by the object). Member data keeps its values over the life of an object.
Objects and Instances
There is a very important distinction between an object and an instance of an object. An object is actually a definition, or a template for instances of that object. An instance of an object is an actual thing that can be manipulated. For instance, we could define a Person object, which may include such member data as hair color, eye color, height, weight, etc. An instance of this object could be "Dave" and Dave has values for hair color, eye color, etc. This allows for multiple instances of an object to be created. Let's go back to the medieval video game example and define the monster object.
Monster Object:
data:
health
skin thickness
claws
tail spikes
actions:
move
attack player with claws
attack player with tail
END;Now, our game could have one instance of a player:
Player Instance #1:and our game could have two instances of monsters:
data:
health = 16
strength = 12
agility = 14
type of weapon = "mace"
type of armor = "leather"
END;Notice how an instance of an object contains information on member data, but holds nothing about member functions. Every instance of the Monster object performs "attack player" the same way. There is a series of steps in this member function. But each instance of the monster has its own value for the member data. In the preceding example, we can tell the two monsters in our game apart, because of their member data. One monster is tough and the other monster is weak.
a tough one: and a weak one: Monster Instance #1:
data:
health = 21
skin thickness = 20
claws = "sharp"
tail spikes = "razor sharp"
END; Monster Instance#2:
data:
health = 9
skin thickness = 5
claws = "dull"
tail spikes = "quite dull"
END;Let's say that we had a "Battle" function in our game. The pseudocode for it may go something like the following:
Function Battle(parameters: _player = the Player Object instance
_monster = the Monster Object instance)
turn = PLAYER;
while ((_player's health > 0) AND (_monster's health > 0)) {
if (turn == PLAYER){
player attack's monster;
turn = MONSTER;
}
else {
monster attack's player
turn = PLAYER;
}
}
} // END FUNCTION BattleIn the "attack" phase, the attacking person would somehow deduct points from the defending person. Let's say that the player was fighting with the weaker monster. The weaker monster's health value is 9. If the player attacked the monster and did 5 points of damage to the monster, the monster's new health value would be 4. The monster keeps this value as its health value until it is undated again. So if the monster ran away at this point, and later in the game, the player discovered the weaker monster again, it's health value would still be 4.
Summary
Objects are ways of bundling parts of programs into small, manageable pieces. Objects are simply a definition for a type of data to be stored. An instance of an object contains meaningful information, these are manipulated by the program. There can be more than one instance of an object. Instances of objects keep track of information, called member data, or instance variables. This data is kept track of by the instance until it no longer exists. Object instances also know how to perform certain functions, called member functions, or class functions. Every instance of an object performs the same steps when carrying out a member function, although the steps can be influenced by the instances' present member data.
Object Design
There are entire books and long college courses that discuss Object design, I will go through the basics. As discussed in the previous section, An object (synonymous with a class in C++) has data that it remembers and actions that it can perform. So once it has been determined how an object fits into a program, it's member data and member functions can be determined. The question becomes how to determine what role within a program an object is will play.
The role that an object plays within a program should be able to be defined in one to three short sentences. If it takes more than this to define (generally) an object's role, then there should be more than one object. For instance, good concise role's for an object would be:
- Manages all requests into a data structure
OR - Arbitrates turns in a multi-user game
OR - does all data type conversions within program
OR - easy interface to reading, writing, and parsing files.
Drawing pictures that describe the functionality of objects can be a big help when designing a program. Pictures can often describe the relationship between objects better than a paragraph of words. Objects relate to each other in the following ways: ownership (contains), contained-by, knows-about, doesn't-know-about.
Here's a picture of how some of the objects in the text-based medieval video game relate to each other:
![]()
Players and Monsters need to be able to fight each other. Otherwise it wouldn't be a very exciting game. When the Player and a Monster are Battling they battle through a third object, the BattleMgr. The BattleMgr decides which Battler acts first, and eventually, which battler wins. So the Player object and the monster object need to know about the BattleMgr, and the BattleMgr needs to know about both the Player and the Monster.
We have already decided on the attributes of a Battler, so let's add these to the picture.
![]()
Remember our pseudo-code for a battler:
Player Object:Notice that the actions are not listed in the picture, Just the attributes (data). Weapons and Armor are their own type of objects so players/monsters must know about one of each of these types of objects. The reason that health, strength, and agility are treated differently will become clear later. For now, understand what we are trying to accomplish by drawing a picture: we want to first of all understand the relationships between objects. Secondly we want to talk our way through the program with this picture and make sure that we aren't leaving something out.
data:
health
strength
agility
type of weapon
type of armor
actions:
move
attack monster
get treasure
ENDLet's move to a more complex example. In our game, a player can move through a maze encountering Monsters to battle, and weapons and treasure to pick up.
We still have Players, Monsters, and a BattleMgr. We also have a GameDatabase (GameDB) which keeps track of all the rooms in the maze and what is in them. We also have a RoomManager (RoomMgr) that keeps track of the current room where the player is and interfaces with the GameDB when the player moves to see where the player ends up.
Here is the diagram:
![]()
So let's go through some parts of the game. The player starts the game and decides to go east: so the Player object tells the RoomMgr that the player is going east. The RoomMgr checks that the move is valid and then asks the GameDB for the next room.
We already have a few problems. The RoomMgr needs an instance variable to keep track of the current room. How does the RoomMgr know if "east" is a valid move? Well, each room will have to have 4 instance variables: east, west, north, and south. Their values will be 1 if that is a valid direction and 0 if it is not a valid direction. What about the contents of the room. What can rooms contain? We'll have to create a Treasure object and rooms will have to keep a list of what Treasure they contain and also what Monsters reside in that room.
How will we keep a list of an arbitrary number of items? We will use what is called a linked list. This will be a good example of reusing pieces of code.
So where do we go from here? In the next section, we will try and pseudo-code out our program. We will determine how we want everything to work and then write it down in pseduo-code.
Before going into the next section take a shot at re-drawing the previous picture and figure out how you would organize the objects and what instance variables and member functions they would contain. Your picture will no doubt be different from ours. Not that that means you are right or wrong. One of the interesting things about programming is that there are often many different ways to solve the same problem.
Declaring a Class
Once you have designed your objects, writing the C++ code is simple. The hard part is designing objects that will interact well with each other, that will do everything you need them to be able to do, but nothing more. There is almost no new syntax you need to learn to write objects in C++. It involves using the syntax for variables and functions, so make sure you understand this syntax before continuing.
Let's continue to flesh out our text-based adventure game. First, we'll write the code for our
Playerobject. In Chapter 6.1, we decided that players would have the following attributes, or member data: health, strength, agility, type of weapon, and type of armor. To simplify this example, we'll just use the first three attributes. We also wanted thePlayerto have the following actions, or member functions: move, attack monster, and get treasure.To write the code for our object, all we need to do is declare the member data and member functions, and wrap them up inside an object declaration. Here's how it's done:
class Player {This is a completely valid, working class declaration for the
int health;
int strength;
int agility;
void move();
void attackMonster();
void getTreasure();
};Playerobject. All we did was declared our member data (variables for our object) and member functions (functions that our object can use), and enclosed them inside a class declaration block. The class declaration block consists of the keyword class, followed by the name of the object, in this casePlayer, a pair of braces, and a semi-colon.Of course, this object won't be able to do anything, because we haven't defined its member functions. Inside the class declaration, we said that the
Playerobject would be able to do things like move, attack monsters, and get treasures; but we did not say how aPlayerwould execute these functions. We need to write a function body for each function, so that aPlayerinstance knows how to attack a monster, for example.Here's the syntax for writing a function definition for a member function:
void Player::move() {
//function body goes here
}In other words, it's almost identical to writing a function definition for a plain-old, stand-alone function. The only difference is that we precede the name of the function, in this case
move(), with the name of the object,Player, and two colons. This tells the compiler that this function is part of thePlayerclass.
Using a Class (Instantiation)
Just as writing a class declaration was an extension of concepts we've already covered, the same is true of the syntax needed to instantiate an object. Instantiating an object is what allows you to actually use objects in your program. You can write hundreds and hundreds of class declarations, but none of that code will be used until you create an instance of an object. A class declaration is merely a template for what an object should look like. When you instantiate an object, C++ follows the class declaration as if it were a blueprint for how to create an instance of that object.
Instantiating an object
The good news is, you already know how to create an instance of an object! It is exactly the same as using a variable. Let's say you want to have four players in your game, each trying to find their way to the end of a maze faster than the others. You might start by creating four instances of your Player object, like this:
Player blueHat;It's as easy as that. Although these objects are all
Player redHat;
Player greenHat;
Player yellowHat;Players, they are completely independent of one another. They were created from the same template, but they can have different attributes. For example, "blueHat" might be a slow, strong player, while "greenHat" might be quick and weak, and "yellowHat" might be a well balanced individual, etc. The thing that makes these objects similar is that they all must have values for strength, health, and agility, but nothing else. They can all move, attack monsters, and get treasures, but that is all they can do. So -- they are similar in the kinds of things they can do and the attributes they must have, but they are different in that they can each have their own values for those attributes.Using an object's member functions
Now that we can create objects, we need to know how to use them. That is, we need to be able to use their member functions. Calling an object's member functions is similar to calling a regular function, with a slight twist.
Suppose someone is playing your adventure game, and they are controlling the player with the green hat. When the person hits the key to attack a monster, you need to make sure that the correct code gets executed so that the right player attacks the monster. The code would look like this:
greenHat.attackMonster();It's very similar to the way that a regular function is called, preceeded by the name of the object on which the function should be called (greenHat), and a period. So, instead of calling the functionattackMonster(), we are tellinggreenHatto call the functionattackMonster. This is the power of C++. You can very easily "delegate responsibility" to the objects you've written, so that what seems like an impossible task, writing a video game, becomes much more manageable.Now let's suppose that
greenHatpicks up a treasure. Somewhere in your program, the following will get executed:greenHat.getTreasure();This will cause the functiongetTreasureto be executed for the player with the green hat only. The other players in the game will not execute this function. Perhaps you writegetTreasureto look like this:void Player::getTreasure() {Suppose that before
health++; // increments the value of the player's health by one
}greenHatpicked up the treasure, the following were the players' values for their healths:AfterblueHat: 14redHat: 11yellowHat: 8greenHat: 11greenHatpicked up the treasure, the values would be:blueHat: 14redHat: 11yellowHat: 8greenHat: 12Notice that only
greenHat's health increased when the functionPlayer::getTreasurewas called; that's because the member function was called ongreenHatonly.
Constructors and Destructors
In addition to all of the member functions you'll create for your objects, there are two special kinds of functions that you should create for every object. They are called constructors and destructors. Constructors are called every time you create an object, and destructors are called every time you destroy an object.
Constructors
The constructor's job is to set up the object so that it can be used. Remember in Chapter 3.2, when we first declared a variable? Before we initialized the variable, it stored a garbage value. We needed to initialize the variable to 0 or to some other useful value before using it. The same is true of objects. The difference is that with an object, you can't just assign it a value. You can't say:
Player greenHat = 0;because that doesn't make sense. A player is not a number, so you can't just set it to 0. The way object initialization happens in C++ is that a special function, the constructor, is called when you instantiate an object. The constructor is a function whose name is the same as the object, with no return type (not even void). For our video game, we'll probably want to initialize our Players' attributes so that they don't contain garbage values. We might decide to write the constructor like this:Player::Player() {We would also have to change the class declaration so that it looks like this:
strength = 10;
agility = 10;
health = 10;
}class Player {
int health;
int strength;
int agility;
Player(); // constructor - no return type
void move();
void attackMonster();
void getTreasure();
};One problem with this constructor is that all of the players will be initialized to have strength=10, agility=10, and health=10. We might want to create players with different values for strength and agility to make our game more interesting. So, we can add a second constructor, which has parameters for strength and agility. Our class declaration would now look like this:
class Player {and we would add a function definition for the alternate constructor, which looks like this:
int health;
int strength;
int agility;
Player(); // constructor - no return type
Player(int s, int a); // alternate constructor takes two parameters
void move();
void attackMonster();
void getTreasure();
};Player::Player(int s, int a) {Now, when we want to instantiate the
strength = s;
agility = a;
health = 10;
}Playerobject four times, we can do the following:Player redHat; // default constructor
Player blueHat(14, 7); // alternate constructor
Player greenHat(6, 12); // alternate constructor
Player yellowHat(10, 10); // alternate constructorDestructors
Destructors are less complicated than constructors. You don't call them explicitly (they are called automatically for you), and there's only one destructor for each object. The name of the destructor is the name of the class, preceeded by a tilde (~). Here's an example of a destructor:
Player::~Player() {
strength = 0;
agility = 0;
health = 0;
}Since a destructor is called after an object is used for the last time, you're probably wondering why they exist at all. Right now, they aren't very useful, but you'll see why they're important in Section 8.3.
Protect your Private Parts
At the beginning of Section 7, we used the following example of a class declaration:
class Player {Although this is perfectly legal C++, we left out an important part of class declarations to simplify the example. Every data member and member function in a class is either
int health;
int strength;
int agility;
void move();
void attackMonster();
void getTreasure();
};private,public, orprotected. We'll explain the meaning of each in this chapter.Private
Specifying that a data member or member function is
privatemeans that it can only be accessed from within the class. For data members, this means that the data can be accessed or modified only while inside a member function of the class. For member functions, this means that the function can be called only while inside another member function of the class. This is the default, if no specifiers are used.Public
Specifying that a data member or member function is
publicmeans that it can be accessed from anywhere in your code. Thepublicspecifier is less restrictive thanprivate.Protected
Specifying that a data member or member function is
protectedmeans that it can only be accessed from within the class or a subclass. We haven't yet talked about subclasses (Section 10), so don't worry about usingprotectedjust yet. Theprotectedspecifier is less restrictive thanprivatebut more restrictive thanpublic.How do I use these specifiers?
Using
private,public, andprotectedare easy. The specifier affects all data members and member functions until the next occurrence of a specifier. Here's thePlayerclass, with protection specifiers added:class Player {In this example, the
private:
int health;
int strength;
int agility;
public:
void move();
void attackMonster();
void getTreasure();
};privatekeyword begins aprivatesection encompassing the three data members. Thepublickeyword specifies that the next three member functions should bepublic. So, only code which is in aPlayermember function can access the data members, while any code in the program is free to call the member functions in thePlayerclass.Why bother with this stuff?
Specifiers allow a class to be very complex, with many member functions and data members, while having a simple public interface that other classes can use. A class which has two hundred data members and one hundred member functions can be very complicated to write; but if there are only three or four
publicmember functions, and the rest are allprivate, it can be easy for someone to learn how to use the class. He only needs to understand how to use a small handful ofpublicfunctions, and doesn't need to bother with the two hundred data members, because he's not allowed to access this data. He can only access theprivatedata through the class' public interface. Without a doubt, in a small program, using these specifiers may seem unnecessary. However, they are worth understanding if you plan to do any program of reasonable size (more than a couple hundred lines). In general, it is good practice to make data membersprivate. Member functions which must be called from outside the class should bepublic, and member functions which are only called from within the class (also known as "helper functions") should probably beprivate. These specifiers are especially useful in a large program involving more than one programmer.
Inline Functions
We've already seen how to define member functions for a class, as follows:
void Player::getTreasure() {
health++; // increments the value of the player's health by one
}There's another way in C++ to define your member functions. You can define them "inline", inside the class declaration. Here's how you would define
getTreasureinline:class Player {
private:
int health;
int strength;
int agility;
public:
void move();
void attackMonster();
void getTreasure() { health++; } // this is the function definition
};The braces following
getTreasure()contain the entire code for the function. We don't have to define the function later in our code using thePlayer::getTreasure()syntax -- in fact, the compiler won't allow it, because it's already been defined here inside the class declaration.Why inline?
As you probably noticed, it's definitely fewer keystrokes to inline a function. However, another good reason to inline is that you can sometimes speed up your program by inlining the right function. Instead of calling the function every time it is invoked, the compiler will replace the function call with a copy of the function body. If it's a small function which gets called a lot, this can sometimes speed things up.
Depending on the function, it can also be easier to read inline. If it's a function like the following:
class Math { // class declaration
public:
int addTwoIntegers(int a, int b); // function declaration
};
int Math::addTwoIntegers(int a, int b) { // function definition
return a + b;
}it's probably easier to read if it's inlined:
class Math { // class declaration
public:
int addTwoIntegers(int a, int b) {return a + b; } // inlined function
}; // (combined declaration and definition)Why not inline everything?
Since the compiler will copy the entire function body every time the function is called, if it is a large function (more than three or four lines), inlining can increase the size of your executable program significantly. You may want to try to see what kind of speed gains you can achieve by inlining, and also compare the increase in the size of your executable.
And, just as it is sometimes easier to read functions if they are inlined, it is sometimes harder to read inlined functions. If a function is more than one or two lines, inlining it will more than likely distract a reader who is trying to understand how the class works. In these cases, it's probably better not to inline.
What is a Pointer?
So what is a pointer? A pointer is a way to get at another object. Essentially it is a way to grab an instance of an object and then either pass that instance a message or retreive some data from that object. A pointer is actually just an address of where an instance is held in memory.
Some piece of your program can either possess an instance of an object, or know where an instance of an object is. An instance of an object is a chunk of memory that is big enough to store all the member data of that object. A pointer is an address that explains how to get to where the instance is actually held in memory. Here's a quick example:
Our Player object has three pieces of data that it owns: strength, agility, and health. These are a part of the player object. That makes sense in real world terms. The player knows about two other pieces of data: the weapon and the armor that the player possesses. Here's a diagram for an instance of the player object.
![]()
So that is how to conceptually think of pointers. Now what's really going on? Memory in a computer is a complicated thing, but let's reduce it to it's simplest form: one large string of slots with addresses that data can be put in. As in the following picture:
![]()
If we were to access the spot in memory with address 3, we would get the value 45. If we were to access the spot in memory with address 2 we would get the value "Dave". The previous diagram over simplifies two important concepts, however. First, each spot that has an address is the same size as every other spot. Second, what's held in memory is simply data. That is, the information there is just a string of binary data, 1's and 0's. The way that the data is viewed gives it meaning.
With these new ideas in mind let's Take a look at our previous diagram about the player and see what's really going on. Here is the pseudo code for the Player in a little more detail than we have seen:
class Player {
// attributes
int health;
int strength;
int agility;
// pointers to weapons and armor
Pointer weapon;
Pointer armor;
// actions that a player knows how to perform
void move();
void attackMonster();
void getTreasure();
};What follows could be a view of memory. This will seem fairly complex and is not imperative to understanding the c++ language. If it does not make sense right away, come back to it.
I have translated the actual binary values to their corresponding values in the context of our program. In this view an instance of a Player is stored at memory address 4098. The first attribute (instance variable) is there: health is 12. The second attribute is strength, 14. Then agility 16. The next attribute, stored at address 4104 is a pointer to an instance of a weapon object. If we follow that to the bottom of the diagram, there is the name of the weapon, "club" stored as ASCII values at address 6144 through address 6148 (the 0 ends the string). The next attribute for a weapon after name is rating, in this case 2, which means "poor" because I have decided that the rating system should be:
1 = very poor
2 = poor
3 = average
4 = good
5 = very goodNotice that all the memory contains is binary data. It is how that data is viewed that actually gives it meaning.

