You are on page 1of 83

C++:

An Introduction to
Functions and Classes
John P. Baugh








This work is dedicated to my mother Ellen Arlene Baugh (née Phillips)
whose dedication and support are the major reason
I am where I am today.

And in memory of my father, Henry Jackson Baugh Sr.


who didn’t live long enough
to see me graduate high school,
let alone undergraduate and graduate school.
I miss you every day.
Table of Contents
Introduction
About the Author
Who is this book for?
Extra Resources and Information
Chapter 1: Quick and Dirty Review of IDEs
1.1 Basics of IDEs (Integrated Development Environments)
1.2 Using IDEs
Say “Hello World” using Visual Studio
Say “Hello World” using Code::Blocks
Chapter 2: A Quick and Dirty Review of C++ Fundamentals
2.1 Variables and Arithmetic Operators
2.2 Relational and Logical Operators
2.3 Control Structures: How to Control the Flow of a Program
2.4 Closing Comments and Summary for our Quick and Dirty C++ Review
Chapter 3: Functions
3.1 Function Concepts
3.2 Return Values and Parameters
Return Type Classification
Function Classification by Parameters
Passing by value vs Passing by reference
3.3 More Examples and other Function Topics
Multiple Parameters
Function Overloading
3.4 Comments and Brief Summary
Chapter 4: Classes
4.1 Basic Class and Object-Oriented Terminology
4.2 Member Functions and Data Members
Rectangle class
Dog class
4.3 The Three Pillars of Object-Oriented Programming
4.4 Comments on Classes and OOP
CLOSING REMARKS
Contact Information

Introduction

About the Author
John P. Baugh holds a Master of Science degree in Computer Science from the
University of Michigan – Dearborn. He is currently pursuing a Ph.D. in Information
Systems Engineering. While working on his Master’s degree, from 2005 – 2007, he
worked as a research assistant to Dr. Jinhua Guo in the Vehicular Networking Systems
Research Laboratory. Upon completion of his Master’s degree, John went on to work for
Siemens PLM Software as a Software Engineer from 2007 – 2011. He has also taught as
an adjunct lecturer at the University of Michigan – Dearborn since 2005.
In 2011, Prof. Baugh accepted a position as a full-time faculty member of the Computer
and Information Systems department at Oakland Community College – Orchard Ridge
Campus in Farmington Hills, Michigan. He has been Chair of the CIS Department at
OCC since 2014.
In his spare time, he loves playing video games (especially Fallout 4, Starcraft 2,
Minecraft, Diablo III, and a few others), hanging out with friends, and sleeping. A lot. Oh
yeah - and eating. A lot. (In fact, several waiters and waitresses at Buffalo Wild Wings
know him by name.)

Who is this book for?
This book is for anyone wanting to learn more about functions and classes in
C++. I assume you have some experience in C++, ranging from a first year college
student taking a class in C++ to a seasoned professional who wants to solidify his/her C++
knowledge a little bit.
Functions and classes are some of the more difficult topics for many students to work
with, so a short but useful guide to the concepts, terminology, and practical application of
functions and classes is a great addition to anyone’s programming library.
I don’t expect you to be an expert to understand the topics in this guide. However, if you
have never touched an IDE (integrated development environment) such as Visual Studio,
Code::Blocks, CodeLite, or Dev C++, then I’d suggest looking elsewhere before picking
up this book. (Keep your eyes peeled! I’m hoping to get an absolute beginner’s guide out
soon too!) I do a quick review of some fundamental concepts before we dive right in, but
it is probably not enough to become a pro if you’ve never programmed before. If you are
familiar with another high-level language, the review may be enough to get started!

Extra Resources and Information
Go to http://www.profjpbaugh.com for more resources, some tutorials, a list of
books as they come out! If you think there’s a need for a particular book or particular
topic to be covered, e-mail me at profjpbaugh@gmail.com. Enjoy!

Chapter 1: Quick and Dirty Review of IDEs

1.1 Basics of IDEs (Integrated Development Environments)
In order to work with C++, you have to be able to write C++ source code, and
then have it converted into machine code, which the computer can understand.
Ultimately, a computer only understands binary code – the 1s and 0s that represent high
and low electrical signals, respectively. So, a computer doesn’t even directly understand
C++.
For C++, the translation from C++ source code into machine code (also called object
code) is called compilation. When you compile your source code, a machine code
version of your high-level instructions is produced so that a computer can understand it.
The program that does the compiling of your source code is called a compiler. A
compiler is one part of an IDE (integrated development environment.)
Another part of the IDE is the source code editor, which is just a text editor for your
source code. It usually has a feature called syntax highlighting which means that it
understands special C++ symbols and keywords.
Yet another part is the debugger, which helps you find and remove bugs, which are
problems with your code. And, there is also a part of your IDE called the linker/loader,
which links and loads different symbols and libraries so that your source code can use
them. In other words, a lot of really handy things are available to you without you having
to write them from scratch.
There are several popular IDEs for C++ on the market. Some are commercial, and others
are free. If you’re using Windows, then Visual Studio is one of the more popular IDEs.
Visual Studio Community Edition is a full-featured and solid version of Visual Studio,
available from Microsoft for free.
If you’re not using Windows, or you just prefer open source software, then Code::Blocks
and CodeLite are two very popular open source, free IDEs for you to use. On Macintosh
computers, XCode is available and has features to code and compile C++. It is also freely
available from Apple.

1.2 Using IDEs
We’ve learned thus far that IDEs are useful for software development, largely
because they contain multiple tools needed in the software development process. In this
section, we’re going to take a brief look at a couple popular IDEs so that you should be
able to at least create a new project to store your source files, as well as compile and run a
simple program.
Although you may not be using these specific IDEs, most IDEs have similar steps and
concepts involved, so this section should be useful regardless of the IDE you are using.
We’ll use two very popular IDEs used for C++.
Visual Studio
Code::Blocks

Say “Hello World” using Visual Studio
For the examples I’m going to show, note that I am using Visual Studio Professional
2012. This isn’t a mistake, and yes – I’m aware there are more recent versions. As of this
writing, VS 2013 and VS 2015 are both available. But I’m very cozy with the 2012
version for now, although I am well versed in 2013 also and have used 2015. Regardless,
the steps are mostly identical, and the screenshots should be very similar.
In Visual Studio (VS), and many IDEs for that matter, there are a couple major concepts
that we must first understand.
Firstly, in VS, a solution is basically just a container of one or more projects. A project
contains the resources and source code files.
So, without further ado, let us create a project to say “Hello World”.
1. Start Visual Studio
2. Go to File —> New —> Project
In some editions, this is a combined command, and in others it is as shown
above


3. In the New Project dialog box, make sure you are under Visual C++ as the
language
Sometimes, this requires you to click “Other Languages” in the pane on the
left
If you have C++ set as the primary (or only) language you will not have to
worry about this

4. Select Win32 Console Application


5. Click Browse and navigate to a location you want to serve as the directory (folder)
to house your Visual Studio project
6. Make sure to give your project a good name. Above, I have selected to give my
project the name Ch1_VS_Test
7. Click OK

8. At the Win32 Application Wizard dialog, you should just click Next (or just click
Application Settings)



9. Make sure that Console Application is selected and that you have Empty Project
checked

10. Click Finish
11. You should see the Solution Explorer showing your new Solution containing the
new Project
If you do not see Solution Explorer, go to View—>Solution Explorer
12. Now it’s time to create an actual code file. Right-click Source Files, go to Add—
>New Item


