Not able to modify class composite data members - c++

I have 3 classes in my program that interact with each other and contain each other's instances:
class Inventory
{
public:
// Increment Data Members
void incrementHerbs() { herbs++; }
void incrementHealth() { health++; }
void incrementGold() { gold++; }
// Getters
int getHerbs() { return herbs; }
int getHealth() { return health; }
int getGold() { return gold; }
private:
int herbs = 0;
int health = 3;
int gold = 0;
};
class Player
{
public:
void setRow(int row) { this->rowCoordinate = row; }
void setCol(int col) { this->colCoordinate = col; }
int getRow() { return rowCoordinate; }
int getCol() { return colCoordinate; }
Inventory getBag() { return Bag; }
private:
int rowCoordinate;
int colCoordinate;
Inventory Bag;
};
class Board
{
public:
int getNumRows() { return numRows; }
int getNumCols() { return numCols; }
Player getPlayer() { return User; }
private:
int numRows;
int numCols;
char** maze;
Player User;
};
I am only instantiating a Board object in the main function. At a point in my program, I want to be able to increment the herb count in the inventory class through that object.
I have tried doing:
Board board;
board.getPlayer().getBag().incrementHerbs();
This call compiles without any errors but when I print out the herb count afterwards, the herb count is still the same.
It did not increment. What can be going wrong and what can I do?

What can be going wrong and what can I do?
In your Player class, your getBag() function returns a copy of Inventory (i.e. member Bag).
Inventory getBag() { return Bag; }
//^^^^^^----> is copy!
You need to return the reference in order to modify it
Inventory& getBag() { return Bag; }
//^^^^^^^^
The same issue with the Board's function getPlayer()
Player getPlayer() { return User; }
//^^^^----> is copy!
you need
Player& getPlayer() { return User; }
//^^^^^^
And here's a demo.

Related

C++, "friend class" that's defined in the same header

