c++ set value of a class with a pointer of another class - c++

I am trying to implement the game Deal or no deal, i have two classes, Box & Player. in box is stored the vector game_box and in Player I want to store the box and the money that the player has to keep till the end of the game.
I have tried to implement it in this way. it runs correctly, without no errors, but when i try to verify if the values were stored into the setter, it just give me that the setter is empty. I really dont understand why! does anybody knows why?
class Box
{
vector<Box> game_box;
float pound_contained;
int box_number;
public:
Box(int box_number, float pound_contained);
Box();
int getbox_number();
float getpound_contained();
};
class Player :public Box
{
int player_box;
float player_money;
public:
Player();
~Player();
float getplayer_money();
int getplayer_box();
void setplayer_money(float);
void setplayer_box(int);
};
void Player::setplayer_money(float)
{
player_money = player_money;
}
void Player::setplayer_box(int)
{
player_box = player_box;
}
float Player::getplayer_money()
{
return this->player_money;
}
int Player::getplayer_box()
{
return this->player_box;
}
int main()
{
vector<Box> game_box;
srand(time(0));
int n;
Player money;
Box oper;
float myArray [22][2] = { { 0.01, 0 }, { 0.10, 0 }, { 0.50, 0 },
{ 1, 0 }, { 5, 0 }, { 10, 0 },
{ 50, 0 }, { 100, 0 }, { 250, 0 },
{ 500, 0 }, { 750, 0 }, { 1000, 0 },
{ 3000, 0 }, { 5000, 0 }, { 10000, 0 },
{ 15000, 0 }, { 20000, 0 }, { 35000, 0 },
{ 50000, 0 }, { 75000, 0 }, { 100000, 0 },
{ 250000, 0 }
};
//random assignation of pound value to the 22 boxes
for (int e = 1; e <22; e++)
{
int pos;
bool op = true;
while (op)
{
pos = rand() % 22 + 1;
if (myArray[pos][1] == 0)
{
myArray[pos][1] = 1;
op = false;
}
}
Box b(e, myArray[pos][0]); //creating the class game
game_box.push_back(b); //function of the vector to insert a data in it
}
// random assignment of a box to the player
int i = rand() % 22 + 1;
Box* boxes = &game_box[i];
cout << "Your box is going to be the box number: "<< boxes->getbox_number()<<endl;
////////////////////////////////////////////////////////////////////setter not working
money.setplayer_money(boxes->getpound_contained());
money.setplayer_box(oper.getbox_number());
cout << money.getplayer_box() << " " << money.getplayer_money() << endl << endl;
game_box.erase(game_box.begin()+i);
return 0;
}

There are not "setters" or "getters" in C++ that are distinct from other method calls. So you write them just as you would any other method.
To elaborate on the problem pointed out by #maniek, you wrote:
void Player::setplayer_money(float)
{
player_money = player_money;
}
C and C++ have the ability to specify method and function arguments without names--just types. This might seem a little strange as there is no way to access that parameter (at least not a way that is guaranteed to work in all compilers or optimization levels, you can possibly do it by messing with the stack). So what you are doing here is just setting the member player_money to itself.
(Note: If you are wondering why it allows you to specify a method argument without a name, it has a few uses...one is that not naming it suppresses warning messages that you aren't using that parameter. So it is a way of marking something as not being used at the current time, yet still required--perhaps for legacy reasons or perhaps because you might use it in the future.)
You can give a new name to the parameter that doesn't overlap with the name of the member variable:
void Player::setplayer_money(float new_player_money)
{
player_money = new_player_money;
}
That's one way of avoiding ambiguity. Because in terms of what value is in scope, the parameter will win over the member variable. So this would be another do-nothing operation, that would assign the parameter value to itself:
void Player::setplayer_money(float player_money)
{
player_money = player_money;
}
(Note: Since player_money is passed by value and not by reference, that wouldn't change the parameter's value at the calling site. In particular, how could it change the value, if you passed in a constant like 10.20.)
What #maniek suggested is that a way to disambiguate in that case is to use this->player_money when you mean the member variable and player_money when you mean the argument to the method. Another thing some people do is name their member variables specially--like start them with m_ as in m_player_money:
void Player::setplayer_money(float player_money)
{
m_player_money = player_money;
}
(Note: You can also just use an underscore prefix with no m as long as the next character is lowercase, but some people consider that too dangerous as underscores followed by capital letters are reserved for compiler internal usages.)
As a final thought--if the class name is Player then it's already implicit whose money you are setting (the player's) so you could just call it set_money. Furthermore, I'm not a fan of underscores in names (more common in C than C++) so I'd probably call it setMoney.