13. Make sure that C++ File (.cpp) is selected
If you were working with classes and wanted a header file, you’d select
Header File (.h)
14. Give the file a good name – I’ve chosen main.cpp
Usually, you can leave the file’s location alone – Visual Studio will put the
file within the project folder automatically


15. Click the Add button
16. You should now see the C++ file you just created under Source Files in your
project



17. You should be able to add code in the source code editor portion of the workspace


18. Add the code exactly as above. For your convenience, here it is in a text format:

#include <iostream>
using namespace std;

int main()
{
cout<<“Hello World!”<<endl;

return 0;
}



19. Now, we have C++ source code! We need to convert it to machine code that the
computer can understand. Let’s do this by going to Build—>Build Solution
Some editions of Visual Studio might have slightly different interface
options here

20. Once it is built, it can be run to test it. To do this, go to Debug—>Start without
Debugging
Start with Debugging is fine also

21. You should get output such as the following:

Easy, right? Congratulations, you’ve just written a very simple C++ program and run it in
Visual Studio! Hopefully if you were not familiar with Visual Studio that this at least gets
you started with the very basics.
Now, on to a different IDE!
Say “Hello World” using Code::Blocks
Now we’re going to take a look at the same process in Code::Blocks (also just called
CodeBlocks or Code Blocks) so that we can have a little bit of variety. However, you’ll
notice a lot of what we do will be the same, or at least very similar.
1. Start Code Blocks
2. Go to File —> New —> Project…
Sound familiar?


3. In the New from template dialog, select Console application


4. Click Go
5. If you get the following dialog, click Next
You can check “Skip this page next time” if you don’t want it to show again


6. Select C++ from the Please make a selection list


7. Click Next
8. You should give your project a useful title, and also select the location to put the
project in


9. Click Next and then click Finish
You can leave the default compiler (usually it’s the g++ compiler, which is
an open source compiler used on many different platforms.)

10. Under your workspace, you should see your new project, as well as a Sources
folder
11. If you expand the Sources node, you’ll see that they have already provided a Hello
World source file for you. Cool huh?!
If you needed additional source (or header) files, you’d just go to File —>
New File, and select the appropriate type, giving it a useful name and
location
Note that the full path is expected, so it’s best just to click the … (ellipsis)
button and give your new file a name in the Select filename dialog
12. To build your application, go to Build —> Build
13. To run the application, go to Build —> Run
Super easy, right?!
Most IDEs are fairly easy to get started with. Obviously some are more difficult than
others. However, Visual Studio is an industry-standard development environment for
Windows, and Code Blocks is used a lot in industry, academia, and for personal use on
many different platforms.
Chapter 2: A Quick and Dirty Review of C++
Fundamentals

2.1 Variables and Arithmetic Operators
In computer programming, a variable is simply a named location in memory
(RAM, typically) where data is stored. The data type of the variable is the type of data
that the variable can hold. Data types can include all sorts of types ranging from integers
(whole numbers), floating-point numbers, also called floats (real numbers – those that
can have decimal points), characters (single lexical symbols like single letters, special
symbols, etc.) and Boolean data (a variable which contains the value of either true or
false.) Additionally, in C++, we can create custom types, typically by making use of
classes, which we will see later on.
In order to use a variable, you must first declare the variable. This typically involves
stating a data type, followed by a name for the variable, formally called the variable’s
identifier. You can also store an initial value in the variable using the assignment
operator, the = symbol.
Let’s take a look at some code that assigns values to some variables.

1 #include <iostream>
2
3 using namespace std;
4
5 int main()
6 {
7 int myNum = 15;
8 float myPi = 3.14159;
9 char myFirstLetter = ‘J’;
10 bool isHappy = true;
11
12 return 0;
13 }


In the code above, we can see on lines 7-10, several variables being declared
andinitialized on the same line on which they are declared. On line 7, we declare
an int named myNum . Its value is 15. On line 8, we declare a float named myPi and set
its value to 3.14159. Then, we declare a character variable named myFirstLetter and set
its value to be the character ‘J’. Finally, on line 10, we declare a Boolean
variable, isHappy , and set its value to true .
Note that we can declare and initialize variables on separate lines.
For example:

int myNum;
myNum= 15 ;



We can apply various arithmetic operators to variables and values in order to obtain
some sort of result. The standard arithmetic operators in C++ are the following:

Symbol Name Example/Description

+ Addition operator int a = 2;


int b = a + 4; //b = 6

- Subtraction int a = 10;


operator int b = 10 – 12; //b = -2

* Multiplication int a = 4;
operator int b = a * 3; //b = 12

/ Division operator int a = 10;


int b = a / 5; //b = 2

% Modulus operator //Returns the remainder/residue of a


division problem
int a = 10;
int b = a % 5; //b = 0, because 10 / 5 = 2,
with remainder 0


Note that we can also use compound operators to quickly do any of the above operations
to a variable and some other operand and store the value back into the left-hand variable.
For example,

int a = 150;
a += 50; //a now contains 200, because this is the same as a = a + 50;
a *= 2; //a is now 400
a /= 5; //a is now 80
a %= 3; //a is now 2, since 80 / 3 = 26 (the quotient), and the remainder is 2.


The typical order of operations (PEMDAS), with an additional M for Modulus
(PEMMDAS) applies in C++ just as it does in mathematics.
As a note of terminology, the “things” on either side of an operator are called operands.
So, if we have the following statement:
5 + 12
We would say that the + symbol (the addition operator) has two operands: the 5 and the
12. Note that any operator with two operands is called a binary operator. There are
unary operators in C++ as well, such as:

int a = 5;
a++; //a is now 6
a++; //a is now 7
a—; //a is now 6


2.2 Relational and Logical Operators
We are not limited to simply doing arithmetic. We also have ways of writing
programs so that they can make decisions, which are very useful, particularly with the
control structures we will see in just a little bit.
The relational operators are as follows:

Symbol Name Example

> Greater than 5 > 6 //returns


false
10 > 2 //returns
true

< Less than 5 < 6 //returns


true
10 < 9 //returns
false

>= Greater than or 5 >= 5 //returns


equal to true
5 >= 17
//returns false

<= Less than or equal to 5 <= 5 //returns


true
5 <= 3 //returns
false

== Is equal to (equality) 5 == 5 //returns


true
5 == 7 //returns
false

!= Is not equal to (non- 5 != 5 //returns


equality) false
5 != 7 //returns
true


The relational operators are all binary operators (they take two operands.) The types of
the operands are frequently numeric, but they do not have to be. C++ allows operator
overloading, which means that the operators are often defined to work with many different
types – including objects that are created from classes.
The logical operators are as follows:
Symbol Name Example

&& Logical AND (5 > 3) && (2 < 4) The && and


