How to make functions interact with class variables between eachother c++ - c++

I have been having trouble with a simple program that utilizes seperate file classes (i'm pretty new to them). Could you please help me figure out why it won't display the changed value?
main
stats startout;
startout.beginning();
startout.start();
header
class stats
{
public:
void start();
void beginning();
//setter
void setHealth(int x){
health = x;
}
//getter
int getHealth(){
return health;
}
private:
int health;
};
implementation .cpp file
void stats::beginning(){
stats set;
set.setHealth(10);
}
void stats::start(){
stats stat;
cout << "Health: " << stat.getHealth() << endl;
}
It keeps displaying health as 0, which I assume is some sort of default since it is not being set as ten as described in my beginning() function. If anybody knows what the problem is or has suggestions on the best way to handle variables in classes and trading them between functions then please share your wisdom!

The functions start() and beginning() are still members of the class just like your getter and setter functions. That they're in a different .cpp doesn't mean you need new local instances of stats set and stat respectively, they still members of the instance declared as startout and will operate on it. You've made them operate on brand new instances.
So they should be defined as
void stats::beginning() {
setHealth(10);
}
void stats::start() {
cout << "Health: " << getHealth() << endl;
}

Related

Trying to change c++ code that was started in linux mint to windows with eclipse, getting stack error

I've began making a program in linux with c++ and I'm trying to make it work on windows. It compiles fine, but when run I get this error: "1 [main] Trails of Cold Steel Simulator 8748 cygwin_exception::open_stackdumpfile: Dumping stack trace to Trails of Cold Steel Simulator.exe.stackdump". In the stack trace this exception occurs: "Exception: STATUS_ACCESS_VIOLATION". Here's some code;
#include "Tachi.h"
#include "AutumnLeafCutter.h"
#include <iostream>
#include "Weapon.h"
#include "Armour.h"
#include "Shoes.h"
int main() {
int stats[12] = {15,110,10,4,2,1,2,4,4,3,7,1};
Tachi* Tachi1 = new Tachi(stats, "Tachi");
Tachi1->addEquipment(new PracticeSword());
Tachi1->addEquipment(new LeatherJacket());
Tachi1->addEquipment(new WorkBoots());
Tachi1->addMasterQuartz(new Forcelvl1());
std::string input;
std::cout << "\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n";
while(input != "q") {
std::cout << "Your current stats are:" << std::endl;
std::cout << "\n";
std::cout << "HP EP STR DEF ATS ADF SPD DEX AGL MOV RNG" << std::endl;
for(int i = 0; i < 12; i += 1) {
std::cout << Tachi1->getBaseStats()[i] << " ";
}
std::cout << "\n\n";
std::cout << "Select a Craft by typing its name:" << std::endl;
std::cout << std::endl;
for(int i = 0; i < Tachi1->getCrafts().size(); i++) {
std::cout << Tachi1->getCrafts()[i]->getName() << std::endl;
}
std::cout << std::endl;
getline(std::cin, input);
if(Tachi1->findCraft(input) != NULL) {
Tachi1->useCraft(input);
} else {
std::cout << "You do not have this craft." << std::endl;
}
std::cout << "\n\n\n";
}
}
Im extremely sorry for any formatting, I've never posted here. The error comes from lines 14,15,16 and 18. When I replaced all the "new xxx()" with NULL and comment out the body of the function with them, the program works. It does this for both addEquipment() and addMasterQuartz(). This is the functions;
void Character::addEquipment(Equipment* e) {
equipment.push_back(e);
std::cin.get();
for(int i = 0; i < 12; i++) {
baseStats[i] += equipment[equipment.size()]->getStatsModifier()[i];
}
}
and
void Character::addMasterQuartz(MasterQuartz* mq) {
masterQuartz = mq;
for(int i = 0; i < 12; i++) {
baseStats[i] += masterQuartz->getStatsModifier()[i];
}
}
Im guessing its a problem with the baseStats[i] += xxx stuff as its the only thing that occurs in both, but I have no idea how to fix that. It could also occur when the stuff is made using new xxx().
I can provide whatever else is needed. Thanks!!!!
EDIT:
I kept testing and the problem seems to lie in the creating of the objects. It worked on linux. Here is one of the object codes, they are all similiar and all crash the program;
#include "Armour.h"
Armour::Armour(int* sm, std::string n):Equipment(sm, n) {}
LeatherJacket::LeatherJacket():Armour(stats, armourName) {}
with header file;
#ifndef ARMOUR_H
#define ARMOUR_H
#include "Equipment.h"
class Armour:public Equipment {
public:
Armour(int* sm, std::string n);
};
class LeatherJacket:public Armour {
int stats[12] = {0,0,0,5,0,0,0,0,0,0,0,0};
std::string armourName = "Leather Jacket";
public:
LeatherJacket();
};
#endif
As soon as I remembered I did this I tried compiling (I think) with -std=c++11, it didnt help.
This is your error
baseStats[i] += equipment[equipment.size()]->getStatsModifier()[i];
By definition this is an out of bounds access on your vector, if a vector has a certain size, then the valid indexes are 0 to size - 1, not 0 to size.
It's fairly obvious that you wanted to access the last item in the vector. You can do that like this
baseStats[i] += equipment[equipment.size() - 1]->getStatsModifier()[i];
but even clearer is to use the back method.
baseStats[i] += equipment.back()->getStatsModifier()[i];
Another way would be to use the e variable you've just pushed onto the vector.
baseStats[i] += e->getStatsModifier()[i];
Adding some detail to the problem spotted by Useless, this code is incorrect.
class LeatherJacket : public Armour {
int stats[12] = {0,0,0,5,0,0,0,0,0,0,0,0};
std::string armourName = "Leather Jacket";
public:
LeatherJacket();
};
LeatherJacket::LeatherJacket() : Armour(stats, armourName) {}
The problem is the order in which things happen. First the Armour constructor is called, then the stats and armourName variables are initialised. So the call to the Armour constructor is using uninitiialised variables and will likely crash.
Several solutions possible, the best is probably to use virtual functions.
Making a couple of assumptions about Equipment (which isn't specified the question) it seems you should do something like this.
// header file
class Equipment
{
public:
virtual ~Equipment() {}
virtual std::string getName() const = 0;
virtual const int* getStatsModifier() const = 0;
};
class Armour : public Equipment
{
};
class LeatherJacket : public Armour
{
static const int stats[12];
public:
virtual std::string getName() const { return "Leather Jacket"; }
virtual const int* getStatsModifier() const { return stats; }
};
// source file
const int LeatherJacket::stats[12] = {0,0,0,5,0,0,0,0,0,0,0,0};
This answer adds pure virtual functions to the base class Equipment (which has become an interface), and implements those functions in LeatherJacket. Because the functions are virtual the appropriate function will always be called and there no need to pass the information down to Equipment. Also since it seems to be per-class constant data, stats has been made static const. Until you get to C++17 static const arrays must be defined in a source file, not the header file, as shown above.
Firstly, I'm going to replace the int[12] arrays with a proper type. Partly so the magic number 12 isn't littered all over the code and hard to change later, and partly because it will behave better (ie, not decay to a pointer in some contexts). This needs C++11.
#include <array>
using Stats = std::array<int, 12>;
To me it looks like Armour should have stats and a name, initialized from the arguments passed to its constructor (which you currently ignore).
Like so:
class Armour: public Equipment {
public:
Stats m_stats;
std::string m_name;
Armour(Stats const& s, std::string const &n) : m_stats(s), m_name(n) {}
};
You were already passing those two arguments to the constructor - you just weren't doing anything with them. Now you are.
This means that when we later have leather, scale, chain and plate subclasses, I can have a pointer of type Armour* and not need to worry about which subclass I'm looking at: the stats are available right there in the base class.
I made the members public, which is generally bad style, to save space. It might not matter for your use. I named the members with the m_ prefix so they can't accidentally get confused with similarly-named non-members. It's broadly good style but not essential.
LeatherArmour doesn't need an additional copy per instance, it just needs one of each for the whole class - so they should be const static members.
class LeatherJacket: public Armour {
static const Stats stats {0,0,0,5,0,0,0,0,0,0,0,0};
static const std::string name{"Leather Jacket"};
public:
LeatherJacket() : Armour(stats, name) {}
};
I made the LeatherJacket-specific stat values static const by writing static const in front of them.
The static means that every LeatherJacket has the same base stats, so you don't need a copy per instance, just one copy for the whole class. It's const because the base stats for leather jackets never change over time. You still have the base class member Armour::m_stats which can change as your individual leather jacket gets damaged, repaired, buffed or whatever.
Again, the LeatherJacket constructor was already passing (the equivalent of) these members to the base class constructor, but now they already exist (see the link above about static storage duration). The original instance variables didn't exist when you used them, because the derived (LeatherJacket) object and its data members aren't really constructed until after the base class subobject.

can't get virtual function of parent class to work [duplicate]

This question already has answers here:
C++ overridden virtual function not getting called [duplicate]
(3 answers)
Closed 4 years ago.
I have a parent class with a virtual function in it, I then make a child class and define the function. I then make a vector of vectors and insert one of the child classes into it. I then try to call the virtual function and nothing outputs to the screen. I do not know why this is happening, does anyone know?
Parent Class
class insect{
public:
string type;
int food_cost;
int armor;
int damage;
insect();
void set_food_cost(int x);
void set_armor(int x);
void set_damage(int x);
virtual void attack(){} // this is the problematic function
};
Child Class
class bee: public insect{
public:
bee();
int armor;
int damage;
void set_armor(int x);
void attack();
};
void bee::attack(){
cout << "im a bee, stab stab!\n";
}
Creating Vector of Vectors
vector< vector<insect> > insects_on_board(10);
Adding a bee to the vector of vectors
void add_bee(vector< vector<insect> > &insects_on_board, int &bees){
bees++;
insects_on_board[9].push_back(bee());
}
Function Call
cout << "testing " << insects_on_board.at(9).at(0).type << endl;
insects_on_board.at(9).at(0).attack();
Output
testing B
My Question Again
so in the output im expecting to see "testing B" and then "im a bee, stab stab!"
but only the "testing B" is outputted to the screen, any ideas why the other part is not?
That's because you are storing actual insects and not any bees. Polymorphism (in its basic C++ way) works when you are doing 3 things:
Have a type hierarchy with properly defined and overridden virtual methods (like you are doing here,)
Create child instances (or a variety of parent and child instances,)
Access them through pointers (or references.)
You are missing points 2 and 3.
So, one way to fix it would be to store pointers to insect, and initialize them as either bees or plain insects, like so:
vector<vector<insect *>> insects_on_board (10, vector<insect *>(2)); // note the type
insects_on_board[9][0] = new bee;
insects_on_board[9][1] = new insect;
// Note the use of "->" instead of "."
cout << "testing " << insects_on_board[9][0]->type << endl;
insects_on_board[9][0]->attack();
// Contrast the output with the above's
cout << "testing " << insects_on_board[9][1]->type << endl;
insects_on_board[9][1]->attack();
Update:
Note that (at the basic level) any container that stores insects by value cannot contain anything else; not even classes derived from insect. All the polymorphism and stuff you read and hear about is only applicable for pointers to parent and child types (or references to them.)
So, your add_bee function should look like this:
void add_bee (vector<vector<insect *>> & insects_on_board, int & bees) {
bees++;
insects_on_board[9].push_back(new bee());
}
I've made only two changes in there: the vectors now contain pointers to insect and I'm newing the bees.

Do functions need to be declared anywhere else besides in the class and before the program?

I've been trying to convince myself that that objects of the same type have access to each others private data members. I wrote some code that I thought would help me better understand what is going on, but now I am getting an error from XCODE7 (just 1), that says that I am using the undeclared identifier "combination."
If someone could help me understand where I have gone awry with my code, I would love to learn.
My code should simply print false, if running correctly.
#include <iostream>
using std::cout;
using std::endl;
class Shared {
public:
bool combination(Shared& a, Shared& b);
private:
int useless{ 0 };
int limitless{ 1 };
};
bool Shared::combination(Shared& a,Shared& b){
return (a.useless > b.limitless);
}
int main() {
Shared sharedObj1;
Shared sharedObj2;
cout << combination(sharedObj1, sharedObj2) << endl;
return 0;
}
combination is a member function of the class Shared. Therefore, it can only be called on an instance of Shared. When you are calling combination, you are not specifying which object you are calling it one:
cout << combination(sharedObj1, sharedObj2) << endl;
^^^
Instance?
The compiler complains because it thinks you want to call a function called combination, but there is none.
So, you'll have to specify an instance:
cout << sharedObj1.combination(sharedObj1, sharedObj2) << endl;
In this case however, it doesn't matter on which instance it is being called on, so you should make combination static, so you can do
cout << Shared::combination(sharedObj1, sharedObj2) << endl;

Need to create a function for a casino game

I have a Project for my programming class, and its requiring me to set up the main functionality for the casino using functions.
First, I needed to seed the random number generator which I think I did right.
void seedRand(int seed)
{
srand(time(0));
}
Second, was to continue to set up functions. So I set the next one to print out numbers to the second decimal place.
void printMoney(double money)
{
std::cout << std::setprecision(2) << std::fixed;
}
The next one, and the one I'm not understanding, is to have the user pay, and have the casino receive the money.
Sorry if i didn't put enough information, if something is missing please ask. I'm still new to understanding everything. Any help would be appreciated. Thanks.
void payMoney(double & wallet, double amount)
{
}
which I think I did right.
No you didn't, it should rather look like
void seedRand(int seed) {
srand(seed == 0?time(0):seed);
}
If there's a parameter passed, it's probably meant to be actually used. I've chosen zero as a convention, when seed() should be called with a randomly time based value.
So I set the next one to print out numbers to the second decimal place.
Your second function sets up the output stream state well, but misses to output the value, it should look like
void printMoney(double money) {
std::cout << std::setprecision(2) << std::fixed << money << std:: endl;
// ^^^^^
}
And at least your last function is probably supposed to be implemented as
void payMoney(double & wallet, double amount) {
wallet -= amount;
}
All in all it's hard to answer what you're supposed to do with this task.
But since you tagged this question c++, I'd rather recommend to go putting these functions in context of classes like class Casino and class Player.
class Casino;
class Player {
double wallet;
public:
void payMoney(Casino& Casino, double amount);
};
class Casino {
public:
void addToBank(double money) {
bank += money;
}
private:
double bank;
};
void Player::payMoney(Casino& casino, double amount) {
wallet -= amount;
casino.addToBank(amount);
}

debuging--Class / object stuff, noob problems

Please tear this code apart, make it complex and scarcely readable, I'd rather learn the hard way once than learn the same thing many times the wrong way.
The base class is as follows:
class baseMob{
private:
int _healthMax;
int _healthCurrent;
int _manaMax;
int _manaCurrent;
int _experiencePoints;
public:
//Set max Hp
void setHealthMax(int);
//Get max Hp
int getHealthMax();
//Set Current Hp
void setCurrentHealth(int);
//Get Current Health
int getCurrentHealth();
//Set Max Mana
void setMaxMana(int);
//Get Max Mana
int getMaxMana();
//Set Current Mana
void setCurrentMana(int);
//Get Current Mana
int getCurrentMana();
//getMob Exp on kill
int getExperiencePoints();
//Set mob Exp points
void setExperiencePoints(int);
//leaving out the member functions for space conservation
};
The individual mob that I'm trying to create is a green slime, which I'm trying to create via the default constructor I've made...
class greenSlime: private baseMob{
public:
greenSlime(){
setHealthMax(100);
setMaxMana(100);
setCurrentHealth(100);
setCurrentMana(100);
setExperiencePoints(150);
}
};
My main function looks like this right now:
greenSlime slime();
for(; slime.getCurrentHealth() >= 0; slime.setCurrentHealth(-1)){
cout << "The current health of the slime is: " << slime.getCurrentHealth() << endl;
if (slime.getCurrentHealth() <= 0 ){
cout << "Player is awarded with: " << slime.getExperiencePoints() << " Experience. ";
}
}
If anyone wants to tear this up and make me look like a jackass, I'd really appreciate the help.
The error that I'm presently getting is:
Project1.cpp:107: error: request for member getCurrentHealth' inslime', which is of non-class type `greenSlime ()()'
Along with other errors of the same type.
Tl;Dr: Class implementation isn't working, posted all my source when I probably could've posted about 1/10th of this and still made sense, and would love to have someone tell me why it's not working and how bad I am.
The problem is that the compiler thinks that the slime declaration line is another type of predeclaration since greenSlime doesn't have a ctor with parameters.
You can fix it by not putting the parenthesis after slime.
// greenSlime slime();
greenSlime slime;
Here is the absolute best advice I can give regarding weird errors that you don't understand. Make a smaller example of the problem makes it easier to uncover what is actually wrong.
Here is what I wrote to test.
struct Foo {
Foo() {}
void bar() {}
};
int main(int argc, char ** argv) {
Foo foo;
foo.bar();
return 0;
}
Others have pointed out problems in terms of why your code doesn't work. I'll make a recommendation about program design.
When explaining inheritance, tutorials and programming classes frequently use toy examples that are very similar to your code. These examples show what inheritance is, but really aren't very good at showing what inheritance is useful for.
I wouldn't use inheritance in this case. I think a better design is to have a class that represents the mob type and holds all the data that is static for all that mob of that type, such as the mob name, starting/max HP, attack types, etc. And then have another class where each instance represents a specific mob and holds data that changes for that mob, such as current hp.
class Mob_type {
string name;
int max_hp;
vector<shared_ptr<Attack_type>> attacks;
public:
Mob_type(string name,int max_hp,vector<shared_ptr<Attack_type>> attacks)
: name(name),max_hp(max_hp),attacks(attacks) {}
int get_max_hp() const { return max_hp; }
};
class Mob {
Mob_type const &type;
int hp;
public:
Mob(Mob_type const &type) : type(type), hp(type.get_max_hp()) {}
Mob_type const &get_type() const { return type; }
int get_hp() const { return hp; }
};
void print_health(Mob const &m) {
cout << m.get_hp() << '/' << m.get_type().get_max_hp() << '\n';
}
int main() {
vector<shared_ptr<Attack_type>> attacks; // ...
Mob_type green_slime("Green Slime",50,attacks);
Mob green_slime_A(green_slime), green_slime_B(green_slime);
fight(green_slime_A,green_slime_B);
cout << "A: ";
print_health(green_slime_A);
cout << "B: ";
print_health(green_slime_B);
}
This way you can have a data file that contains the mob types and all you have to do to add a type is to update the data file.
class greenSlime: private baseMob{
should be:
class greenSlime: public baseMob{
Since the class that you're inheriting from is private, you can't see any of the inherited methods.
Also, what Tom Kerr said, you don't want the parentheses after you declare your object. Basically, if you don't want any parameters, don't use the parentheses when making an object.
Also, very next thing I imagine you'll encounter: you almost never want private inheritance, at least not unless you know you really want it. I'm guessing you meant for the class declaration of greenSlime to be
class greenSlime: public baseMob
First of all if you make private inheritance you won't be able to access any of base class' functions. Public inheritance allows you access base class' public and protected functions and members.
Second if you want to make a pointer of greenSlime class, you must do:
//greenSlime() with parentheses
greenSlime *slime = new greenSlime();
But if you want to make an object of greenSlime with non parameter constructor (default constructor) you must do:
//without parentheses
greenSlime slime;