How about:
void Player::setplayer_money(float player_money)
{
this->player_money = player_money;
}
?

Related

Is it good practice to have boolean "recursiveCall" parameter in a function?

I have a function which calls itself, but to avoid infinite recursion when the function is calling itself I pass a boolean variable so it does not call itself again. However this also means someone using my code can use the function and pass it a true argument.
class Test
{
public:
static bool doCheck(int x, bool recursiveCall = false)
private:
int m_array {10, 5, 3, 25, 12, 0, -6};
int tracker = 0;
};
bool Test::doCheck(int x, bool recursiveCall)
{
if (m_array[tracker] > x)
{
//do stuff
++tracker;
return true;
}
else if (!recursiveCall)
{
// reset tracker
tracker = 0;
return doCheck(x, true);
}
return false;
}
int main()
{
Test::doCheck(2); // returns true, m_array[tracker] now equals 5
// The next call will go through the "else if" part which will reset the tracker
// and return false, if we didn't call the function as recursive it would call itself infinitely !
Test::doCheck(50);
return 0;
}
Edit: As requested I provided a better example. Of course we could perform the m_array[tracker] > x before calling doCheck() again but it means our check will be done twice, and it can be problematic if we check some things using a more complex algorithm
Is it good practice to do that?
No, that's a bad idea. Instead re-write your base case so that it will always stop on it's own.
Your example is never going to sensibly recurse, so it may as well be
void foo(int x)
{
if (x > 10)
{ /* Do stuff here */ }
}

C++ member of class updated outside class

I have a question about pointers and references in C++. I am a programmer who normally programs in C# and PHP.
I have two classes (for now) which are the following.
The X/Y in Controller are continuously changing but i want them up to date in the Commands. I have multiple commands like Forward, Turn, Backward etc.
When i make the commands i give them the controller but the state (X, Y) of the controller are updating every second.
How can i fix that the controller attribute in the Commands are getting updated also every second?
class Forward : ICommand
{
Controller ctrl;
void Execute() {
int CurrentX = ctrl.X;
int CurrentY = ctrl.Y;
//Check here for the current location and calculate where he has to go.
}
}
class Controller
{
int X;
int Y;
void ExecuteCommand(ICommand command) {
command.Execute();
}
}
Main.cpp
Controller controller;
Forward cmd1 = new Forward(1, controller);
Turn cmd2 = new Turn(90, controller);
Forward cmd3 = new Forward(2, controller);
controller.Execute(cmd1);
controller.Execute(cmd2);
controller.Execute(cmd3);
I have read something about pointers and references and i think i have to use this but don't know how to use it in this situation.
(code can have some syntax errors but that's because i typed over. Everything is working further except for the updating).
If you use references rather than copy objects you can see changes.
#include <iostream>
using namespace std;
class ICommand
{
public:
virtual ~ICommand() = default;
virtual void Execute() = 0;
};
class Controller
{
public:
int X = 0;
int Y = 0;
void ExecuteCommand(ICommand & command) {
// ^-------
command.Execute();
}
};//,--- semicolons required
class Forward : public ICommand //note public
{
const int step;
Controller ctrlCopy;
Controller & ctrlReference;
public:
Forward(int step, Controller & ctrl) :
step(step),
ctrlCopy(ctrl), //this is a copy of an object
ctrlReference(ctrl) //this is a reference to an object
{
}
void Execute() {
std::cout << "copy: " << ctrlCopy.X << ", " << ctrlCopy.Y << '\n';
std::cout << " ref: " << ctrlReference.X << ", " << ctrlReference.Y << '\n';
//Check here for the current location and calculate where he has to go.
ctrlCopy.X += 10;
ctrlReference.X += 10;
}
};//<--- semicolons required
int main() {
Controller controller;
Forward cmd1(1, controller);
//Turn cmd2(90, controller); //Left for the OP to do
Forward cmd3(2, controller);
controller.ExecuteCommand(cmd1);
//controller.ExecuteCommand(cmd2);
controller.ExecuteCommand(cmd3);
//Do it again to show the copy and reference difference
std::cout << "Once more, with feeling\n";
controller.ExecuteCommand(cmd1);
controller.ExecuteCommand(cmd3);
}
Giving
copy: 0, 0
ref: 0, 0
copy: 0, 0 // [1]
ref: 10, 0 // [2]
Once more, with feeling
copy: 10, 0
ref: 20, 0
copy: 10, 0
ref: 30, 0
1 shows that the copy has X and Y of 0, while the reference shown in [2] has moved by the stated step (in controller.ExecuteCommand(cmd3))
Note, we don't need to use new to make this work (don't forget delete if you use new).
Also, void ExecuteCommand(ICommand command) now takes a reference instead otherwise the by-value copy does "slicing" (e.g. see here)