|| are binary
(also called logical //returns true since BOTH of its operators.
conjunction) operands are true The NOT
operator
|| Logical OR (5 >3) || (20 < 3)
(negation
(also called logical //returns true, since AT LEAST operator: !)
disjunction) ONE of is unary – it
// its operands is true takes only
one
! Logical NOT !(5 > 3) // returns false since operand. It
is quite
(also called logical //5 > 3 is true, NOT true
negation) simple in
// equals false that it just
reverses the
truth value of whatever its operand is.
Whereas relational operators can take many different types as operands (as long as they
are defined properly) and return Boolean values, the logical operators only take Boolean
values as operands and they return a Boolean value. They are used for combining the
values of other operations (frequently relational operations.)
2.3 Control Structures: How to Control the Flow of a Program
In programming languages like C++, we are often concerned with making
decisions based on program state, that is, the values of various variables often taken in
combination. For example, you might want to allow a person to play the “drinking game”
if they are 21 or over, but not allow them if they are under 21. As another example, you
might want to read a file, line by line, and perform various operations on the input – and
you may or may not know how many lines the file contains. These are all examples of
controlling the flow of the program.
There are three primary categories of control structures:
Sequential (also called Linear)
Selection (also called Decision or Branching)
Repetition (also called Iteration or Iterative, or simply just called “loops”)
Sequential structure is pretty easy. C++ executes each statement, one right after the other
from the beginning of the program to the end. This is the default structure of programs.
Selection structure allows the program to choose among alternatives based on a
condition. In other words, the program selects the code to execute (or not execute) based
on some condition being met (or not met.)
The selection control statements available in C++ are:
if
if-else
switch
The if statement allows you to either execute a block (or statement) of code or ignore it.
This is why the if statement is often described as a single-selection control statement.

if(someValue > 15)


{
//do something
}


The if-else statement allows you to select to execute one statement (or block) or another
explicitly. This is why the if-else statement is often described as a double-selection
control statement. Note that you can chain or nest if-else statements as needed to
simulate selecting among multiple alternatives.

if(someValue > 15)


{
//do something
}
else
{
//do something else
}

The switch statement has built in multi-selection control. It can only be performed on an
integral (integer) value, and you select among one or more cases, and possibly a default.

switch(someInteger)
{
case 10:
//do something specific if its value is 10
break;
case 15:
//do something specific if its value is 15
break;
default:
//by default, do whatever is here
}


Repetition structure allows the program to repeat over and over again until a condition is
met. This condition is called the loop continuation condition.
The repetition control statements available in C++ are:
while
do-while
for
Note that since the C++ 11 standard, there is also a special variation of the for loop called
the range-based for loop. This is outside the scope of our discussion and necessity for
this review. Just be aware that if you need to iterate over one of many kinds of collections
of data (called data structures), then you can use the range-based for loops in many of
these situations.
The while loop is structured so that it tests its loop continuation condition first, and if the
condition is true, the body of the loop is executed. Then, the condition is checked again,
and so on. Since it checks its loop continuation condition before executing the body of the
loop, a while loop is classified as a pre-test loop.
Note that if we do not increment the counter (assuming a counter-controlled loop like the
following), the loop will never terminate – at least until you (or your operating system)
force the program to close. This type of look is called an infinite loop, because
algorithmically and theoretically it would continue for eternity without outside
intervention.

int count = 0;
while(count < 10)
{
//do something 10 times
count++; //we MUST move toward termination of the loop
}

The do-while loop is the only post-test loop in C++. It is the reckless younger sibling of
the while and for loops. It executes the code in its body and then checks the loop
continuation condition. That’s why it is classified as post-test.

int count = 0;
do
{
//do something 10 times
count++;
}
while(count < 10);


Note that after the while near the bottom of the do-while loop, there is a semicolon. This
is required.
The for loop is a pre-test loop like the while loop, and it is excellent for loops that require
counter-controlled repetition, because the counter initialization, loop continuation
condition check, and the modification of the counter variable are all done in the header of
the loop.

for(int c = 0; c < 10; c++)


{
//do something 10 times
//do not increment the counter variable inside the body
//it’s already done for us in the header!
}


2.4 Closing Comments and Summary for our Quick and Dirty C++
Review
Even if you’ve been studying C++ for a couple semesters – or even many years –
you might find some of the terminology and classifications in this chapter overwhelming.
Terminology is important. During the past 10 years teaching computer science and
software engineering at various levels, I have had many students come back to me and tell
me that they were able to impress their interviewers, more effectively communicate with
their co-workers, and overall, understand programming better because of knowing the
terminology.
Granted, just knowing definitions does not make you a good programmer automatically.
However, knowing terms like control structure, iterative control, selection control, post-
test loop, pre-test loop, arithmetic operator, relational operator, logical operator, and
many others can help you more fully grasp the language. Also, knowing these terms will
help you become more prepared to read other literature on your own to become a better
developer in many different languages. Don’t let the terms overwhelm you – learn them –
even at a high-level or basic level. Be able to classify them and know what they apply to.
So, I encourage you to, at very least, know the following categories and terms:
Variable
Value
Data type
Control Structure
Three categories:
1. Sequential control structure
2. Selection control structure
if
if-else
switch
3. Repetition/Iterative control structure
while
do-while
for
Post-test vs pre-test loops
Operators and Operands
Arithmetic operators
Relational operators
Logical operators

If you are comfortable with the above terms, can list any of the operators that you’re asked
about (e.g., if I say “What are all the relational operators? What are they used for?”), you
should be able to do well in the subsequent parts of this book.
Chapter 3: Functions

3.1 Function Concepts
In this chapter, we’ll start our journey into functions, which are self-contained,
reusable, callable blocks of code. They are self-contained in that they are given a name
and other information and contain executable code within their associate function code
block. They are reusable and callable in that they promote code reusability by allowing
the programmer (yourself or someone else) to call them (invoke them) wherever they are
needed.
If some of these concepts are a little weak right now, don’t worry. Hopefully they will
make sense in just a bit. Like variables, functions have a type. Specifically, they have a
return type, which is the data type that the function returns or generates in place of a call
to itself. Additionally, you can send information using parameter passing. We will take a
look at that in just a moment.
The general form of a function is as follows:
returnType functionIdentifier([parameters])
{
//do something here
//if it’s value-returning, return a value here
}
Note that the parentheses do appear in the header of the function. However, the square
brackets are there surrounding the word “parameters” to indicate that the parameters are
optional.

3.2 Return Values and Parameters
Functions can be classified in multiple ways. Two popular ways of classifying a
function is by its return type and by its parameters (or lack thereof.)
Return Type Classification
In terms of return type, a function may be classified as one of two kinds:
void function
value-returning function
A void function is a function that performs some tasks and then when it is done, it simply
stops. Its function call (also called function invocation) is not replaced by a value. Let’s
consider the following void function:

void DoSomething()
{
cout<<“In the DoSomething Function!”<<endl;
}



Our DoSomething function starts with the C++ keyword void , because it is… a void
function. No surprise there! This indicates that when the function is called, it will not
leave a value in its place when it’s done performing its tasks. It simply performs its tasks,
and then stops.
In the context of a program, you could write the function and call it like in the following
example (notice I said could – there’s a better, cleaner way that I’ll show you in a
moment.)

1 #include <iostream>
2 using namespace std;
3
4 void DoSomething()
5 {
6 cout<<“In the DoSomething Function!”<<endl;
7 }
8
9 int main()
10 {
11 DoSomething();
12
13 cout<<“In main!”<<endl;
14
15 DoSomething();
16
17 return 0;
18 }

Defining and calling a function


In the code above, you should note that I coded a full function definition on lines 4-7.
This contains the header of the function on line 4, and the body of the function on lines 5-
7. I call (invoke) the function on line 11, and then again on line 15 from inside the main
function.
The output of the above code is the following:

In the DoSomething Function!


In main!
In the DoSomething Function!
Press any key to continue …


This particular output comes from Visual Studio (which is why it says “Press any key to
continue …” after the code output.) Your output after the program is complete might be
different.
Notice that, as we expect, the call to DoSomething on line 11 causes “In the DoSomething
Function!” to be printed once. Then, on line 13, we code a cout statement to just print out
“In main!”. Finally, on line 15, we make another call to DoSomething (causing “In the
DoSomething Function!” to print again), before the return statement on line 17.
Now, I mentioned that there is a better way to work with functions. Although the code
above is syntactically fine (it adheres to C++’s grammar) and the tabbing and formatting is
reasonable and it’s easy to read, there is a coding convention that in a C++ program, the
main function should be the first function in a program file to be defined, that is, to have
its header and body shown.
So, the better way of coding the exact same program is to use a function
prototypebefore main ’s definition. Then, put the definition of the DoSomething
function below main , as follows:

1 #include <iostream>
2 using namespace std;
3
4 void DoSomething();
5
6 int main()
7 {
8 DoSomething();
9
10 cout<<“In main!”<<endl;
11
12 DoSomething();
13
14 return 0;
15 }
16
17 void DoSomething()
18 {
19 cout<<“In the DoSomething Function!”<<endl;
20 }

Using function prototypes


The code just above has the function prototype on line 4. It consists of the return type and
the function signature, that is, the name (identifier) of the function (in our
case, DoSomething ) and then a list of parameters (we have none at this time) between the
parentheses.
The actual function definitionfor DoSomething now appears on lines 17-20. You might
wonder what we’ve gained – besides more lines in our code which seems to be moving in
the wrong direction! We want our programs to be efficient and clean right? Well,
although we’ve added a couple more lines of code and some spaces, keeping a list of
functions at the top above main but leaving main as the first function that is defined allows
us to immediately see where main is, as well as where all the functions are.
So why do we need a function prototype in the first place? Can we leave it out? The
answer is no. In some languages (such as Java), the methods can be defined before or
after when they are called. Note that methods in Java are essentially and conceptually the
same thing as functions in C++.) However, C++ requires that the function be declared
before it is ever called. A function prototype gives the compiler a “head’s up” about what
functions are available before they are called so that it knows that a particular function
exists and to look elsewhere in the code for the actual definition.
So, we’ve talked a lot about functions – how to declare them, what a function prototype is,
and even what a void function is. But we have another return type classification to talk
about: value-returning functions.
As you might have figured out, whereas a void function just performs tasks and doesn’t
produce a value to replace its call, a value-returning function returns a value. Now,
there are many different types of values that can be returned – from the built-in types of
C++ (int, float, double, char, bool, etc.) to custom types and pointers to these types that
you might create yourself.
If you put anything as the return type of a function other than void, then the function is
classified as value-returning.
However, let’s keep things simple and do an example with an integer return type.

