1 / 37

Beginning C++ Through Game Programming, Second Edition

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

argus
Download Presentation

Beginning C++ Through Game Programming, Second Edition

An Image/Link below is provided (as is) to download presentation Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author. Content is provided to you AS IS for your information and personal use only. Download presentation by click this link. While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server. During download, if you can't get a presentation, the file might be deleted by the publisher.

E N D

Presentation Transcript


  1. Beginning C++ Through Game Programming, Second Edition by Michael Dawson

  2. Chapter 9 • Advanced Classes and Dynamic Memory: Game Lobby

  3. Objectives • Combine objects • Use friend functions • Overload operators • Dynamically allocate and free memory • Avoid memory leaks • Produce deep copies of objects

  4. 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

  5. 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

  6. 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; • }

  7. 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

  8. Farm Class • class Farm • { • public: • Farm(int spaces = 1); • void Add(const Critter& aCritter); • void RollCall() const; • private: • vector<Critter> m_Critters; • };

  9. 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"; • }

  10. 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; • }

  11. 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

  12. 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);

  13. 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)

  14. 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);

  15. Memory on the Heap Persists • int* intOnHeap() • { • int* pTemp = new int(20); • return pTemp; • } • Can access heap memory from another function • int* pHeap2 = intOnHeap();

  16. 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

  17. 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

  18. 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

  19. Memory Leak 1 (cont.) • To avoid • delete drip1 in leak1() function • OR return copy of drip1 and free memory later

  20. 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

  21. Memory Leak 2 (cont.) • To avoid leak, delete drip2 before assigning new memory address to it

  22. 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

  23. 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

  24. 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

  25. 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

  26. 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

  27. Default Copy Constructor Pitfalls • Default copy constructor creates shallow copies • Potential problem if object has data member on the heap

  28. Default Copy Constructor Pitfalls (cont.) • Deleting shallow copy leaves original object with dangling pointer

  29. 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

  30. 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; • }

  31. Copy Constructor Example - Continued • Copy constructor creates deep copy • When copy of object is destroyed, original is unaffected

  32. 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 member-wise 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.

  33. 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; • }

  34. 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

  35. 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

  36. 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

  37. 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

More Related