This document discusses pointers in C++ and how they allow objects to communicate with each other. It provides an example of a light bulb and button class that illustrate this. The light bulb class tracks the state of the light and can change its state. The button class has a pointer to the light bulb object and can call the light bulb's method to change its state when pressed. This demonstrates how objects can talk to each other through the use of pointers, allowing the button object to modify the light bulb object.
C++ Software Development Class: Pointers, Objects Communicating
1. An Introduction To Software
Development Using C++
Class #17:
Pointers!, Objects
Talking To Each Other
2. Homework #3:
The Chatterbox Light System
• There is a problem with your current traffic light
control system:
– It turns out that the majority of your control logic is
contained in the main routine.
– Since this part of the control system runs in
a box located at the intersection, there is
always the possibility that a car could hit it
and take out the entire stoplight system.
3. Homework #3:
What You Need To Do
• Starting with Dr. Anderson’s solution
to HW #2
• Remove all of the traffic light control
logic from your program's "main"
routine.
• Move it into methods that you create
for each of the four traffic light
objects.
• Implement new logic as methods for
the light objects that allows each of
the light objects to communicate
with each other in order to signal
when a light should change from red
to green.
Image Credit: phys.org
5. What Happens When You Load A
Program Into A Computer’s Memory?
00000000
00000001
00000002
00000003
00000004
00000005
00000006
00000007
• Memory is typically laid out as a sequential series of
memory locations.
• We usually refer to these locations as eight-bit bytes.
• Each space can be uniquely distinguished from all
other spaces by its address.
• All machines use bytes that have sequential addresses
starting at zero and going up to however much memory you have in your computer.
6. Sample Program
//: MyPets1.cpp
#include <iostream>
using namespace std;
int dog, cat, bird, fish;
void f (int pet)
{
cout << "pet id number: " << pet << endl;
}
int main()
{
int i, j, k;
}
• Each of the elements in this program
has a location in storage when
the program is running.
• Even the function occupies storage.
• It turns out that what an element is
and the way you define it usually
determines the area of memory where
that element will be placed.
Image Credit: www.petrecognition.com
7. &
• There is an operator in C and C++ that will tell
you the address of an element. This is the ‘&’
operator. All you do is precede the identifier
name with ‘&’ and it will produce the address
of that identifier.
Image Credit: www.yorkshirebusinesscentre.co.uk
8. Program Addresses
//: MyPets2.cpp
#include <iostream>
using namespace std;
int dog, cat, bird, fish;
void f (int pet) {
cout << "pet id number: " << pet << endl;
}
int main()
{
int i, j, k;
cout << "f(): " << (long)&f << endl;
cout << "dog: " << &dog << endl;
cout << "cat: " << &cat << endl;
cout << "bird: " << &bird << endl;
cout << "fish: " << &fish << endl;
cout << "i: " << &i << endl;
cout << "j: " << &j << endl;
cout << "k: " << &k << endl;
}
When we run this program:
1. You can see how the variables that are
defined inside main( ) are in a different area
than the variables defined outside of main( );
2. f( ) appears to be in its own area;
3. Code is typically separated from data
in memory.
4. Another interesting thing to note is that variables
defined one right after the other appear to be
placed contiguously in memory. They are
separated by the number of bytes that are
required by their data type.
f(): 4199220
dog: 0x477008
cat: 0x47700c
bird: 0x477010
fish: 0x477014
i: 0x28fefc
j: 0x28fef8
k: 0x28fef4
1
Image Credit: www.mecca911.org
9. Just What Can You Do With
An Address?
• The most important thing you can do is store it inside another variable for later
use.
• Both C and C++ have a special type of variable that holds an address. This variable
is called a pointer.
• The operator that defines a pointer is the same as the one used for
multiplication: ‘*’.
• The compiler knows that it isn’t multiplication because of the context in which it is
used, as you will see. When you define a pointer, you must specify the type of
variable it points to.
• You start out by giving the type name, then instead of immediately giving an
identifier for the variable, you say “Wait, it’s a pointer” by inserting a star between
the type and the identifier. So a pointer to an int looks like this:
int* ip; // ip points to an int variable
Image Credit: www.quia.com
10. You Must Be Careful When
Defining Pointers
• The association of the ‘*’ with the type looks sensible and reads easily, but it can
actually be a bit deceiving.
• With an int or other basic data type, it’s possible to say:
int a, b, c;
whereas with a pointer, you’d like to say:
int* ipa, ipb, ipc;
• C syntax (and by inheritance, C++ syntax) does not allow such sensible expressions.
• In the definitions above, only ipa is a pointer, but ipb and ipc are ordinary ints.
• Consequently, the best results can be achieved by using only one definition per
line; you still get the sensible syntax without the confusion:
int* ipa;
int* ipb;
int* ipc;
Image Credit: www.thebookdesigner.com
11. Always Initialize Your Pointers
• Since a general guideline for C++ programming is that you
should always initialize a variable at the point of definition,
this form actually works better.
• For example, the variables in our example are not initialized
to any particular value; they hold garbage. It’s much better
to say something like:
int a = 47;
int* ipa = &a;
• Now both a and ipa have been
initialized, and ipa holds the
address of a.
Image Credit: www.examiner.com
12. The Null Pointer
• A null pointer does not point to any object. Code can check whether a pointer is null before
attempting to use it. There are several ways to obtain a null pointer:
int* p1 = nullptr; // equivalent to int *p1 = 0;
int* p2 = 0; // directly initializes p2 from the literal constant 0
// must #include cstdlib
int* p3 = NULL; // equivalent to int *p3 = 0;
• The most direct approach is to initialize the pointer using the literal nullptr, which was
introduced by the new standard. nullptr is a literal that has a special type that can be
converted to any other pointer type. Alternatively, we can initialize a pointer to the literal 0,
as we do in the definition of p2.
• Older programs sometimes use a preprocessor variable named NULL, which the cstdlib
header defines as 0.
• When we use a preprocessor variable, the preprocessor automatically replaces the variable
by its value. Hence, initializing a pointer to NULL is equivalent to initializing it to 0. Modern
C++ programs generally should avoid using NULL and use nullptr instead.
Image Credit: kateheddleston.com
13. How To Use A Pointer
• Once you have an initialized pointer, the most basic thing you
can do with it is to use it to modify the value it points to.
• To access a variable through a pointer, you dereference the
pointer using the same operator that you used to define it,
like this:
int a = 47;
int* ipa = &a;
*ipa = 100;
• Now a contains the value 100
instead of 47.
Image Credit: fedgeno.com
14. Why Use Pointers?
• Why do you want to modify one variable using another
variable as a proxy?
• For this introductory view of pointers, we can put the
answer into two broad categories:
1. To change “outside objects” from within a function. This
is perhaps the most basic use of pointers, and it will be
examined next.
2. Because by using pointers,
we can finally get objects
to talk to each other!!!
Image Credit: ocw.mit.edu
15. Modifying The Outside Object
x = 47
a = 47
a = 5
x = 47
//: PassByValue.cpp
#include <iostream>
using namespace std;
void f (int a) {
cout << "a = " << a << endl;
a = 5;
cout << "a = " << a << endl;
}
int main()
{
int x = 47;
cout << "x = " << x << endl;
f(x);
cout << "x = " << x << endl;
}
• In f( ), a is a local variable, so it exists only
for the duration of the function call to f( ).
• Because it’s a function argument, the value
of a is initialized by the arguments that are
passed when the function is called; in
main( )the argument is x, which has a value
of 47, so this value is copied into a when
f( ) is called.
• Initially, x is 47. When f( ) is called, temporary
space is created to hold the variable a for the
duration of the function call, and a is initialized
by copying the value of x, which is verified by
printing it out.
• When f( ) is completed, the temporary space
that was created for a disappears, and we see
that the only connection that ever existed
between a and x happened when the value of x was copied into a. 2
16. What If You Want To Modify
A Variable That Lives “Outside”?
• But what if you do want to modify a variable that lives
outside of the current function?
• This is where pointers come in handy. In a sense, a pointer is
an alias for another variable.
• So if we pass a pointer into a function instead of an
ordinary value, we are actually passing an alias to the
outside object, enabling the function to modify that
outside object as shown in this code.
x = 47
&x = 0x28fefc
p = 0x28fefc
*p = 47
p = 0x28fefc
x = 5
//: PassAddress.cpp
#include <iostream>
using namespace std;
void f(int* p)
{
cout << "p = " << p << endl;
cout << "*p = " << *p << endl;
*p = 5;
cout << "p = " << p << endl;
}
int main()
{
int x = 47;
cout << "x = " << x << endl;
cout << "&x = " << &x << endl;
f(&x);
cout << "x = " << x << endl;
}
3 Image Credit: www.philly.com
17. The Lightbulb And The Switch Example
Two Classes:
Light
Button
5 Methods:
Light
Light
Change State
Show State
Button
Button
Press
Question: What’s So Special About This Example?
Answer: We’re going to see objects talking to other objects!!!
4
18. Class Light
• Constructor method is used to
initialize the light to an “off” state.
• Uses only one “global” variable:
light_state – used to keep track of
the current state of the light: on / off
• changeState simply switches the
current state of the light – turns it on
if off, off if on.
• showState prints out the current
state of the light.
class Light
{
private:
int light_state;
public:
Light()
{
light_state = OFF;
}
void changeState()
{
if (light_state == OFF)
light_state = ON;
else
light_state = OFF;
}
void showState()
{
if (light_state == OFF)
cout << "light is off" << endl;
else
cout << "light is on" << endl;
}
}; // class Light
Image Credit: www.lightingpic.com
19. Class Button
• One “global” variable – light_bulb
which is a pointer to an object of
type Light.
• Constructor accepts a Light object as
input and then sets the global
variable light_bulb to remember how
to reach it.
• Press method calls the Light method
changeState and causes the current
state of the Light object being
pointed to by light_bulb to switch to
on if its off, or off if its on.
Class Button
{
private:
Light* light_bulb;
public:
// the constructor makes the link
between the associated objects
Button(Light* bulb)
{
light_bulb = bulb;
}
// the press method sends a
message to the associated object
void press()
{
light_bulb -> changeState();
}
}; // class Button
How a pointer to an object calls one
of that object’s methods
Image Credit: www.businessinsider.com
20. Main
• Three variables: Big_Light is an object
of class Light, Light_Button is an
object of class Button, and choice is
an int.
• Main loop continues until user enters
a “2”.
• When Light_Button is declared, its
constructor runs and “remembers”
how to reach the Light object
Big_Light.
• If the user enters a “1”, then the
Button object Light_Button calls it’s
own method: press.
int main()
{
Light Big_Light;
Button Light_Button(&Big_Light);
int choice = 0;
while (choice != 2)
{
// show if the light is on or off
Big_Light.showState();
cout << "enter 1 to press light button, 2
to quit." << endl;
cin >> choice;
if (choice == 1)
Light_Button.press();
}
cout << "End of program." << endl;
} Image Credit: www.clipartpanda.com
21. How Does All Of This Work?
Big_Light Light_Button
light_state = OFF; light_bulb
(User enters a “1”)
Light_Button.press();
light_bulb->changeState();
if (light_state == OFF)
light_state = ON;
else
light_state = OFF;
light_state = ON;
22. So What’s The Take-Away?
• The whole idea behind object-orientated programming is to
create an “ecosystem” where you can have objects talking to
and controlling each other.
• This example shows us how to do it: use pointers!
• When you are creating objects you need to set up the
pointers so that they can “find” the objects.
• A pointer to an object can “call”
one of that object’s public methods.
Image Credit: www.slideshare.net
23. In-Class Programming Challenge:
The Electric Blanket Problem
• Create a C++ program to
simulate an electric blanket
controller. The controller has
three settings: off, medium,
and high.
• Use two classes: controller and
blanket.
• Make them talk to each other.
• When the controller setting is
changed, have the blanket
report “off”, “medium”, or
“high”.
Image Credit: www.amazon.co.uk
The blanket has been set to OFF
0 = turn blanket off, 1 = set it to medium, 2 = set it to high, and 3 = quit
1
The blanket has been set to MEDIUM
0 = turn blanket off, 1 = set it to medium, 2 = set it to high, and 3 = quit
2
The blanket has been set to HIGH
0 = turn blanket off, 1 = set it to medium, 2 = set it to high, and 3 = quit
0
The blanket has been set to OFF
0 = turn blanket off, 1 = set it to medium, 2 = set it to high, and 3 = quit
3
End of program.
24. In-Class Programming Challenge:
The 10-Second Beer Company
• There are 5 steps in the beer brewing process: Mashing, Lautering, Boiling,
Fermentation, and Conditioning.
• Create a program with 5 classes (M,L,B,F, and C). Have each part of the brewing
process be able to talk to the next step in the process.
• Have the user enter the number of barrels of beer that they want to brew.
• Pass the number of barrels of beer to brew to the first step in the brewing process
and have it then pass that number to the next step in the process and so on.
• Have the final step in the brewing process print out the number of barrels of beer
that have been brewed.
Mashing Lautering Boiling Fermentation Conditioning
“100 barrels” “100 barrels”
25. What’s In Your C++ Toolbox?
cout / cin #include if/else/
Switch
Math Class String getline While
For do…While Break /
Continue
Pointers
26. What We Covered Today
1. Pointers!
Image Credit: http://www.tswdj.com/blog/2011/05/17/the-grooms-checklist/
27. What We’ll Be Covering Next Time
1. Vectors & Arrays
Image Credit: http://merchantblog.thefind.com/2011/01/merchant-newsletter/resolve-to-take-advantage-of-these-5-e-commerce-trends/attachment/crystal-ball-fullsize/
Editor's Notes
New name for the class
I know what this means
Technical professionals are who get hired
This means much more than just having a narrow vertical knowledge of some subject area.
It means that you know how to produce an outcome that I value.
I’m willing to pay you to do that.