Chapter 9

advertisement
Beginning C++ Through
Game Programming,
Second Edition
by Michael Dawson
Chapter 9
Advanced Classes and Dynamic
Memory: Game Lobby
Objectives
•
•
•
•
Combine objects
Use friend functions
Overload operators
Dynamically allocate and free
memory
• Avoid memory leaks
• Produce deep copies of objects
Aggregation
• Game objects often composed of
other objects
– Drag racer: body, four tires, an engine
• Other times, see an object as a
collection of related objects
– Zoo as a collection of animals
• Can mimic these kinds of
relationships among objects in OOP
using aggregation
Using Object Data Members
• A data member that's an object itself
• Has a relationship
• A Critter object can have an
attribute m_Name that is a string
object
Critter Class
class Critter
{
public:
Critter(const string& name = "");
string GetName() const;
private:
string m_Name;
};
Critter::Critter(const string& name):
m_Name(name)
{}
inline string Critter::GetName() const
{
return m_Name;
}
Container Data Members
• You can also use containers as data
members for your objects
• A Farm object has a single data
member that's a vector for Critter
objects
Farm Class
class Farm
{
public:
Farm(int spaces = 1);
void Add(const Critter& aCritter);
void RollCall() const;
private:
vector<Critter> m_Critters;
};
Farm Class (cont.)
Farm::Farm(int spaces)
{
m_Critters.reserve(spaces);
}
void Farm::Add(const Critter& aCritter)
{
m_Critters.push_back(aCritter);
}
void Farm::RollCall() const
{
for (vector<Critter>::const_iterator iter =
m_Critters.begin();
iter != m_Critters.end();
++iter)
cout << iter->GetName() << " here.\n";
}
Using Critter and Farm
int main()
{
Critter crit("Poochie");
cout << "Critter's name:" << crit.GetName()
cout << "\nCreating critter farm.\n";
Farm myFarm(3);
cout << "\nAdding three critters to farm.\n";
myFarm.Add(Critter("Moe"));
myFarm.Add(Critter("Larry"));
myFarm.Add(Critter("Curly"));
cout << "\nCalling Roll...\n";
myFarm.RollCall();
return 0;
}
Friend Functions
•
Friend functions have complete access to any member of
a class
• Specify function is friend of a class with friend before
function prototype inside class definition
• In a Critter class:
friend void Peek(const Critter& aCritter);
• Peek() can access any member of a Critter object
• Outside of Critter class definition, define global
function Peek():
void Peek(const Critter& aCritter)
{
cout << aCritter.m_Name << endl;
}
• Peek() can access private member m_Name of a
Critter object
Overloading Operators
•
•
•
•
Give meaning to built-in operators used with new types that you
define
Overload the << operator so it can work with Critter objects
Can send Critter object << to cout
Outside a Critter class, define a global function that
overloads << operator
ostream& operator<<(ostream& os, const Critter&
aCritter)
{
os << "Critter Object - ";
os << "m_Name: " << aCritter.m_Name;
return os;
}
•
Function can directly access the private data member m_Name
of a Critter object because function is a friend of the
Critter class
friend ostream& operator<<(ostream& os,
const Critter&
aCritter);
Dynamically Allocating
Memory
• Local variables live on the stack
• Local variables don't persist beyond
function in which declared
• Heap memory persists until programmer
frees it
• Dynamic heap memory offers efficiency
– Use only memory needed, free when done
– Access memory even after a function ends
(without having to return a copy of the object)
The new Operator
• Allocates memory on the heap and returns its
address
• Use new followed by the type of value
int* pHeap = new int;
• new int allocates memory on the heap for one int
and returns its address
• int* pHeap, declares a local pointer, pHeap, which
points to the newly allocated chunk of memory on the
heap
• Can initialize memory on the heap at the same time
you allocate it
int* pHeap = new int(10);
Memory on the Heap
Persists
int* intOnHeap()
{
int* pTemp = new int(20);
return pTemp;
}
• Can access heap memory from another
function
int* pHeap2 = intOnHeap();
The delete Operator
• Memory on the heap must be explicitly
freed
delete pHeap;
• Memory on heap pointed to by pHeap is
returned to the heap for future use
• Good rule of thumb—every new should
have a corresponding delete
delete Pitfalls
• Freeing memory on the heap with delete
does not alter pointers to the heap
• When calling delete on a pointer, potential
problem of dangling pointer
• Never dereference dangling pointers
• Can assign 0 to them, as in
delete pHeap;
pHeap = 0;
• Or immediately assign dangling pointer valid
memory address
Memory Leak 1
• Allocate memory on heap but have no way to free
• Large enough leak, a program runs out of memory
and crashes
void leak1()
{
int* drip1 = new int(30);
}
• No way to free the allocated memory on heap that
stores 30
Memory Leak 1 (cont.)
• To avoid
–
–
delete drip1 in leak1() function
OR return copy of drip1 and free memory later
Memory Leak 2
void leak2()
{
int* drip2 = new int(50);
drip2 = new int(100);
delete drip2;
}
•
Assigning drip2 address of memory on the heap that
stores the 100 leaks memory on the heap that stores 50
Memory Leak 2 (cont.)
• To avoid leak, delete drip2 before assigning new
memory address to it
Declaring Data Members on
the Heap
• Given the constructor of a Critter class
Critter::Critter(const string& name, int age)
{
cout << "Constructor called\n";
m_pName = new string(name);
m_Age = age;
}
• Each Critter object has data member, m_pName,
that's a pointer to memory on the heap
Destructors
• Member function that’s called just
before an object is destroyed
• Most often used for cleanup
• Must have the name of the class
preceded by a tilde (~) character
• No parameters and no return value
• If you don’t write a destructor of your
own, complier will supply a default
destructor
Destructor Example
•
If necessary to clean up memory on the heap—default
constructor won't do
~Critter()
{
cout << "Destructor called.\n";
delete m_pName;
}
•
When class allocates memory on the heap, write a
destructor that frees that memory
Copy Constructors
• Sometimes an object is copied
automatically
• Copying is done by a special member
function called the copy constructor
• Occurs when an object is
–
–
–
–
Passed by value to a function
Returned from a function
Initialized to another object through an initializer
Provided as a single argument to the object’s
constructor
Default Copy Constructor
• Default copy constructor is supplied if you
don’t write your own
• Copies the value of each data member to data
members of the same name in the new
object—shallow copy
• For simple classes, default copy constructor is
usually fine
• For classes with a data member that points to
value on the heap, usually write your own
copy constructor
Default Copy Constructor
Pitfalls
• Default copy constructor creates shallow copies
• Potential problem if object has data member on the
heap
Default Copy Constructor
Pitfalls (cont.)
• Deleting shallow copy leaves original object with
dangling pointer
Copy Constructor
• Copy constructor must have the same
name as the class
• Returns no value, but accepts a
reference to an object of the class—
the object that needs to be copied
• Reference is almost always made a
constant reference to protect the
original object from being changed
during the copy process
Copy Constructor Example
• Following allocates separate memory on the heap
for the name of the new Critter object
//copy constructor definition
Critter::Critter(const Critter& c)
{
cout << "Copy Constructor
called\n";
m_pName = new string(*(c.m_pName));
m_Age = c.m_Age;
}
Copy Constructor Example Continued
• Copy constructor creates deep copy
• When copy of object is destroyed, original is
unaffected
Overloading the Assignment
Operator
• When both sides of an assignment statement are
objects of the same class, the class’ assignment
operator member function is called
• A default assignment operator member function is
supplied for you if you don’t write one of your own
• Default assignment operator provides only memberwise duplication
• For simple classes, the default assignment operator
is usually fine
• When you have a class with a data member that
points to a value on the heap, you usually provide
an overloaded assignment operator of your own; if
you don’t, you’ll end up with shallow copies of
objects when assigning one object to another.
Overloading the Assignment
Operator
Critter& Critter::operator=(const Critter& c)
//overloaded assignment op def
{
cout << "Overloaded Assignment Operator\n";
if (this != &c)
{
delete m_pName;
m_pName = new string(*(c.m_pName));
m_Age = c.m_Age;
}
return *this;
}
Summary
• Aggregation is the combining of objects so
that one is part of another
• Friend functions have complete access to
any member of a class
• Operator overloading allows you to define
new meanings for built-in operators as they
relate to objects of your own classes
• The stack is an area of memory that is
automatically managed for you and is used
for local variables
• The heap is an area of memory that the
programmer can use to allocate and free
memory
Summary (cont.)
• The new operator allocates memory on the
heap and returns its address
• The delete operator frees memory on the
heap that was previously allocated
• A dangling pointer points to an invalid
memory location
• Dereferencing or deleting a dangling
pointer can cause your program to crash
• A memory leak is an error in which memory
that has been allocated becomes
inaccessible and can no longer be freed
Summary (cont.)
• A destructor is a member function that’s
called just before an object is destroyed
• If you don’t write a destructor of your own,
the complier will supply a default destructor
for you
• The copy constructor is a member function
that’s invoked when an automatic copy of
an object is made
• A default copy constructor is supplied for a
class if you don’t write one of your own
• The default copy constructor simply copies
the value of each data member to data
members with the same names in the copy,
producing a shallow copy
Summary (cont.)
• A deep copy is a copy of an object that has
no chunks of memory in common with the
original
• A default assignment operator member
function, which produces a shallow copy, is
supplied for you if you don’t write one of
your own
Download