I'm following this tutorial to create a simple iterator, although they are iterating primitive int, I'm iterating an object type SpamValue.
I have class called SpamValue and another called SpamValueStackIter and they are tightly coupled, because I didn't want to expose a lot of getters, so I made one class SpamValueStackIter a "friend class" in SpamValue header.
#ifndef SPAMSTACK_H
#define SPAMSTACK_H
#include <iostream>
#include "SpamValue.h"
using namespace std;
class SpamStack
{
public:
friend class SpamValueStackIter;
SpamStack(SpamValue** SpamValueItems, int size)
{
_position =-1;
_total_size = size;
_SpamValueItems = new SpamValue*[_total_size];
int i=0;
for (; i<_total_size; i++)
{
this->_SpamValueItems[i] = SpamValueItems[i];
}
}
~SpamStack()
{
if (NULL!=_SpamValueItems)
{
/*delete each*/
int i =0;
for (; i<_total_size; i++)
{
if (NULL!=_SpamValueItems[i])
{
delete _SpamValueItems[i];
}
}
/*delete the array*/
delete [] _SpamValueItems;
}
}
/*push*/
void push(SpamValue* SpamValue)
{
_SpamValueItems[++_position];
}
/*pop*/
SpamValue* pop()
{
return _SpamValueItems[_position--];
}
/*isEmpty*/
bool isEmpty()
{
return (_position == -1);
}
/*getters*/
SpamValue** getSpamValueItems()
{
return this->_SpamValueItems;
}
int getTotalSize()
{
return _total_size;
}
SpamValueStackIter* createIterator()const;
private:
SpamValue** _SpamValueItems;
int _total_size;
int _position;
};
class SpamValueStackIter
{
const SpamStack* _stack;
int _index;
public:
SpamValueStackIter(const SpamStack *s)
{
_stack = s;
}
/*set index position to first item*/
void first()
{
_index = 0;
}
/*set index position to the next item in the iterator*/
void next()
{
_index++;
}
/*is the iteration completed */
bool isDone()
{
return _index == _stack->_position + 1;
}
/* return the current item */
SpamValue* currentItem()
{
return _stack->_SpamValueItems[index];
}
/*create a new iterator*/
SpamValueStackIter* SpamStack::createIterator()const
{
return new SpamValueStackIter(this);
}
};
#endif /* SPAMSTACK_H*/
In the SpamStack.h:, Im getting this error:
SpamStack.h:77:6: error: ‘SpamValueStackIter’ does not name a type
SpamValueStackIter* createIterator()const;
And also:
SpamStack.h:121:52: error: cannot define member function ‘SpamStack::createIterator tor’ within ‘SpamValueStackIter’
SpamValueStackIter* SpamStack::createIterator()const
Why can't SpamStack resolve the "friend class" that's defined in the same header?
After forward declaration, as suggested by others:
#ifndef SPAMSTACK_H
#define SPAMSTACK_H
#include <iostream>
#include "SpamValue.h"
using namespace std;
/*forward declare*/
class SpamValueStackIter;
class SpamStack
{
public:
friend class SpamValueStackIter;
SpamStack(SpamValue** SpamValueItems, int size)
{
_position =-1;
_total_size = size;
_SpamValueItems = new SpamValue*[_total_size];
int i=0;
for (; i<_total_size; i++)
{
this->_SpamValueItems[i] = SpamValueItems[i];
}
}
~SpamStack()
{
if (NULL!=_SpamValueItems)
{
/*delete each*/
int i =0;
for (; i<_total_size; i++)
{
if (NULL!=_SpamValueItems[i])
{
delete _SpamValueItems[i];
}
}
/*delete the array*/
delete [] _SpamValueItems;
}
}
/*push*/
void push(SpamValue* SpamValue)
{
_SpamValueItems[++_position];
}
/*pop*/
SpamValue* pop()
{
return _SpamValueItems[_position--];
}
/*isEmpty*/
bool isEmpty()
{
return (_position == -1);
}
/*getters*/
SpamValue** getSpamValueItems()
{
return this->_SpamValueItems;
}
int getTotalSize()
{
return _total_size;
}
SpamValueStackIter* createIterator()const;
private:
SpamValue** _SpamValueItems;
int _total_size;
int _position;
};
class SpamValueStackIter
{
public:
SpamValueStackIter(const SpamStack *s)
{
_stack = s;
}
/*set index position to first item*/
void first()
{
_index = 0;
}
/*set index position to the next item in the iterator*/
void next()
{
_index++;
}
/*is the iteration completed */
bool isDone()
{
return _index == _stack->_position + 1;
}
/* return the current item */
SpamValue* currentItem()
{
return _stack->_SpamValueItems[index];
}
private:
const SpamStack* _stack;
int _index;
};
/create a new iterator/
SpamValueStackIter* SpamStack::createIterator()const
{
return new SpamValueStackIter(this);
}
#endif /* SPAMSTACK_H */
In getting this error now:
SpamStack.h:117:45: error: invalid types ‘SpamValue** const[<unresolved overloaded function type>]’ for array subscript
return _stack->_SpamValueItems[index];

Non overwriting object