1 #include <iostream>
2 using namespace std;
3
4 int GetMyNumber();
5
6 int main()
7 {
8
9 int myInteger = GetMyNumber();
10
11 cout<<“My number is: ” <<myInteger<<endl;
12 cout<<“Another call without using a variable: “<<GetMyNumber()<<endl;
13
14 return 0;
15 }
16
17 int GetMyNumber()
18 {
19 int someNum = 5;
20
21 return someNum;
22 }
23

Defining and calling a value-returning function


In the example above, we show a function prototype for our value-returning function,
named GetMyNumber . Notice that the type of this function is int . This means that when
the function is done performing its tasks, it will leave, in the place of its function call, an
integer.
Notice that the function definition (lines 18-22) has a declaration of an integer variable
(line 20), storing the value 5. Then, on line 22, the value of the local variable someNum is
returned. I could have also just used one line and said “ return 5; ” and foregone the use of a
variable. But I thought maybe this would be a little clearer and give us some more
practice with variables.
Notice that I make two separate calls to GetMyNumber in the code above. On line 9, I call it
in an assignment operation where the variable myInteger will receive the value returned
by GetMyNumber . Remember that anywhere I can use an integer literal (that is, an actual
integer such as 5 or 7 or -56 rather than a variable) or an integer variable, I can also use a
function call to value-returning function that returns a type compatible with an integer.
Since GetMyNumber will return a 5, the variable myInteger will be assigned the value 5 on line
9.
On line 11 I print the variable’s contents to the console. Then, I use the function
call GetMyNumber in a slightly different way on line 13. Instead of storing the result in a
variable and then printing the variable using cout , I directly call the function. Again,
anywhere you can use a literal or a variable of a type, you can call a function that returns
that type (or a compatible type.)

Now, let’s take a look at parameters!
Function Classification by Parameters
As mentioned earlier, we can describe a function based on its return type (which we
discussed in the last subsection.) You can also classify a function based on its parameters
or lack thereof. The two classifications of functions in relation to their parameter lists are:
Parameterless functions
Parameterized functions

The functions we have seen thus far (in the previous subsection) were parameterless, that
is, they had no parameters between their parentheses. This means that these particular
functions do not require any additional information from the calling function, that is, from
where they were called in the code. For example, the main function
called GetMyNumber function in two locations in the most recent code sample. So, the main
function is called the calling functionwhereas the GetMyNumber function is sometimes
referred to as the called (or invoked) function.
A parameterized function is a function that has parameters, or variable placeholders for
values that are passed in. In other words, a parameterized function requires additional
information from the calling function.
Let’s take a look at a simple example. Consider a function whose purpose is to calculate
the square of an integer that is passed in, and return the squared value as a result.
So in this case, we have a value-returning function that takes a single parameter:

1 #include <iostream>
2 using namespace std;
3
4 int Square(int num);
5
6 int main()
7 {
8
9 cout<<“The Square of 5 is “<<Square(5)<<endl;
10
11 cout<<“The Square of 15 is “<<Square(15)<<endl;
12
13 cout<<“The Square of 2 is “<<Square(2)<<endl;
14
15 return 0;
16 }
17
18 int Square(int num)
19 {
20 return num * num;
21 }

A value-returning function that takes a single parameter, and returns the square of it
Note that the function prototype on line 4 not only has a value ( int ) as its return type, but
it also takes an integer as a parameter. As an aside, the name of the integer parameter in
the function prototype does not need to match the name of the parameter in the definition
(lines 18-21, in our case.) In fact, in the function prototype, the identifier is optional. In
other words, we could have just written:
int Square(int);


The definition however requires the identifier as well as the data type. We actually call
the Square function on lines 9, 11, and 13 in the above code sample. However, notice that
the data we pass into the function is different on each of these lines. For example, the
value 5 is passed in on line 9, so that, as we see in the definition, the parameter
variable num in the header for the definition of the Square function (line 18) will hold that
value while its body is executed. In this case, we only use one line of code, on line 20.
This simply takes the value of num and multiplies it by itself ( num * num ) and returns that
value. As you know, the square of a number is produced by taking the value of that
number and multiplying it by itself.
The output of the code above is as follows:

The Square of 5 is 25
The Square of 15 is 225
The Square of 2 is 4
Press any key to continue …


