CS11 – Introduction to C++ Spring 2013-2014 Lecture 7Computer Strategy Game ! Want to write a turn-based strategy game for the computer ! Need different kinds of units for the game " Different capabilities, strengths, weaknesses, etc. ! Examples: " Infantry unit " Transport ship " TrebuchetUnit Classes ! Infantry unit data members: " Current location, strength, experience level " Who owns the unit ! Member functions: " Move to another location " Attack another unit, receive attack from another unit ! What about transport ships? " Probably not “experience level” or “attack a unit” " Need to add a list of things the ship is carrying ! Trebuchets are very similar to infantry units " Just a different way of attacking other unitsCommon Themes ! Very clear we have common themes here! " All units have a location, strength, owner " All units can move around " All units can be attacked ! Also have specialized capabilities " Infantry units and trebuchets can’t carry other stuff, and they can’t make it very far on water " Of course, boats can’t make it very far on landSingle-Class Implementation ! Doesn’t make sense to put all features in one class class GameUnit { UnitType type; Point location; int playerID; int strength; // For transport ships only! int transportCapacity; vector<GameUnit *> contents; public: ... bool move(const Map &map, int direction); // For infantry and trebuchets only! bool attack(const Map &map, int direction); // For transport ships only! bool transportItem(GameUnit *u); };Single-Class Implementation (2) ! Not a clean abstraction! " Both data and operations for infantry units are mixed together with transport ships, etc. " Hard to understand what is going on ! Very likely to lead to bugs, e.g. " Infantry units can accidentally carry other units " Transport ships can attack other units ! Also wastes space " Infantry unit doesn’t need list of units it’s carryingC++ Class Inheritance ! C++ provides class inheritance " (as do all OOP languages) ! Base class provides generalized capabilities " A “game unit” type with location and owner " Basic ability to move unit around, retrieve owner info, etc. ! Derived classes inherit the state and behavior of the base class " They can also move around or report the unit’s owner ! Derived classes also provide specialized capabilities " The “transport ship” type adds the ability to hold other units " The “trebuchet” type adds the capability to rain fiery death from aboveClass Inheritance (2) ! Class inheritance models an “is-a” relationship " An infantry unit “is a” game unit " A transport ship “is a” game unit " A trebuchet “is a” game unit ! Terminology: " Base class, parent class, superclass " Derived class, child class, subclassA Game Unit Base-Class class GameUnit { Point location; int playerID; int strength; public: GameUnit(const Point &loc, int owner, int strength); Point getLocation() const; bool move(const Map &map, int direction); string getUnitType() const { return "generic game unit"; } }; ! Basic features common to all game unitsExtending the Generic Game Unit ! Transport Ship class will extend GameUnit " Add in new state and behaviors class TransportShip : public GameUnit { int capacity; vector<GameUnit *> contents; public: TransportShip( /* TODO */ ); bool loadUnit(GameUnit *u); vector<GameUnit *> unloadAll(); }; " Don’t need to specify location, owner, etc. ! State and associated behaviors inherited from parent class " Can also provide new capabilities ! Ability to load and unload units from the transportGeneric Functions ! This class can use GameUnit type for its functions class TransportShip : public GameUnit { int capacity; vector<GameUnit *> contents; public: TransportShip( /* TODO */ ); bool loadUnit(GameUnit *u); vector<GameUnit *> unloadAll(); }; " Because any subclass of GameUnit “is a” GameUnit, we can pass any subclass to our load/unload functions " Don’t need to provide a version for each specific subclass! ! Same general principle for other APIs! " Write functions against the base-type where appropriateTransport-Ship Constructor ! Need to implement the transport ship constructor " Problem: base class also has its own data members " We need to initialize these members too ! First attempt: TransportShip(const Point &loc, int owner, int capacity) : location(loc), playerID(owner), strength(100), capacity(capacity) { assert(capacity > 0); } " Doesn’t compile! Subclasses cannot initialize base-class data members directly.Calling Base-Class Constructor ! Want to call the base-class constructor from the subclass constructor " Must call the base-class constructor in member initializer list " Must be the first item of the member initializer list! ! Transport ship constructor, take 2: TransportShip(const Point &loc, int owner, int capacity) : GameUnit(loc,owner,100),capacity(capacity) { assert(capacity > 0); } " Now we get to reuse our GameUnit constructor code!Initialization of Derived Classes ! Remember the class initialization process: " All (non-primitive) data members of a class are initialized before the class’ constructor-body is run " Constructor-body can refer to these members, because they have already been initialized ! The same is true for class hierarchies " Base-class initialization occurs before derived-class initialization " Derived class’ constructor body can also refer to data members in the base class!Initialization of Derived Classes (2) ! Initialization of base-class members usually happens automatically " Base class’ default constructor is called before the derived class is initialized " Don’t need to put this in the member initializer list; it happens automatically! ! But, not every base class has a default constructor! " …or, you may simply not want the default initialization ! In these cases, need to put the non-default base-class constructor call in the member initializer list " …and it needs to be first in the initializer list.Transport Ship’s Unit-Type ! GameUnit class has
View Full Document