Hello I have four files: AllOnesGA.cpp, GeneticAlgorithm.h, Population.h, Individual.h
And I don't know why individual.getFitness() give me -1 and not 2 that is the last value that I give it with the method setFitness
I simplified my code
int main()
{
GeneticAlgorithm ga(100);
Population population = ga.initPopulation(50);
ga.evalPopulation(population);
ga.isTerminationConditionMet(population);
...
In geneticAlgorithm
void evalPopulation(Population population)
{
double populationFitness = 0;
for (Individual individual : population.getIndividual())
{
individual.setFitness(2);
}
}
bool isTerminationConditionMet(Population population)
{
for(Individual individual :population.getIndividual())
{
cout<<individual.getFitness()<<endl; //this gives -1 and not 2
}
}
and in Individual.h
class Individual{
public:
Individual(vector<int> chromosome2)
:chromosome(chromosome2),chromosomeLength(chromosome2.size())
{}
Individual(int chromosomeLength)
:chromosomeLength(chromosomeLength)
{
for(int gene=0;gene<chromosomeLength;gene++)
{
chromosome.push_back(gene);
}
}
int getChromosomeLength()
{
return chromosomeLength;
}
vector<int> getChromosome()
{
return chromosome;
}
int getGene(int offset)
{
return chromosome[offset];
}
void setFitness(double fitness)
{
this->fitness=fitness;
}
double getFitness()
{
return fitness;
}
private:
vector<int> chromosome;
double fitness=-1.0;
int chromosomeLength;
from Population.h
...
vector <Individual> getIndividual()
{
return this->population;
}
...
private:
vector <Individual> population;
But don't confuse the object population from AllOnesGA.cpp and the population object from Population.h that is a vector.
Any recomendation?

How to use classes inside another class function independently of where it is declared in C++?

I'm trying to create a Monopoly game in C++ and I've been messing with object-oriented-programming, the problem happens with the classes "Game" and "Player", I would like to know how to use "Game"'s functions inside "Player" and "Player"'s functions inside "Game", but I've been getting a compiler error saying that the class is not defined.
Switching class positions won't work (obviously) but I tried anyways.
Code (reduced and minimized to the Game and Player classes):
namespace Monopoly {
typedef enum { normal, train, company, incometax, luxurytax, start, chancecard, chestcard, jail } type;
class Game {
private:
bool running = false;
int turn = 1;
int currentPlayerID;
int startingMoney = 1000;
std::vector<Player> players;
public:
// Functions
void createPlayer() {
++currentPlayerID;
Player newPlayer(currentPlayerID, startingMoney);
players.push_back(newPlayer);
++currentPlayerID;
}
void createPlayers(int playerAmount) {
for (int i = 0; i <= playerAmount; ++i) {
createPlayer();
}
}
Player getPlayer(int index) {
Player p = players[index];
return p;
}
};
class Player {
private:
int playerID;
int money;
std::vector<int> propertiesOwned;
void addProperty(int id) {
this->propertiesOwned.push_back(id);
}
public:
// Constructor
Player(int pID, int sMoney) {
this->playerID = pID;
this->money = sMoney;
}
// Functions
Player payMoney(int payAmount, unsigned int destinationID, Game engine) {
this->money -= payAmount;
if (destinationID > 0) {
// Checks if you're paying to a player or bank
bool playerFound = false;
for (int i = 0; i <= engine.getPlayerAmount(); ++i) {
if (engine.getPlayer(i).getID() == destinationID) {
playerFound = true;
break;
}
}
if (playerFound) {
// Player was found
engine.getPlayer(destinationID).giveMoney(payAmount);
return;
}
else {
std::cout << "\nERROR: Invalid player ID at function payMoney\n";
return;
}
}
else {
// You're paying to the bank
}
return;
}
void buyProperty(int id, int price, Game engine) {
payMoney(price, 0, engine);
addProperty(id);
}
void giveMoney(int payMoney) {
this->money += payMoney;
}
// Returns
inline int getMoney() { return this->money; }
inline int getID() { return this->playerID; }
inline auto getProperties(int index) {
auto p = propertiesOwned[index];
return p;
}
inline int getPropertyAmount() {
int amount = std::size(propertiesOwned);
return amount;
}
};
}
I expected the classes to run the other classes function normally, but it seens like that in C++, classes are defined in certain order, and you can only access classes (in a class) declared before the class you're using, feedback and alternatives that fix this would help
You are correct that in C++ declaration order matters, and that is the cause of your errors, however there are a few other issues with the code.
Firstly, you should swap the order that Game and Player are defined. This will make it easier, as Player relies on Game fewer times than Game relies on Player.
Next, add a forward declaration for Game before the definition of Player:
class Game;
This tells the compiler that a class named Game exists and allows you to use it in scenarios where it doesn't need to know the contents (i.e. definition) of the class.
Next, make payMoney and buyProperty accept their engine parameter by reference instead of by value by changing the parameter specifier to Game &engine. This is important for two reasons. First, passing by value can only be done if you have already defined the type, which we have not (we've only declared it). Second, passing by value creates a copy of the object, which in this case means a completely new vector of completely new Player objects, and the changes will not synchronize back to the old object. See here for a better explanation of references.
Next, you need to extract the definition of payMoney to after the definition of Game. The reason is that while the parameter list of payMoney no longer relies on the definition of Game, the code in the function body does (because it calls functions on the engine object). See the end for what this looks like.
This fixes all the problems with declaration/definition order. You also should make payMoney return void as its return value is never provided and never used, pick a consistent type for IDs (either int or unsigned int, not a mix), and add the getPlayerAmount to Game.
Here's what the final code could look like:
namespace Monopoly {
typedef enum { normal, train, company, incometax, luxurytax, start, chancecard, chestcard, jail } type;
class Game;
class Player {
private:
int playerID;
int money;
std::vector<int> propertiesOwned;
void addProperty(int id) {
this->propertiesOwned.push_back(id);
}
public:
// Constructor
Player(int pID, int sMoney) {
this->playerID = pID;
this->money = sMoney;
}
// Functions
void payMoney(int payAmount, int destinationID, Game &engine);
void buyProperty(int id, int price, Game &engine) {
payMoney(price, 0, engine);
addProperty(id);
}
void giveMoney(int payMoney) {
this->money += payMoney;
}
// Returns
inline int getMoney() { return this->money; }
inline int getID() { return this->playerID; }
inline auto getProperties(int index) {
auto p = propertiesOwned[index];
return p;
}
inline int getPropertyAmount() {
int amount = std::size(propertiesOwned);
return amount;
}
};
class Game {
private:
bool running = false;
int turn = 1;
int currentPlayerID;
int startingMoney = 1000;
std::vector<Player> players;
public:
// Functions
void createPlayer() {
++currentPlayerID;
Player newPlayer(currentPlayerID, startingMoney);
players.push_back(newPlayer);
++currentPlayerID;
}
void createPlayers(int playerAmount) {
for (int i = 0; i <= playerAmount; ++i) {
createPlayer();
}
}
Player getPlayer(int index) {
Player p = players[index];
return p;
}
int getPlayerAmount() {
int amount = players.size();
return amount;
}
};
void Player::payMoney(int payAmount, int destinationID, Game &engine) {
this->money -= payAmount;
if (destinationID > 0) {
// Checks if you're paying to a player or bank
bool playerFound = false;
for (int i = 0; i <= engine.getPlayerAmount(); ++i) {
if (engine.getPlayer(i).getID() == destinationID) {
playerFound = true;
break;
}
}
if (playerFound) {
// Player was found
engine.getPlayer(destinationID).giveMoney(payAmount);
return;
}
else {
std::cout << "\nERROR: Invalid player ID at function payMoney\n";
return;
}
}
else {
// You're paying to the bank
}
return;
}
}
Side note: it's technically better C++ to use size_t instead of int for variables storing the size of vectors, as that is what the size functions return (and it's an unsigned integer type whereas int is signed), but that's not especially important.

Array of pointers to an object in C++

I am trying to write a super basic program which creates an array of objects under class Receipt. The class includes an int price, string good (name), and a simple function that adds an item to the list. I am stuck because every time I compile it seg faults before it even gets to the add function, meaning something is wrong with my default constructor.
I am still really new to C++ and pointers are probably my biggest struggle. I have looked online and at my lecture notes trying to figure out what I am doing wrong. I feel like it's something small but I cannot figure it out.
Here is my program:
#include <iostream>
#include <string>
using namespace std;
class Receipt {
private:
int price;
string good;
Receipt* goods[500]; //partially filled array
public:
Receipt();
void add(string name, int cost);
string getName();
int getPrice();
void setName(string name_in);
void setPrice(int price_in);
void displayList();
};
Receipt::Receipt()
{
for (int i=0; i < 500; i++)
{
goods[i]->setName("Empty");
goods[i]->setPrice(-1);
}
}
void Receipt::add(string name, int cost)
{
int place=0;
for (int i=0; i <500; i++)
{
if (goods[i]->getName()=="Empty" && goods[i]->getPrice()==-1)
{
place = i;
break;
}
}
goods[place]->setName(name);
goods[place]->setPrice(cost);
}
int Receipt::getPrice()
{
return price;
}
string Receipt::getName()
{
return good;
}
void Receipt::setName(string name_in)
{
good = name_in;
}
void Receipt::setPrice(int price_in)
{
price = price_in;
}
void Receipt::displayList()
{
//just displaying first item in list for debugging purposes
cout << goods[0]->getName() << endl << goods[0]->getPrice();
}
int main()
{
Receipt mine; //seg faults here
mine.add("banana", 50);
mine.displayList();
return 0;
}
your design is wrong, you have array of Receipt inside Receipt so when you initialize the object, it create 500 where each of them create another 500 endlessly. I think you want to create something like this instead
#include <iostream>
#include <string>
using namespace std;
class Receipt {
private:
int price;
string good;
public:
void setName(string name_in);
void setPrice(int price_in);
string getName();
int getPrice();
};
class Receipts {
private:
Receipt* goods[500]; //partially filled array
public:
Receipts();
void add(string name, int cost);
void displayList();
};
Receipts::Receipts()
{
for (int i = 0; i < 500; i++)
{
goods[i] = new Receipt();
goods[i]->setName("Empty");
goods[i]->setPrice(-1);
}
}
void Receipts::add(string name, int cost)
{
int place = 0;
for (int i = 0; i <500; i++)
{
if (goods[i]->getName() == "Empty" && goods[i]->getPrice() == -1)
{
place = i;
break;
}
}
goods[place]->setName(name);
goods[place]->setPrice(cost);
}
int Receipt::getPrice()
{
return price;
}
string Receipt::getName()
{
return good;
}
void Receipt::setName(string name_in)
{
good = name_in;
}
void Receipt::setPrice(int price_in)
{
price = price_in;
}
void Receipts::displayList()
{
//just displaying first item in list for debugging purposes
cout << goods[0]->getName() << endl << goods[0]->getPrice();
}
int main()
{
Receipts mine; //seg faults here
mine.add("banana", 50);
mine.displayList();
return 0;
}

Dynamic object array increase

I'm building a domino game and trying to make a function that adds a Stone to a pile.
This is the Stone class:
class Stone
{
public:
Stone(){ left = 0; right = 0; };
Stone(int x, int y){ left = x; right = y; };
void turnStone();
bool comStones(const Stone&);
void printOpen();
void printClosed();
friend class Pile;
friend class Game;
private:
int left, right;
};
And this is the Pile class:
class Pile
{
public:
Pile(){};
Stone indexfun(int);
void printOpen();
void printClosed();
void fillPile();
void randPile();
void addStone(Stone&);
void remStone(Stone&);
friend class Player;
friend class Game;
private:
Stone* list;
int size=0;
};
Now the function I built for adding a stone to the pile is:
void Pile::addStone(Stone& newStone) {
Stone* newList = new Stone[size + 1];
int i;
for (i = 0; i < size; i++)
{
newList[i] = list[i];
}
newList[i] = newStone;
delete[] list;
list = newList;
size++;
}
When I try and build the newlist array it throws me out of the program. can't find the reason. Help anyone?
the previous functions and more classes in the project:
class Game
{
public:
Game(char*);
void run();
private:
Player human, computer;
Pile box, table;
int start, finish;
void playerMove(int);
void checkPile(int);
bool checkMove(int,int);
bool whosFirst();
bool checkGame();
void printTable();
};
class Player
{
public:
Player(){};
void addStone(Stone&);
void remStone(Stone&);
void printPile();
Stone* searchStone();
friend class Game;
private:
char* name;
Pile pie;
};
void Game::run() {
cout << "starting the game" << endl;
box.fillPile();
box.size = 28;
box.randPile();
for (int i = 0; i < 7; i++)
{
human.addStone(box.list[i]);
box.remStone(box.list[i]);
computer.addStone(box.list[i]);
box.remStone(box.list[i]);
}
}
void Player::addStone(Stone& added) {
pie.addStone(added);
}
int main()
{
char name[80];
cout << "enter your name" << endl;
cin >> name;
Game game(name);
game.run();
}
Maybe change the "list" variable name to "list1" or something like that. "list" is a STL container, just like vector.