Note that, given different values being passed in, the results are different as well. Think of
Square as a machine. You feed it some sort of raw material (the parameter), and it
produces something out of that raw material (the return value.)
As a matter of terminology to commit to memory for the purpose of professional
communication (and to sound really smart at parties full of programming nerds), the
actual value (or variable) that you pass in when you call the function is called the
argument. The placeholder for that value, in the definition of the function is what is
actually called the parameter.
For example, we’d say that, in our code from earlier, the values 5, 15, and 2 are the
arguments to the three function calls to Square. The variable num is the parameter.
Sometimes you might hear arguments called actual parameters and what I call
parameters referred to as formal parameters. However, that can cause even more
confusion, so I generally prefer using the terms “argument” and “parameter” instead.
Note that some programmers, professors, and authors use these terms interchangeably
sometimes. But just remember that there is a distinction and that distinction could be
useful in various situations, not the least of which might be a job interview. In fact, I have
had students tell me that they were able to impress their interviewers with how they
naturally and fluidly used terminology related to programming like what we’ve covered
thus far (and will cover.) So, it does matter!
Passing by value vs Passing by reference
Another distinction that must be made when dealing with passing parameters is whether or
not the parameters are pass-by-value or pass-by-reference.
You can think of pass-by-value, which is what we’ve done thus far, as pass-by-copy. A
copy of the variable (or literal value) that you pass in is made, stored in the parameter, and
used in the function. If the value of the parameter changes inside the function, it does not
affect the variable or value that was passed in when the function was called. Think of
making a photocopy of an important assignment and leaving it on the dining room table.
Your little brother crawls up onto one of the dining room chairs and proceeds to practice
his skills as a budding artist using crayons all over your photocopy. This would not affect
the original from which you made the copy – only the copy is modified. Thus it is with
pass-by-value.
Variables all have memory addresses. With pass-by-value (the default mode of parameter
passing), as we discussed in the preceding paragraph, a copy of the variable or value is
made and stored in a variable (the parameter.) The parameter has its own memory
address, as would any variable you passed as an argument have itsown memory address.
For example, given our earlier Square function:
int someValue = 15;
Square(someValue);
//… Later on in the code
int Square(int num)
{
return num * num;
}
In this code sample, the variable someValue is passed as an argument, and num is the
parameter in the function definition. Since it is passed by value, the variable
some V alueand num have different memory addresses. When you modify one, it doesn’t
affect the other.
On the other hand, pass-by-reference can be thought of as pass-by-address. In this case,
the parameter will act as an alias for the variable in the calling function. The result is that
whatever you do to the parameter inside the body of the function to which it was passed
by reference will happen to the argument as well.
To indicate pass-by-reference in C++, you use the & symbol.
Let’s take a look at an example with two functions: one that passes by value and one that
passes by reference.

1 #include <iostream>
2 using namespace std;
3
4 void DoNotChange(int a);
5 void Change(int& a);
6
7 int main()
8 {
9 int myInteger = 20;
10
11 cout<<“Initially, myInteger is “<<myInteger<<endl;
12
13 DoNotChange(myInteger);
14
15 cout<<“After calling DoNotChange, myInteger is “<<myInteger<<endl;
16
17 Change(myInteger);
18
19 cout<<“After calling Change, myInteger is “<<myInteger<<endl;
20
21
22 return 0;
23 }
24
25 void DoNotChange(int a)
26 {
27 a = 150;
28 }
29
30 void Change(int& a)
31 {
32 a = 150;
33 }

Examples of Pass-By-Value and Pass-By-Reference


Notice that the function prototypes (on lines 4 and 5) and the definitions
for DoNotChange (lines 25-28) and Change (lines 30-33) are very similar.
The actual code in the bodies of these functions is identical (line 27 and line 32.) All the
code does is assign the parameter a value of 150. Even the function calls on the
parameters (lines 13 for DoNotChange and 17 for Change , respectively) pass myInteger in
identically.
However, the tiny difference is what makes Change pass-by-reference while DoNotChange is
still pass-by-value. Notice the & in int& a . That causes the parameter to be pass-by-
reference.
Let’s see the output and see if we can determine what the practical implications of this are.

Initially, myInteger is 20
After calling DoNotChange, myInteger is 20
After calling Change, myInteger is 150
Press any key to continue …


Notice that even after our call to DoNotChange , the value of the argument ( myInteger ) remains
20. It was not changed to 150 inside the DoNotChange function on line 27. Remember that
in a pass-by-value function like DoNotChange , the parameter (a, in this case) gets its own
memory address and simply gets a copyof the value of whatever was passed in. In this
case, upon entering the function DoNotChange , a hasa value of 20 (copied from
the myInteger variable on line 13 from inside main .) Then, this parameter is assigned the
value 150. However, that parameter’s memory goes out of scope as soon as the function
ends. Therefore, there was never any effect on the argument, myInteger .
However, after the call to Change , the value of myInteger is now 150. This is
because Change ’s parameter a ispass-by-reference. Therefore, the parameter a (of type
integer reference, that is, int& ) is an aliasfor myInteger . So anything that happens to it (such
as its value being changed on line 32) happens to the original argument as well.

3.3 More Examples and other Function Topics
Let’s take a look at a couple more examples just so we can solidify our understanding a
bit.

Multiple Parameters
We aren’t limited to only using one parameter! To use more than one parameter, simply
separate the parameters by commas. You can have many different types, and even
different passing modes (i.e., some parameters can be pass-by-value while others are pass-
by-reference.)
Let’s see an example.

1 #include <iostream>
2 #include <string>
3 using namespace std;
4
5 void PrintNameAndAge(string name, int age);
6
7 int main()
8 {
9 string name;
10 int age;
11
12 cout<<“Please enter your full name.”<<endl;
13 getline(cin, name); //if a single string, cin>>name; would suffice
14
15 cout<<“Now, enter your age.”<<endl;
16 cin>>age;
17 cout<<endl<<endl; //extra spacing
18
19 PrintNameAndAge(name, age);
20
21 return 0;
22 }
23
24
25 //–––-| Print the Name and Age |––––-//
26 void PrintNameAndAge(string name, int age)
27 {
28 cout<<“Hello, “<<name<<endl;
29 cout<<“You are “<<age<<” years old.”<<endl;
30 }

Example with Multiple Parameters


In this example, you can see that in the function prototype (line 5), the function header
(line 26), and even in the function call (line 19), the parameters (or argument in the case of
the function call) are separated by a comma. This particular function only takes two
parameters.
I made the program a little more interesting by taking in user input using cin – the standard
input variable. Something interesting to note in the above code is line 13. I use
the getline function (defined for string s in the string library) which also takes two parameters.
We pass cin as the first argument (so the function knows where to obtain the data that is
input) and the name (which is the string we want to store the data in.) The getline function
works even if you have multiple strings, separated by spaces. If you only want one single
string, then cin>> will suffice.
Note that you mustinclude the string library (line 2) if you want to use strings. The string
type is a class in C++, not a primitive type.
All the function does is greet the person by the name passed in, and then tells them how
old they are (lines 28 and 29.) This is fairly straightforward. So, as you might guess, the
output (with user interaction) is as below:

Please enter your full name.


Bob Snuggles
Now, enter your age.
22


Hello, Bob Snuggles
You are 22 years old.
Press any key to continue …


I have bolded the user input in the above output/user interaction so you can see where the
user typed something from the keyboard.
Function Overloading
In C++, unlike C, you can multiple functions with the same name as long as they have
different signatures. The signature of a function includes its name (identifier) and its
parameter list. It does not include the return type. Having multiple functions with the
same name (but different signatures) is called function overloading.
Let’s see an example with function overloading.

1 #include <iostream>
2 #include <string>
3 using namespace std;
4
5 int Multiply(int num1, int num2);
6 int Multiply(int num1, int num2, int num3);
7
8
9 int main()
10 {
11 cout<<“2 * 3 = “<<Multiply(2, 3)<<endl;
12
13 cout<<“2 * 3 * 4 = “<<Multiply(2, 3, 4)<<endl;
14
15 return 0;
16 }
17
18 int Multiply(int num1, int num2)
19 {
20 return num1 * num2;
21 }
22
23 int Multiply(int num1, int num2, int num3)
24 {
25 return num1 * num2 * num3;
26 }

Example of function overloading