refer to global data from a template function?

Templates generally are inline - you have to supply the definition with the declaration.
Global (static) data requires that there be exactly one definition of the data (but it can be declared multiple times).
So, for a class with static data, one normally declares the static in the class definition (header), and the storage as static in the implementation file (.cpp).
But what does one do for a template that needs to refer to static / global data?
Here's a bit of code to give you something somewhat concrete to consider:
// we represent in a formal manner anything that can be encoded in a MSVS format specification
// A format specification, which consists of optional and required fields, has the following form:
// %[flags][width][.precision][{h | l | ll | w | I | I32 | I64}] type
// based on https://msdn.microsoft.com/en-us/library/56e442dc.aspx
struct FormatSpec
{
enum Size {
normal,
h,
l,
ll,
w,
I,
I32,
I64
};
enum Type {
invalid,
character,
signed_integer,
unsigned_integer,
unsigned_octal,
unsigned_hex,
floating_point,
expontential_floating_point,
engineering_floating_point,
hex_double_floating_point,
pointer,
string,
z_string
};
unsigned fLeftAlign : 1;
unsigned fAlwaysSigned : 1;
unsigned fLeadingZeros : 1;
unsigned fBlankPadding : 1;
unsigned fBasePrefix : 1;
unsigned width;
unsigned precision;
Size size_;
Type type_;
};
struct FormatSpecTypeDatum
{
FormatSpec::Type id; // id
const TCHAR * symbol; // text symbol
};
FormatSpecTypeDatum kTypeSpecs[] =
{
{ FormatSpec::character, _T("c") },
{ FormatSpec::character, _T("C") },
{ FormatSpec::signed_integer, _T("d") },
{ FormatSpec::signed_integer, _T("i") },
{ FormatSpec::unsigned_octal, _T("o") },
{ FormatSpec::unsigned_integer, _T("u") },
{ FormatSpec::unsigned_hex, _T("x") },
{ FormatSpec::unsigned_hex, _T("X") },
{ FormatSpec::expontential_floating_point, _T("e") },
{ FormatSpec::expontential_floating_point, _T("E") },
{ FormatSpec::floating_point, _T("f") },
{ FormatSpec::floating_point, _T("F") },
{ FormatSpec::engineering_floating_point, _T("g") },
{ FormatSpec::engineering_floating_point, _T("G") },
{ FormatSpec::hex_double_floating_point, _T("a") },
{ FormatSpec::hex_double_floating_point, _T("A") },
{ FormatSpec::pointer, _T("p") },
{ FormatSpec::string, _T("s") },
{ FormatSpec::string, _T("S") },
{ FormatSpec::z_string, _T("Z") },
};
template <typename ctype>
bool DecodeFormatSpecType(const ctype * & format, FormatSpec & spec)
{
for (unsigned i = 0; i < countof(kTypeSpecs); ++i)
if (format[0] == kTypeSpecs[i].symbol[0])
{
spec.type_ = kTypeSpecs[i].id;
++format;
return true;
}
return false;
}
It's relatively simple - a symbolic ID to character representation lookup table.
I want to be able to use DecodeFormatSpecType<>() for char, unsigned char, wchar_t, etc.
I could remove the template from DecodeFormatSpecType() and just supply overloaded interfaces for various character types.
The main thing is that the data isn't really changing - an unsigned char 'c' and a wchar_t 'c' and a legacy char 'c' have the exact same value, regardless of the character's storage size (for core ASCII characters this is true, although there are undoubtedly some other encodings such as EDBIC where this isn't true, that's not the problem I'm attempting to solve here).
I just want to understand "how do I construct my C++ libraries so that I can access global data defined in exactly one location - which is stored as an array - and I want the accessing templated code to know the length of the global data, just like I can with normal non-templated code have a global symbol table like what I've shown in my example code by having the table and the implementation that needs its size both exist in the appropriate .cpp file"
Does that make sense?
global data + functions that need to know the exact definition but also can be presented (with an interface) this generic (to a valid domain).
A function template can use global functions and global data without any problem.
If you want to encapsulate the definition of kTypeSpecs and not have it defined in a header file, you can use couple of functions to provide access to the data.
size_t getNumberOfTypeSpecs();
// Provide read only access to the data.
FormatSpecTypeDatum const* getTypeSpecs();
and then implement DecodeFormatSpecType as
template <typename ctype>
bool DecodeFormatSpecType(const ctype * & format, FormatSpec & spec)
{
size_t num = getNumberOfTypeSpecs();
FormatSpecTypeDatum const* typeSpecs = getTypeSpecs();
for (unsigned i = 0; i < num; ++i)
if (format[0] == typeSpecs[i].symbol[0])
{
spec.type_ = typeSpecs[i].id;
++format;
return true;
}
return false;
}
The functions getNumberOfTypeSpecs and getTypeSpecs can be implemented in a .cpp file as:
// Make the data file scoped global variable.
static FormatSpecTypeDatum kTypeSpecs[] =
{
{ FormatSpec::character, _T("c") },
{ FormatSpec::character, _T("C") },
{ FormatSpec::signed_integer, _T("d") },
{ FormatSpec::signed_integer, _T("i") },
{ FormatSpec::unsigned_octal, _T("o") },
{ FormatSpec::unsigned_integer, _T("u") },
{ FormatSpec::unsigned_hex, _T("x") },
{ FormatSpec::unsigned_hex, _T("X") },
{ FormatSpec::expontential_floating_point, _T("e") },
{ FormatSpec::expontential_floating_point, _T("E") },
{ FormatSpec::floating_point, _T("f") },
{ FormatSpec::floating_point, _T("F") },
{ FormatSpec::engineering_floating_point, _T("g") },
{ FormatSpec::engineering_floating_point, _T("G") },
{ FormatSpec::hex_double_floating_point, _T("a") },
{ FormatSpec::hex_double_floating_point, _T("A") },
{ FormatSpec::pointer, _T("p") },
{ FormatSpec::string, _T("s") },
{ FormatSpec::string, _T("S") },
{ FormatSpec::z_string, _T("Z") },
};
size_t getNumberOfTypeSpecs()
{
return sizeof(kTypeSpecs)/sizeof(kTypeSpecs[0]);
}
FormatSpecTypeDatum const* getTypeSpecs()
{
return kTypeSpecs;
}
Update, in response to comment by OP
Yes, you can. The following are perfectly valid:
size_t getNumberOfTypeSpecs()
{
static constexpr size_t num = sizeof(kTypeSpecs)/sizeof(kTypeSpecs[0]);
return num;
}
constexpr size_t getNumberOfTypeSpecs()
{
return sizeof(kTypeSpecs)/sizeof(kTypeSpecs[0]);
}

Using enums and a for-loop to create instances of a class

enum { WOOD, BRICK, GRAIN, HEMP, WOOL, RAWMETAL, HONEY, SALT, METALGOODS, MEAD, CLOTH, BEER, STOCKFISH, CLOTHING, CHEESE, PITCH, PELTS, MEAT, WINE, SPICES, TOTALRESOURCES };
// An array of strings for each of the resource names
// As long as these are in the same order as the enum everything should match up
// .: resName[PIGIRON] is "Pig Iron"
string resName[]{ "Wood", "Brick", "Grain", "Hemp", "Wool", "Raw Metal", "Honey", "Salt", "Metal Goods", "Mead", "Cloth", "Beer", "Stockfish", "Clothing", "Cheese", "Pitch", "Pelts", "Meat", "Wine", "Spices" };
enum { Edinburgh, Scarborough, Boston, London, Bruges, Haarlem, Nimwegen, Groningen, Cologne, Minden, Bremen, Erfurt, Hamburg, Lubeck, Rostock, Berlin, Ripen, Flensburg, Aalborg, Naevsted, Bergen, Stavanger, Oslo, Stockholm, Gothenburg, Malmo, Ahus, Visby, Stettin, Posen, Breslau, Danzig, Thorn, Warsaw, Konigsberg, Kaunas, Riga, Reval, Helsinki, Novgorod, TOTALTOWNS};
string townName[]{ "Edinburgh", "Scarborough", "Boston", "London", "Bruges", "Haarlem", "Nimwegen", "Groningen", "Cologne", "Minden", "Bremen", "Erfurt", "Hamburg", "Lubeck", "Rostock", "Berlin", "Ripen", "Flensburg", "Aalborg", "Naevsted", "Bergen", "Stavanger", "Oslo", "Stockholm", "Gothenburg", "Malmo", "Ahus", "Visby", "Stettin", "Posen", "Breslau", "Danzig", "Thorn", "Warsaw", "Konigsberg", "Kaunas", "Riga", "Reval", "Helsinki", "Novgorod"};
class resource
{
public:
float demand, production, businessNeeds, businessProduction;
// This function, called a constructor, is run every time a new resource is created
// In this case, it assigns 0 to everything
resource()
{
demand = 0;
production = 0;
businessNeeds = 0;
businessProduction = 0;
}
float net()
{
return (this->production - this->demand);
}
float businessNet()
{
return (this->businessProduction - this->businessNeeds);
}
};
class town
{
public:
// The array of pointers to each of a our resource objects
resource *resList[TOTALRESOURCES];
// This is the town constructor
town()
{
// Loops through the array and creates a new resource object in each
// the resource constructor assigns the default values of 0.
for (int i = 0; i < TOTALRESOURCES; i = i + 1)
{
resList[i] = new resource();
}
}
~town()
{
// Loops through the array and deletes each resource object
for (int i = 0; i < TOTALRESOURCES; i = i + 1)
{
delete resList[i];
}
};
int main()
{
//What do I do here?
for (int i = 0; i < TOTALTOWNS; i++)
{
town townName[i];
}
system("pause");
return 0;
}
So, I'm a software engineering student and I just switched majors so I decided to take some personal time to learn how to code in c++ a bit better. I decided to build a program that can plan the logistics for a videogame called Patrician IV.
I have put about 5 days worth of work into this project and have found some serious problems with my initial code (hard to add new functionality and change stuff around). So I took a step back and am trying to build my classes in a more succinct manner while also being able to loop through each instance of town later in a loop so I can update the demand, production, businessNeeds, and businessProduction values easily. I was copying and pasting about 6 lines of code 40 times before this.
I want to know:
(A) is it possible to do what I want - i.e. can I use enums and a for-loop to construct instances of town.
(B) how to loop through each of the towns so that I can add values to the resource variables.
(C) a third-grade-level explanation of how to use pointers for similar purposes would also be great.
:) THANK YOU!
In your main function, use the same idea as resList to initialize your town objects, so:
town* townName[TOTALTOWNS]
for (int i = 0; i < TOTALTOWNS; i++)
{
townName[i]= new town();
}
Then, I'm guessing you want to give different values for each of the different resources. Switch statements go along with enums well. So I would recommend something like this:
for (int i = 0; i < TOTALRESOURCES; i = i + 1)
{
switch(i)
{
case WOOD:
townName[EDINBURGH]->resList[WOOD]->demand= yourValue;
break;
case BRICK:
break;
}
}
Or if you're cycling through towns:
for (int i = 0; i < TOTALTOWNS; i = i + 1)
{
switch(i)
{
case EDINBURGH:
break; //etc.
}
}
If you only want to update a single town or resource, depending on how you're organizing everything, you could create something like this. A function that takes your town array and the enum indexes, like this:
updateTownResources(town* (*townName)[TOTALTOWNS], int townEnum, int resourceEnum, int dValue, int pValue )
{
townName[townEnum]->resList[resourceEnum]->demand= dValue;
townName[townEnum]->resList[resourceEnum]->production= pValue;
//etc...
}
int main()
{
std::vector<town*> townArray;
//What do I do here?
for (int i = 0; i < TOTALTOWNS; i++)
{
town* pTown = new(std::nothrow) town;
townArray.push_back (pTown);
}
std::vector<town*>::iterator iter = townArray.begin();
for (;iter != townArray.end(); iter++) {
(*iter); // gives access to individual objects
}
system("pause");
return 0;
}

Copy Dynamic Struct Array into another C++

I'm not that good in English, that's why my Question is probably wrong. But I have a problem and I don't know how to solve it or if it's even possible to do.
I have 2 Structs defined:
typedef struct
{
UINT16 ScriptNumber;
std::string ScriptText;
} StepStruct;
typedef struct
{
std::string SequenceName;
std::string DisplayName;
StepStruct SequenceSteps;
} SequenceStruct;
As you can see, the first Struct is a Member of the second struct. So I want both structs to by dynamical. So I created 2 Dynamic Arrays from the Type StepStruct and 1 dynamic Array from the Type SequenceStruct.
The two dynamical Arrays for of the Type StepStructs are defined as follows:
StepStruct gsFirstSkript[] =
{
{ 1 , "SkriptText One"},
{ 2 , "SkriptText Two"},
{ 45, "SkriptText Three"}
}
StepStruct gsSecondSkript[] =
{
{ 48, "SkriptText One"},
{ 2 , "SkriptText Two"},
{ 45, "SkriptText Three"}
}
Those to Structs are of the Type StepStruct. Now I want to do the Same with a SequenceStruct Type, but I want to assign the two Arrays I already have to it under the Struct Member SequenceSteps. I mean this as follows:
SequenceStruct gsSequenceList[] =
{
{ "FirstScript", "Test One", gsFirstSkript},
{ "SecondScript", "Test Two", gsSecondSkript}
}
If I now want to Read the Member gsSequenceList, I can not access any information under the SequenceSteps Index of it! What means, that the Data is not copied! I tried it with Pointers
but had no success.
UINT16 lTestVal = gsSequenceList[0].SequenceSteps[2].ScriptNumber;
So Can I mangage that this works, and lTestVal contains the Value 45?
typedef struct
{
std::string SequenceName;
std::string DisplayName;
StepStruct* SequenceSteps;
} SequenceStruct;
This will allow the code to compile and the test fragment you've shown will work.
However this will not copy the data. If you change gsFristSkript it will change in gsSequenceList as well. If you want to make a copy of the data you can either do that explicitly, have a constructor or just use vector<>.
Here's the solution with vector:
#include <vector>
...
typedef struct{
std::string SequenceName;
std::string DisplayName;
vector<StepStruct> SequenceSteps;
} SequenceStruct;
vector<StepStruct> gsFirstSkript =
{
{ 1 , "SkriptText One"},
{ 2 , "SkriptText Two"},
{ 45, "SkriptText Three"}
}
vector<StepStruct> gsSecondSkript =
{
{ 48, "SkriptText One"},
{ 2 , "SkriptText Two"},
{ 45, "SkriptText Three"}
}
SequenceStruct gsSequenceList[] =
{
{ "FirstScript", "Test One", gsFirstSkript},
{ "SecondScript", "Test Two", gsSecondSkript}
}