|
|
|
|
|
|
case 1:{player.GetPlrHealthPacks() += amountChoice * itemQuantity;}break;
GetPlrHealthPacks()
is a function call that returns a value, one can't assign a value to it.public
. Using initialiser list in the constructor might eliminate the need for some of the set functions. Consider using a Mediator Design Pattern.http://en.wikipedia.org/wiki/Mediator_pattern http://patterns.pl/mediator.html |
CResource
, along with Derived classes for individual resources such as cash, ammo etc.CPlayer
who is going to be using the resources, provide an interface function called AcquireResource
which takes a smart pointer to CResource
. This is very important to take advantage of polymorphism. When this function is called, the argument will be a smart pointer to whatever the object is - ammo say.AcquireResource
can use the interface of the particular Resource to update the values inside CPlayer
. The CResource
class can have a protected bool AllowAcess
variable (Inherited by derived classes), which dictates whether get functions should return a value or not. Each get function would check this variable before returning anything.CSuperMarket
scenario, the supermarket can maintain an CInventory
which keeps track of how many resorces there are, and can allow items to be purchased via a CTransaction
process, setting the AllowAcess
to true
, effectively signalling that the object has been bought, and the buyer can acccess the information.Thanks for the tips, I'm still learning so Design Patterns are still too complicated for me right now. |
std::vector<CResource *>
. (Using smart pointers)CResource* AcquireResource(CResource *TheResource);
function .CAmmo
.class CAmmo : public CResource {};
CShop
that AcquireResource
function can call to "Acquire" the object's info.http://patterns.pl/mediator.html |
And doesn't this point out that an item has both a type and a quantity? |
std::tuple
for that, std::pair
might have been OK, but we can later add things to a tuple. A tuple is just the same a record in a database, we can group things together without having to make a class for them.CPlayer
has a vector
of possessions of type CResource*
, we have generalised it, meaning a CPlayer can possess any kind of resource, rather than just the ones hard coded into the class declaration in the OP.CPerson
class, with members m_FirstName
, m_MiddleName
, m_LastName
, m_AddressLIne1
, m_AddressLine2
, m_State
, m_PostCode
, m_Country
, m_DateOfBirth, m_DriversLicence
etc.std::vector<std::string>
- people have more than 3 names. But if it was made a class, then one could have functionality of printing out middle initials, if required. Often people would rather not receive mail with all their names in full.unsigned
. Should there be a maximum limit? If the type was unsigned int
, that would mean the player could have a very large amount of ammo. Should we change the type to something smaller, or should we have another const
variable that is the limit? For example, in one of the TombRaider games, a limit was imposed for how many weapons could be carried (4 I think), and there was a limit to the number of grenades & Health Packs.CTriangle
class. Btw, I wouldn't actually do that, but bear with me for a minute :+)MoveVertex1(double DeltaX, double DeltaY)
, MoveVertex2(double DeltaX, double DeltaY)
, MoveVertex3(double DeltaX, double DeltaY)
.Move(double DeltaX, double DeltaY)
, this function would deal with the private variables. I wouldn't have variables Vertex1
, Vertex2
, Vertex3
either - I would have a vector of vertex's instead.CRegularPolygon
, and CIrregularPolygon
derived from CShape
. An equilateral triangle is a regular polygon with 3 sides, other types of triangle are irregular polygons with 3 sides. In all the cases they are stored as a vector of points. A regular polygon can be defined by a centroid point, a radius (internal or external), and the number of sides. Hint: an n sided regular polygon can be made from n triangles with the centroid being common to them all.CShape
class, as they would be the same, no matter what the shape is. Try to push your functions as high up the inheritance tree as you can, so you only define them once. This is why it is important to generalise things as much as possible.What should I do then? just make them all public? I actually had that before i edited it a few days ago. Also, to be honest I would just like to keep things simple, I have a lot to learn still and i dont want to complicate it by learning something complex like design patterns. I will learn them, just not right now, I need to crawl before I can walk here. |
CurrentWeapon->Reload
rather than getting / setting Ammo Levels with functions. The manipulation of these variables happens inside the Reload
function.41. Make data members private, except in behaviorless aggregates (C-style structs) Summary They're none of your caller's business: Keep data members private. Only in the case of simple C-style struct types that aggregate a bunch of values but don't pretend to encapsulate or provide behavior, make all data members public. Avoid mixes of public and nonpublic data, which almost always signal a muddled design. Discussion Information hiding is key to good software engineering. Prefer making all data members private; private data is the best means that a class can use to preserve its invariants now, and to keep preserving them in the face of future changes. Public data is bad if a class models an abstraction and must therefore maintain invariants. Having public data means that part of your class's state can vary uncontrollably, unpredictably, and asynchronously with the rest of its state. It means that an abstraction is sharing responsibility for maintaining one or more invariants with the unbounded set of all code that uses the abstraction, and that is obviously, fundamentally, and indefensibly flawed. Reject such designs outright. ... Nonprivate data members are almost always inferior to even simple passthrough get/set functions, which allow for robust versioning. Examples Example 1: Proper encapsulation. Most classes (e.g., Matrix, File, Date, BankAccount, Security) should have all private data members and expose adequate interfaces. Allowing calling code to manipulate their internals directly would directly work against the abstraction they provide and the invariants they must sustain. Example 2: ... Example 3: Getters and setters. If there is no better domain abstraction available, public and protected data members (e.g., color) can at least be made private and hidden behind get and set functions (e.g., GetColor, SetColor); these provide a minimal abstraction and robust versioning. Using functions raises the level of discourse about "color" from that of a concrete state to that of an abstract state that we are free to implement as we want: We can change to an internal color encoding other than int, add code to update the display when changing color, add instrumentation, and make many other changes without breaking calling code. ... - Sutter and Alexandrescu in 'C++ Coding Standards: 101 Rules, Guidelines, and Best Practices' |
There are several benefits to be obtained from restricting access to a data structure to an explicitly declared list of functions. For example, any error causing a Date to take on an illegal value (for example, December 36, 2016) must be caused by code in a member function. This implies that the first stage of debugging – localization – is completed before the program is even run. This is a special case of the general observation that any change to the behavior of the type Date can and must be effected by changes to its members. In particular, if we change the representation of a class, we need only change the member functions to take advantage of the new representation. User code directly depends only on the public interface and need not be rewritten (although it may need to be recompiled). Another advantage is ... - Stroustrup in 'The C++ Programming Language' |
It is extremely unlikely that Stroustrup, Koenig, Lippman or Alexandrescu would give you wrong advice. |
With getters/setters, you lose the ability to increment/decrement |
|
|
to take a reference (except perhaps a const reference with the getter), and to take the address. |
&a[0]
)
The idea is to think about Actions (doing things) rather manipulating the member data |
|
|
|
|