Note the function prototypes on lines 5 and 6, as well as the function headers on lines 18
and 23, respectively, have the same function identifier (Multiply), but have different
parameter lists. As long as the parameter list is different, the compiler can distinguish
between the functions.
For example, on line 11, we call Multiply(2, 3) . It has two arguments, so the compiler knows
it needs to call the Multiply definition on lines 18-21. On line 13, since there are three
arguments to Multiply , the version of Multiply on lines 23-26 are called.
Some things to note about function overloading:
You must have a variation of some sort in the parameters
This could mean the number of parameters is different
This could mean the types of the parameters is different
This could mean even just the order of parameters is different
E.g., one function A(int, string) and A(string, int) are two different functions
Therefore, overloading is accomplished simply by switching the
order
You cannot just change the return type when trying to overload a function
Remember the return type is not part of the function signature
This makes practical sense because it would lead to ambiguity when calling
function if C++ allowed just the return type to change
E.g., one function int SomeFunction(inta) and float SomeFunction(int a)
What happens if you call SomeFunction(15) – which would it call?

3.4 Comments and Brief Summary
This short chapter contained a lot of information to help you understand the
fundamental concepts associated with functions, and how to use them in different
scenarios. You should be comfortable with the various ways to declare functions, define
functions, and call (invoke) functions. This includes knowing the differences between
void functions and value-returning functions, as well as the differences between
parameterized and parameterless functions.
You should also know the differences between pass-by-value and pass-by-reference and
how to indicate whether a parameter is one or the other. Additionally, you should
understand how to pass multiple parameters in the parameter list, as well as how to
perform function overloading. You should, as a result, also know what a function
signature is comprised of.









Chapter 4: Classes

4.1 Basic Class and Object-Oriented Terminology
This chapter’s purpose is not to be a full-fledged and comprehensive coverage of
object-oriented programming (OOP), a popular paradigm of programming in which the
central entity of focus is the object, which are entities created from classes. However, at
very least, you will get a fundamental understanding of how to create classes and their
members (both member functions and data members). Also, you will get a conceptual
understanding of the three pillars of object-oriented programming, even though we will
not explore inheritance and polymorphism in depth.
A class is like a blueprint that describes the characteristics and behaviors of an object.
In C++, a class is where you declare and define the functions and variables that help
describe and give functionality to a particular entity. Although most analogies break down
at some level, you might also consider that a class is somewhat like a cookie cutter, and
the objects are like the cookies. Classes can be used to describe all kinds of things – from
real world entities (such as cars, planes, buildings, etc.) to more abstract entities (such as
bank accounts, atm machine transactions, enemies in a video game, etc.) The major
takeaway about why classes are even included in a programming language is in order to
enable us to create custom data types.
Say you’re an automotive engineer and designer. You create a class named Car, and this
“design document” describes the various data that a Car has (number of doors, number of
windows, color, etc.), and also the various behaviors that you can operate or use with a
Car (start, break, turn off car, turn on radio, turn off radio, etc.), it’s obvious you can’t
drive the actual blueprint of the Car. However, if you took that blueprint (or design
schema, documents, CAD drawings, etc.) and created an actual car out of it, then you
could drive that. In this analogy, the Car design document is like the class, and the actual
cars created from the design are the objects.

4.2 Member Functions and Data Members
So, again, to reinforce some concepts, a class (and the resulting objects) contain two
primary categories of “things” that live inside them:
Attributes (also called characteristics)
Operations (also called behaviors)
Attributes are typically nouns – such as weight, age, height, color, numberOfDoors,
milesPerGallon, etc. In C++, attributes come to life inside the class as data members,
which are variables that have at very least, class-level scope. That is, they can be
accessed from anywhere inside the class.
Operations are typically verbs – such as getWeight, getAge, setWeight, setAge,
getNumberOfDoors, etc. In C++, operations come to life inside the class as member
functions. These are just functions (like we saw in the last chapter) that live inside of a
class.
So, a class in C++ has data members and member functions.
Let’s take a look at a simple class, created properly from beginning to end.
Rectangle class
I will teach you a technique called separate compilation, where the declaration and data
are typically in a single file, separated from the full implementation (in another file), and
the client is in yet another file.
Regardless of which IDE you are using, if you plan on creating a single class to be used
and tested in a program, you should create three files:
The class header file (called the specification file)
This describes what the class does, not how the class accomplishes it
In other words, the function prototypes exist in this file inside the class, but
not the definitions (they could, but not if you’re using the technique I’m
teaching)
Usually, the data members are also included in this file
The class source file (called the implementation file)
This file will contain the actual function definitions
The client source file (called the driver file)
This file will typically contain your main function
I often just name mine “main.cpp”
For our Rectangle class, you will need three files:
Rectangle.h
Rectangle.cpp
main.cpp
As you might guess, Rectangle.h is the specification file, Rectangle.cpp is the
implementation file, and main.cpp is the client source file (the driver file.)
In Visual Studio, in Solution Explorer, you can
1. Right-click the Header Files folder
2. Go to Add—>New Item and then make sure to select the Header file (.h) as the
option.
3. Give it the same name as the class. So in our case, it will be Rectangle.h.
4. You then create Rectangle.cpp by right-clicking the Source Files folder and go to
Add—>New Item and then make sure C++ file (.cpp) is selected as the option.
5. Name it the same as the class – Rectangle.cpp.

The specification and implementation files should have the same name as the class.
Although they don’t have to in C++, it’s good programming practice to do so. Also, it
keeps things much more organized, and keeps your instructor and/or co-workers from
pulling their hair out. I think I’m going bald partially because of students not following
this simple convention – but I digress.
6. Finally, just create another C++ file and name it something like main.cpp or
driver.cpp.
Since this file doesn’t directly have a class defined in it, it doesn’t really matter what its
name is, but using a useful name to indicate it’s where the main function resides is a good
idea.

Once you’re done, in Visual Studio it should look something like this:









Let’s look at the files and their contents (which I’ve written and will describe shortly):
Rectangle.h – the Specification File
1 #ifndef RECTANGLE_H
2 #define RECTANGLE_H
3
4 class Rectangle
5 {
6 public:
7 Rectangle(int wid, int len);
8 void setWidth(int wid);
9 void setLength(int len);
10 int getWidth() const;
11 int getLength() const;
12 int getArea() const;
13
14 private:
15 int width;
16 int length;
17 };
18
19 #endif


The Rectangle.h file is the specification file for our Rectangle class. Notice first on lines
1, 2, and 19 you have some peculiar syntax that doesn’t look too much like C++.
Although not always necessary, it is good programming practice to use these so-called
include guards to prevent file conflict in larger applications – where the preprocessor
attempts to include the same file multiple times, ending with tons of conflicts and other
problems.
So, the general syntax is just to first use an #ifndef (if not defined) followed by some
variable name you make up – by convention, you name it the same as the .h file you’re in
except in all caps and using an underscore instead of a dot (.). So in our case, our special
include guard macro variable is RECTANGLE_H . Then, if it makes it past
the #ifndefRECTANGLE_H (in other words, if there isn’t a symbol with that name), then you
define a symbol with that name with the statement #define RECTANGLE_H . Then, you put the
class specification, and on line 19, you designate the end of the block of code that the
macro, preprocessor ifndef applies to. These are very similar to if statements in C++, but
are read by the preprocessor before the compiler is called on the code. If you don’t totally
understand include guards, don’t sweat it! Just use the syntax verbatim, just remembering
to change the include guard macro variable name to the appropriate name of your own
class. For example, if you had a Dog class, you’d probably want to name the
variable DOG _H.
Now, to the actual C++ code. Let’s start on line 4 where the class header is. You just use
the keyword class, and follow it by the name of the class. In our case, this is Rectangle .
Note that the end of the class declaration, on line 17 ends not only with a curly brace, but
also has a semicolon (;). This is not optional in C++. In fact, if you leave it out, you will
get a compiler error (or errors.)
Zooming in just a little bit, let’s take a look at lines 6 and 14, each of which seem to
designate the beginning of some sort of sectionof code. The keyword public indicates that
anything in that section is visible (accessible) outside the class. The private keyword
indicates that anything in that section is accessible onlyto the class itself. Using the private
keyword to protect data is known as information hiding, which is a big part of one of the
three pillars of object-oriented programming, namely, encapsulation.
On lines 7-12 you see the public member functions. Although data can be public also, it
is most common to have public functions and private data (although, likewise, functions
can be private too!) This is typically considered good programming style and good
software engineering practice.
We’ll come back to line 7 because it’s somewhat special. But lines 8-12 should look
pretty familiar. That’s right! They’re just function prototypes. The only slight difference
being the use of the const keyword after getWidth , getLength , and getArea . In the context of
function headers (and their prototypes) in a class, the const keyword means that the
function will not modify any of the internal data members. In other words, these functions
are for obtaining or accessingdata – they will not modify the data in the class.
E.g., getWidth won’t set the private data member width to another value. If you try to do
something like that, you will get a compiler error. While this might seem restrictive, it is
good programming practice to label any member functions that aren’t supposed to modify
data members as const.

