《C++游戏编程入门》第9章 高级类与动态内存:Game Lobby
- 9.1 使用聚合体
- 09.critter_farm.cpp
- 9.2 使用友元函数与运算符重载
- 09.friend_critter.cpp
- 9.3 动态分配内存
- 09.heap.cpp
- 9.4 使用数据成员与堆
- 09.heap_data_member.cpp
- 9.5 Game Lobby程序
- 09.game_lobby.cpp
9.1 使用聚合体
对象的组合,对象成员变量含其他对象。
09.critter_farm.cpp
#include <iostream>
#include <string>
#include <vector>
using namespace std;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;
}class Farm
{
public:Farm(int spaces = 1);void Add(const Critter &aCritter);void RollCall() const;private:vector<Critter> m_Critters;
};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";
}int main()
{Critter crit("Poochie");cout << "My critter's name is " << crit.GetName() << endl;cout << "\nCreating critter farm.\n";Farm myFarm(3);cout << "\nAdding three critters to the farm.\n";myFarm.Add(Critter("Moe"));myFarm.Add(Critter("Larry"));myFarm.Add(Critter("Curly"));cout << "\nCalling Roll...\n";myFarm.RollCall();return 0;
}
9.2 使用友元函数与运算符重载
友元函数对类的任何成员都有完全的访问权。
09.friend_critter.cpp
#include <iostream>
#include <string>
using namespace std;class Critter
{// 友元函数friend void Peek(const Critter &aCritter);friend ostream &operator<<(ostream &os, const Critter &aCritter);public:Critter(const string &name = "");private:string m_Name;
};Critter::Critter(const string &name): m_Name(name)
{
}void Peek(const Critter &aCritter);
ostream &operator<<(ostream &os, const Critter &aCritter);int main()
{Critter crit("Poochie");cout << "Calling Peek() to access crit's private data member, m_Name: \n";Peek(crit);cout << "\nSending crit object to cout with the << operator:\n";cout << crit;return 0;
}void Peek(const Critter &aCritter)
{cout << aCritter.m_Name << endl;
}// 运算符重载
ostream &operator<<(ostream &os, const Critter &aCritter)
{os << "Critter Object - m_Name: " << aCritter.m_Name;return os;
}
9.3 动态分配内存
堆(自由存储区),程序员负责分配与释放。
09.heap.cpp
#include <iostream>
using namespace std;int *intOnHeap(); // returns an int on the heap
void leak1(); // creates a memory leak
void leak2(); // creates another memory leakint main()
{int *pHeap = new int;//new运算符*pHeap = 10;cout << "*pHeap: " << *pHeap << "\n\n";int *pHeap2 = intOnHeap();cout << "*pHeap2: " << *pHeap2 << "\n\n";cout << "Freeing memory pointed to by pHeap.\n\n";delete pHeap;//显示地释放cout << "Freeing memory pointed to by pHeap2.\n\n";delete pHeap2;// get rid of dangling pointerspHeap = nullptr;pHeap2 = 0;return 0;
}int *intOnHeap()
{int *pTemp = new int(20);//分配同时初始化return pTemp;
}void leak1()
{int *drip1 = new int(30);
}void leak2()
{int *drip2 = new int(50);drip2 = new int(100);delete drip2;
}
9.4 使用数据成员与堆
09.heap_data_member.cpp
#include <iostream>
#include <string>
using namespace std;class Critter
{
public:Critter(const string &name = "", int age = 0); // 构造函数~Critter(); // 析构函数Critter(const Critter &c); // 拷贝构造函数Critter &operator=(const Critter &c); // 拷贝赋值运算符void Greet() const;private:string *m_pName;int m_Age;
};Critter::Critter(const string &name, int age)
{cout << "Constructor called\n";m_pName = new string(name); // 分配堆空间m_Age = age;
}Critter::~Critter() // destructor definition
{cout << "Destructor called\n";delete m_pName; // 释放堆空间
}Critter::Critter(const Critter &c) // copy constructor definition
{cout << "Copy Constructor called\n";m_pName = new string(*(c.m_pName));m_Age = c.m_Age;
}Critter &Critter::operator=(const Critter &c) // overloaded assignment op def
{cout << "Overloaded Assignment Operator called\n";if (this != &c){delete m_pName;m_pName = new string(*(c.m_pName));m_Age = c.m_Age;}return *this;
}void Critter::Greet() const
{cout << "I'm " << *m_pName << " and I'm " << m_Age << " years old. ";cout << "&m_pName: " << &m_pName << endl;
}void testDestructor();
void testCopyConstructor(Critter aCopy);
void testAssignmentOp();int main()
{testDestructor();cout << endl;Critter crit("Poochie", 5);crit.Greet();testCopyConstructor(crit);crit.Greet();cout << endl;testAssignmentOp();return 0;
}void testDestructor()
{Critter toDestroy("Rover", 3);toDestroy.Greet();
}void testCopyConstructor(Critter aCopy)
{aCopy.Greet();
}void testAssignmentOp()
{Critter crit1("crit1", 7);Critter crit2("crit2", 9);crit1 = crit2;crit1.Greet();crit2.Greet();cout << endl;Critter crit3("crit", 11);crit3 = crit3;crit3.Greet();
}
9.5 Game Lobby程序
09.game_lobby.cpp
#include <iostream>
#include <string>
using namespace std;class Player
{
public:Player(const string &name = "");string GetName() const;Player *GetNext() const;void SetNext(Player *next);private:string m_Name;Player *m_pNext; // Pointer to next player in list
};Player::Player(const string &name): m_Name(name), m_pNext(nullptr)
{
}string Player::GetName() const
{return m_Name;
}Player *Player::GetNext() const
{return m_pNext;
}void Player::SetNext(Player *next)
{m_pNext = next;
}class Lobby
{friend ostream &operator<<(ostream &os, const Lobby &aLobby);public:Lobby();~Lobby();void AddPlayer();void RemovePlayer();void Clear();private:Player *m_pHead;
};Lobby::Lobby(): m_pHead(nullptr)
{
}Lobby::~Lobby()
{Clear();
}void Lobby::AddPlayer()
{// create a new player nodecout << "Please enter the name of the new player: ";string name;cin >> name;Player *pNewPlayer = new Player(name);// if list is empty, make head of list this new playerif (m_pHead == nullptr){m_pHead = pNewPlayer;}// otherwise find the end of the list and add the player thereelse{Player *pIter = m_pHead;while (pIter->GetNext() != nullptr)pIter = pIter->GetNext();pIter->SetNext(pNewPlayer);}
}void Lobby::RemovePlayer()
{if (m_pHead == nullptr){cout << "The game lobby is empty. No one to remove!\n";}else{Player *pTemp = m_pHead;m_pHead = m_pHead->GetNext();delete pTemp;}
}void Lobby::Clear()
{while (m_pHead != nullptr)RemovePlayer();
}ostream &operator<<(ostream &os, const Lobby &aLobby)
{Player *pIter = aLobby.m_pHead;os << "\nHere's who's in the game lobby:\n";if (pIter == nullptr){os << "The lobby is empty.\n";}else{while (pIter != nullptr){os << pIter->GetName() << endl;pIter = pIter->GetNext();}}return os;
}int main()
{Lobby myLobby;int choice;do{cout << myLobby;cout << "\nGAME LOBBY\n";cout << "0 - Exit the program.\n";cout << "1 - Add a player to the lobby.\n";cout << "2 - Remove a player from the lobby.\n";cout << "3 - Clear the lobby.\n\n";cout << "Enter choice: ";cin >> choice;switch (choice){case 0:cout << "Good-bye.\n";break;case 1:myLobby.AddPlayer();break;case 2:myLobby.RemovePlayer();break;case 3:myLobby.Clear();break;default:cout << "That was not a valid choice.\n";}} while (choice != 0);return 0;
}