Line 7 is a little peculiar. It looks like a function prototype but is missing a return type and
it has the same name as the class. This type of function, with the same name as the class
(and virtually any choice of parameters) is called a constructor, because it is called
automatically when an instance of the class (also called an object) is created.
Now for the private section. On line 15, I declare the width as an integer. I declare length as
an integer on line 16. These data members (attributes) will be specific to each object. So,
you can create multiple objects of the Rectangle type and they can have different values in
their specific, self-contained private data members.

So, we can see that our class will allow the user to get and set the width and length ,
respectively. Also, it allows the user to obtain the area of the Rectangle object.
You might wonder why we didn’t include area as a data member in the private section.
Typically, if you can derive a value from already-present data members, you don’t need to
(and usually shouldn’t) include that calculated value as another variable. Doing so would
also increase the possibility for forgetting to update the area every time
the length or width was changed, leading to an area that doesn’t match the length and width .
When this occurs, we would say that the variable area contains stale data. So it’s best to
avoid this scenario as much as possible.
So now we know what the class allows us to do with an object of its type. But we’re also
responsible for providing the code telling the class how the functions perform their jobs.
Let’s now move on and take a look at how the Rectangle class is actually implemented.


Rectangle.cpp – the Implementation File
1 #include “Rectangle.h”
2
3 Rectangle::Rectangle(int wid, int len)
4 {
5 width = wid;
6 length = len;
7 }
8
9 void Rectangle::setWidth(int wid)
10 {
11 width = wid;
12 }
13
14 void Rectangle::setLength(int len)
15 {
16 length = len;
17 }
18
19 int Rectangle::getWidth() const
20 {
21 return width;
22 }
23
24 int Rectangle::getLength() const
25 {
26 return length;
27 }
28
29 int Rectangle::getArea() const
30 {
31 return length * width;
32 }


In Rectangle.cpp, on line 1, we include the Rectangle.h file so that our implementation
file has access to the prototypes declared in the header file.
Then, you’ll note some very peculiar syntax that we haven’t really seen before. However,
this syntax is necessary so that the compiler can distinguish between member functions
and other functions (so-called global functions, which we looked at in the last chapter.)
Note that the syntax Rectangle:: is in front of the namesof each of the member functions of
the class. For the member functions that have a specified return type (including void),
the Rectangle:: comes after the return type but before the name. With the constructor (on line
3), there is no return type (not even void), so you just put the Rectangle:: in front of it.
This will always be the name of the class, followed by two colons, called the binary
scope resolution operator. Wow! That’s quite a mouth full. But again, it can help you
communicate effectively on the job and will make you the life of the party, if partying
with programmers is your thing.
The code itself for each of the member functions should be relatively straightforward.
Notice in both setWidth and setLength , a parameter is passed (by value) and then inside these
functions, the internal data members width and length are set to their corresponding
parameters.
For example, on line 11, we have width = wid; This sets the private data member, width , of a
particular object (instance) of the class to whatever value is passed in when
the setWidth function is called. The chosen parameter name in this case is wid .
You may wonder if it’s possible to just use the same name for the private data member and
the parameter for a given function. The answer is yes, but you have to take extra
precautions when doing so.
Let’s consider the following:
void Rectangle::setWidth(int width)
{
width = width;
}


We have a bit of a problem here. What does the variable width refer to in the body of the
code (width = width)? Is it referring to the parameter between the parentheses or the
private data member? It seems ambiguous.
The answer is the parameter shadowsthe name of the private data member. Therefore, the
private data member will not be touched, and this setWidth function would essentially be
made useless. Note that this code will compile. So it’s not a syntax error. It’s valid
syntax in C++.

The code above produces what we call a logic error – an error in which the code compiles
(no syntax/compiler error), the code doesn’t crash (no runtime/execution time error), but
just gives the wrong results – or behaves unexpectedly.

So, it’s hard to come up with new names for parameters when have perfectly good names
that we came up with for the private data member. So is there a way to overcome
shadowing so we can make use of the same name and still change the internal private data
member? The answer is of course, yes!
void Rectangle::setWidth(int width)
{
this->width = width;
}


You can use the this keyword, followed by the arrow member access operator, and the
name of the private data member you’re trying to access and distinguish from the
parameter name. The this keyword is actually a pointer(a variable that contains a memory
address) to whatever object is being acted upon at a given time. So you can read the code
as “this object’s width ( this->width ) should be assigned the value of the parameter
named width ”.
Obviously, you don’t have to go through all this trouble if you use a different name for the
parameter from the private data member. However, many programmers use the this
keyword to avoid having to come up with new names. Some use it even if the names are
different, so they can explicitly indicate that they are referring to a data member.

main.cpp – the Client Code (Driver File)
1 #include <iostream>
2 #include “Rectangle.h”
3 using namespace std;
4
5
6 int main()
7 {
8 Rectangle a(4, 5);
9 Rectangle b(10, 20);
10
11 cout << “Rectangle a’s area is: ” << a.getArea() << endl;
12 cout << “Rectangle b’s area is: ” << b.getArea() << endl;
13
14 cout<<endl;
15 cout<< “Currently, a’s width is: ” << a.getWidth() << endl;
16
17 a.setWidth(10);
18
19 cout<< “a’s new width is: ” << a.getWidth() << endl;
20 cout<< “a’s new area is: “<< a.getArea() <<endl;
21
22 return 0;
23 }


The output of this code is as follows:

Rectangle a’s area is: 20


Rectangle b’s area is: 200

Currently, a’s width is: 4
a’s new width is: 10
a’s new area is: 50
Press any key to continue …


You can see in the main.cpp client code that we must include Rectangle.h(you shouldn’t
have to include Rectangle.cpp.) Then, you can create instances of Rectangle such as is done
on lines 8 and 9. Rectangle a hasa width of 4 and height of 5 starting out, because we
wrote the constructor to set the internal width and length to the arguments 4 and 5,
respectively. Rectangle b has width 10 and length 20, as specified on line 9.

Then, we just print out the area of each rectangle on lines 11 and 12.

On line 15, we print out rectangle a ’swidth using the getWidth function. We then change
the internal data for the width using the setWidth function on line 17. Finally, we can see
through the printing done on lines 19 and 20 that the width (and of course, the calculated
area) are different now for a .

Let’s take a look at another example.
Dog class
In this subsection, we’re just going to create a class that represents a dog. I’ll provide less
explanation, but provide mostly just the code. Create the appropriate files just like we did
in the Rectangle class, and run the program.
Dog.h
#ifndef DOG_H
#define DOG_H

#include <string>
using namespace std;

class Dog
{
public:
Dog(); //no-arg / default constructor
Dog(string name, int age, int weight);

void setName(string n);
void setAge(int a);
void setWeight(int w);

string getName() const;
int getAge() const;
int getWeight() const;

private:
string name;
int age;
int weight;
};
#endif


This class has not one but two constructors. Since a constructor is a type of function, and
functions can be overloaded, so can constructors. There is a so-called no-argument
constructor (often just called a no-arg constructor) and a parameterized constructor with
three parameters.
A note about the no-arg constructor: many programmers call a constructor with no
arguments the default constructor. Some other programmers disagree and state that the
default constructor is a no-arg constructor, but is the one that is produced automatically by
the compiler if you don’t include any constructors whatsoever. In other words, if I didn’t
put any constructors, the compiler will provide one automatically. It wouldn’t really do
much of anything as far as setting internal data, but a class must have a constructor if it is
to be instantiated.
Dog.cpp
#include “Dog.h”

//no-arg / default constructor: no parameters
Dog::Dog()
{
name = “Fido”;
age = 3;
weight = 30;
}

Dog::Dog(string name, int age, int weight)
{
this->name = name;
this->age = age;
this->weight = weight;
}

void Dog::setName(string n)
{
name = n;
}

void Dog::setAge(int a)
{
age = a;
}

void Dog::setWeight(int w)
{
weight = w;
}

string Dog::getName() const
{
return name;
}

int Dog::getAge() const
{
return age;
}

int Dog::getWeight() const
{
return weight;
}


main.cpp
#include <iostream>
#include “Dog.h”
using namespace std;


int main()
{
Dog myDog; //calls default constructor
Dog yourDog(“Rover”, 4, 120);

cout << “My dog’s name is ” << myDog.getName() << endl;
myDog.setName(“Beethoven”);

cout << “Now, my dog’s name is ” <<myDog.getName() << endl;
cout << “He weighs ” << myDog.getWeight() << ” lbs and is ”
<< myDog.getAge() << ” years old.” << endl;

cout<<endl<<endl;

cout<<“Your dog’s name is ” << yourDog.getName() << endl;
cout << “He weighs ” << yourDog.getWeight() <<” lbs and is ”
<< yourDog.getAge() << ” years old.” << endl;


return 0;
}


The output is:

My dog’s name is Fido


Now, my dog’s name is Beethoven
He weighs 30 lbs and is 3 years old.


Your dog’s name is Rover
He weighs 120 lbs and is 4 years old.
Press any key to continue …


Looks pretty good. But what if someone uses your Dog class in an unexpected way. Say
they try (or accidentally try) to set the dog’s age to a negative number. Can you prevent
that? Yes! As the developer of the interface which the client code uses to create and work
with classes, you can prevent the outside world from entering invalid data.
How might you fix the setAge function? Using if-statements is one way.(Note that to
get cerr or cout to work, you have to include iostream at the top of the implementation file.)

void Dog::setAge(int a)
{
if(age > 0)
{
age = a;
}
else
{
cerr << “Error : invalid age attempt!” <<endl;
cerr << “Setting to default of 3” <<endl;
age = 3;
}
}


See if you can make a better Dog class. I’ve fixed one function. See if you can come up
with ways to fix the others, or make everything more robust, that is, less prone to error or
invalid data. In fact, there is a much better way to handle invalid data instead of just
sending errors to the standard output device or the standard error device. You can use
exception handling with try-catch statements. This is outside the scope of this book’s
purpose, but if you are familiar with exception handling, see if you can get your class to
communicate with the “outside world” through exception handling when errors or
problems arise.

4.3 The Three Pillars of Object-Oriented Programming
It is good to at least conceptually understand object-oriented programming (OOP)
concepts even if you’re not going to become an expert, at least with this book alone. You
should commit to memory the names of the three pillars of OOP:
1. Encapsulation
2. Inheritance
3. Polymorphism
Say them over and over in your mind until you start having dreams about the words.
Briefly, we’ve actually seen encapsulation so far. This is the most fundamental building
block of OOP. The class in C++ is how we encapsulate attributes and operations
together. Even the name suggests you’re taking a bunch of “stuff” (attributes and
behaviors) and putting them in a capsule (en-capsule-ating them.) The purpose of
encapsulation is to allow the programmer (yourself or others) to treat a bunch of data and
behaviors as being related, rather than just thrown all over the place and held together with
just naming conventions and wishful hope.
Encapsulation allows you to treat a bunch of “stuff” as one entity. We can treat a width
and a length, along with a bunch of behaviors for getting and setting the data and
calculating the area as a single unit – a Rectangle object. We can take a name, age, and
weight and corresponding operations for setting and getting data (even protecting the data)
and combine them into a single entity – a Dog object.

The second pillar, inheritance, is outside the scope of this book as far as actual
implementation details (although if the demand proves high enough, I will gladly create a
book on OOP in C++.) However, inheritance allows you to take a class that’s already
made that is similar to what you need, and to define another class based on the original
class.

Consider having an Animal class that has things like a name , age , weight , height , and the
ability to make a noise. Then you can take the generic functionality and data of the Animal ,
and inherit from it. Dog s, Cat s, Horse s, Cow s, Penguin s, and Narwhal s are all Animal s. They
will specialize the very general Animal class, but you wouldn’t have to re-implement all the
code that they all have in common. Therefore, we can look at inheritance as a form of
software reuse. Terminology may help you understand other books and articles on the
subject: typically the Animal class would be called the base class, parent class, or
superclass. The Dog , Cat , etc. would be called derived classes, children classes
(singular: child class) or subclasses. Although these terms are interchangeable, you
typically hear the terms “base class” and “derived class” being used in C++ programming
circles (also, C# programming circles.) Java programmers usually use the terms
“superclass” and “subclass” to denote the parent/child relationship. We say that
inheritance denotes an is-arelationship. So, Cat is-an Animal . Dog is-an Animal . Etc.

Arguably the most complex of the pillars is polymorphism. It relies on inheritance in
order to understand it. So it’s even more difficult to describe without going into a great
amount of detail on inheritance first. In C++, it also is used very frequently with pointers,
which we did not cover in this book. However, conceptually you should just understand
that it allows us to dynamically (at runtime) determine which function should be called,
given a variable of a base type.

So, because of the is-arelationship in inheritance, we can actually store an object (or
pointer to / address of an object) of type Cat, for instance, inside an Animal pointer
reference variable. Then, when you call makeNoise on the Animal variable, if you’re using
polymorphism (through use of the virtual keyword), the Cat’s version of makeNoise will be
called instead ofthe Animal ’s version.

Again, this is outside the scope of this book. But stay tuned, and e-mail me if you liked
this book and I will produce more!


4.4 Comments on Classes and OOP
Hopefully, this chapter gave you at least a reasonably solid foundation or a good
review of the concepts related to classes. It was in no means intended to be a full-fledged
chapter with dozens of different classes. It should be just enough to get your feet wet for
the first time, or again.

CLOSING REMARKS
Hopefully this book was useful to you. I encourage you to read it, tell your
friends about it, and e-mail me and let me know what you think.
I haven’t self-published in a while, and I don’t claim that this book will be error free. But
I tried to make it as awesome and clean as possible. I am hoping to publish some more
books on other topics in the near future – so let me know what topics, programming
languages, technologies, or general information you’d like to read from me!

Contact Information

My e-mail: profjpbaugh@gmail.com
My YouTube Channel: https://www.youtube.com/user/profjpbaugh
My Website, where you might just find Errata, Supplemental information, and other
goodies:
http://www.profjpbaugh.com

You might also like