I can't access to a value of my objectin C++ - c++

I'm starting C++ : I was trying to make my "player1" attack my "player2", to make him remove health to my "player2" and finally to display the health of "player2". But it's not working and I can't find the mistake.
Here's my code I hope you will be able to help me:
PLAYER.CPP
class Player {
public:
std::string pseudo;
int healthValue = 100;
int attackValue = 5;
Player(std::string aPseudo) {
pseudo = aPseudo;
healthValue = healthValue;
attackValue = attackValue;
}
std::string getPseudo() {
return pseudo;
}
int getHealthValue() {
return healthValue;
}
int getAttackValue() {
return attackValue;
}
void attack(Player aTargetPlayer) {
aTargetPlayer.healthValue -= this->attackValue;
}
};
MAIN.CPP
#include "Player.cpp"
int main() {
Player player1("player1");
Player player2("player2");
std::cout << player2.getHealthValue() << std::endl;
player1.attack(player2);
std::cout << player2.getHealthValue() << std::endl;
return 0;
}

Here:
void attack(Player aTargetPlayer) {
aTargetPlayer.healthValue -= this->attackValue;
}
The parameter aTargetPlayer is passed by value, this means you decreased the health of a copy, not the original one. You must pass by reference, like this:
void attack(Player &aTargetPlayer) {
aTargetPlayer.healthValue -= this->attackValue;
}

#JuanR's answer is valid. Note also that, they way you designed your class, the attack() method could very well be moved out of the class:
Why?
The attacker does not have a stronger affinity to the code of the method than the attacked player. If anything, and since right now, the attack only affects the stats of the attacked player, you might have written a getAttackedBy(const Player& other_player)...
The code for attack() does not need access to protected or private members of the Player class.
So consider writing:
void attack(Player& attacker, Player& attacked);
(This has both players passed by non-const reference in case you want to reduce the number of actions of the attacker, or allow it to take damage from the attacked player's defense etc.)

Related

How should I call a player spell in a text RPG?

I'm trying to create a mechanic that fills a vector with Spell objects, each with its own name, then select the spell with cin input and cast it on a target. What's the best way to do it? This is what I've done, but what if the spell has multiple spell effects?
//Spell.h
class Spell
{
public:
enum e_spellType //enum with all spells
{
FIREBALL = 1,
FROSTBOLT
};
enum e_spellEffect //enum with different effects
{
DAMAGE = 1, //for damaging effect
SLOW
};
Spell(e_spellEffect effect);
void returnSpellEffect(Unit* target);
//getters here
string getSpellName() const { return m_SpellName; }
int getSpellValue() const { return m_SpellValue; }
int getCooldown() const { return m_Cooldown; }
int getManaCost() const { return m_ManaCost; }
protected:
string m_SpellName;
int m_SpellValue;
int m_Cooldown;
int m_ManaCost;
int m_SpellID;
e_spellEffect m_spellEffect;
e_spellType m_spellType;
};
Spell::Spell(e_spellType type)
{
m_spellType = type;
switch (m_spellType)
{
case 1: //Fireball
m_SpellValue = 35;
m_ManaCost = 40;
m_Cooldown = 2;
m_spellEffect = DAMAGE;
case 2: //Frostbolt
m_SpellValue = 30;
m_ManaCost = 40;
m_Cooldown = 2;
m_spellEffect = SLOW;
}
}
void Spell::returnSpellEffect(Unit * target)
{
switch (m_SpellEffect)
{
case DAMAGE:
target->takeDamage(m_SpellValue);
break;
case SLOW:
target->setDamage(0.5); //modifies Unit object's attack dmg to half
break;
default:
break;
}
}
//Game.h
class Game
{
public:
void enemyCombat();
protected:
Player *player;
vector<Enemy*> enemyList;
vector<Spell*> spellList;
};
void Game::enemyCombat()
{
//after you have chosen a target from enemyList (enemyList[target])
spellList.push_back(new Spell(FIREBALL));
spellList.push_back(new Spell(FROSTBOLT));
cout << "Choose a spell to cast:" << endl
<< "1. Fireball" << endl
<< "2. Frostbolt" << endl;
int spellChoice = 0;
cin >> spellChoice;
spellList[spellChoice-1]->returnSpellEffect(enemyList[target]);
}
How do I make this whole thing more abstract to allow a spell to use more than one spell effect?
Consider using polymorphism. If you have a virtual function doSpellEffects, you can implement "usual" logic in the base class, and more specialized logic in other classes for specific spells or spell categories.
class Spell
{
public:
// Copying disabled to avoid slicing.
Spell(const Spell&) = delete;
Spell& operator=(const Spell&) = delete;
virtual ~Spell() = default;
enum e_spellType { /*...*/ };
// TBD whether e_spellEffect belongs in Spell or SimpleSpell.
// Factory function:
static std::unique_ptr<Spell> create(e_spellType spellType);
const std::string& getSpellName() const noexcept { return m_SpellName; }
int getCooldown() const noexcept { return m_Cooldown; }
int getManaCost() const noexcept { return m_ManaCost; }
virtual void doSpellEffects(Unit* target) = 0;
protected:
Spell(e_spellType spellType) :
m_spellType(spellType), m_SpellName(),
m_Cooldown(0), m_ManaCost(0) {}
e_spellType m_spellType;
std::string m_SpellName;
int m_Cooldown;
int m_ManaCost;
};
class SimpleSpell : public Spell
{
public:
SimpleSpell(e_spellType spellType);
void doSpellEffects(Unit* target) override;
int getSpellValue() const { return m_SpellValue; }
protected:
e_spellEffect m_spellEffect;
int m_SpellValue;
};
class WarlocksRay : public Spell
{
public:
WarlocksRay() : Spell(WARLOCKS_RAY, "Warlock's Ray") {}
void doSpellEffects(Unit* target) override;
};
void WarlocksRay::doSpellEffects(Unit* target)
{
// Two effects!
target->takeDamage(5);
target->stun();
}
// The factory function that creates all spells:
std::unique_ptr<Spell> Spell::create(e_spellType spellType) {
switch(spellType) {
case FIREBALL:
case FROSTBOLT:
return std::make_unique<SimpleSpell>(spellType);
case WARLOCKS_RAY:
return std::make_unique<WarlocksRay>();
}
// Invalid spellType: Log an error? Throw an exception? Just return nullptr?
throw std::invalid_argument("Bad spellType in Spell::create");
}
You could use subclassing in other ways, which might or might not be worth it:
Instead of a switch in SimpleSpell::doSpellEffects, create classes for each common effect type, like DamageSpell and SlowSpell.
If the "cooldown" and/or "mana cost" mechanics might not apply to all spells, move these members and related logic out of Spell into a class NormalCastingSpell or something, which would come between Spell and other classes in the heirarchy.
Even go so far as to create a class for each individual spell. In some cases, this could just inherit SimpleSpell or DamageSpell or etc., and the only member it would need to define would be a constructor that correctly sets all data members.
aschepler's answer is probably the most flexible one, in worst case, though, you might end up in implementing every spell on its own. A variation of could be:
a base class Effect
deriving classes DamageEffect, SlowEffect, ...
one single Spell class
The spell class then might look like this:
class Spell
{
std::string name;
std::vector<std::unique_ptr<Effect>> effects;
public:
void cast(Unit& target)
{
for(auto& effect : effects)
effect->applyTo(target);
}
}
When the spell gets casted, you likely would want to show some appropriate visual effect. You could again have polymorphic objects for these and provide one to the spell class as a member (several similar spells could re-use the same animation that way), alternatively you could have an animation for every effect and use the one of the first element in the effects vector.
Side note: You might create every spell just once in some global vector (not getting changed after creation any more, so no re-allocations – best have it const), units being able to cast spells would then just have pointers to those in their own vector.

Need help understanding this piece of code from a book

This code is from "Sams Teach Yourself C++".It might be something simple but I'm having a hard time trying to figure this out. I get the same output if I don't use the getSpeed() method. So do I need this? If not, why does this book use it?
#include <iostream>
class Tricycle
{
public :
int getSpeed();
void setSpeed(int speed);
void pedal();
void brake();
private :
int speed;
};
int Tricycle::getSpeed() //<-- Why do I need this method
{
return speed;
}
void Tricycle::setSpeed(int newSpeed)
{
if (newSpeed >= 0)
{
speed = newSpeed;
}
}
void Tricycle::pedal()
{
setSpeed(speed + 1);
std::cout << "\nPedaling; tricycle speed " << speed << " mph\n";
}
void Tricycle::brake()
{
setSpeed(speed - 1);
std::cout << "\nBraking ; tricycle speed " << speed << " mph\n";
}
int main()
{
Tricycle wichita;
wichita.setSpeed(0);
wichita.pedal();
wichita.pedal();
wichita.brake();
wichita.brake();
wichita.brake();
return 0;
}
This Method return the Value from Speed.
So if you call setSpeed with value greater as 0 then the Speed Value are set to the new Value. Declared as private int variable.
As example
int main()
{
Tricycle wichita;
wichita.setSpeed(10);
int mySpeed= wichita.getSpeed();
}
The Value of mySpeed is now 10.
Since Speed is a private variable, you cannot retrive/set its value outside the class scope. So here we have used setSpeed and getSpeed public functions through which we can retrive/set Speed to tricycle object outside the class scope.
For example,
Tricycle myTricycle = new Tricycle();
// to set speed of tricycle use,
myTricycle.setSpeed(100);
// to retrive speed of tricycle object use,
myTricycle.getSpeed(); // returns 100;
Because you cannot access the private members directly from the main() function or somewhere else. But you can use a public function to access the private elements of an object of any class. In spite of this, you cannot access those private elements. In your code, speed is a private member and to get the value of this, a public function namely getSpeed is being used.

C++ declare derived class object inside of if-else and use it outside

I have a (parent) class named Alma with the (virtual) function Getwidth() and two derived class of Alma, named Birs (with the special function Getheight()) and Citrom (with the special function Getdepth()). I want to declare an object - named Attila - which type is Birs or Citrom depending on a bool. Later, I want to use the common function Getwidth() and also the special functions (depending the bool mentioned).
My (not working) code:
/*...*/
/*Classes*/
class Alma{
public: virtual int Getwidth() = 0;
/*ect...*/
}
class Birs: public Alma{
int Getwidth(){return 1;}
public: int Getheight(){return 2;}
/*ect...*/
}
class Citrom: public Alma{
int Getwidth(){return 3;}
public: int Getdepth(){return 4;}
/*ect...*/
}
/*...*/
/*Using them*/
void Useobjects(){
/*Create object depending on bool*/
if(b00lvar){
Birs Andor();
std::cout<<Andor.Getwidth()<<" "<<Andor.Getheight()<<std::endl;
}else{
Citrom Andor();
std::cout<<Andor.Getwidth()<<" "<<Andor.Getdepth()<<std::endl;
}
/*Using the common part of object*/
std::cout<<Andor.Getwidth()<<std::endl;
/*Using the special part of object*/
if(b00lvar){
std::cout<<Andor.Getheight()<<std::endl;
}else{
std::cout<<Andor.Getdepth()<<std::endl;
}
/*ect...*/
}
This is a classic case of polymorphic object handling. Just make sure you are familiar with that concept as well with pointers and references.
What you need is something looking like:
Alma* Andor;
if(b00lvar){
Andor = new Birs();
std::cout<<Andor->Getwidth()<<" "<<Andor->Getheight()<<std::endl;
}else{
Andor = new Citrom();
std::cout<<Andor->Getwidth()<<" "<<Andor->Getdepth()<<std::endl;
}
Next use dynamic_cast to get back to the derived types and finally of course do not forget to delete the object. But first read about those concepts.
You cannot define a single object whose type is this or that, depending on something else. C++ doesn't work this way. C++ is a statically-typed language. This means that the type of every object is determined at compile time. Other languages, like Perl, or Javascript, are dynamically-typed, where the type of an object is determined at runtime, and a single object can be one thing, at one point, and something else at a different point.
But C++ does not work this way.
To do something like what you're trying to do, you have to refactor the code, and work with the virtual superclass. Something like this:
void UseObject(Alma &andor)
{
/*Using the common part of object*/
std::cout<<andor.Getwidth()<<std::endl;
/*Using the special part of object*/
/* This part is your homework assignment */
}
void Useobjects(){
/*Create object depending on bool*/
if(b00lvar){
Birs andor;
std::cout<<Andor.Getwidth()<<" "<<Andor.Getheight()<<std::endl;
UseObject(andor);
}else{
Citrom andor;
std::cout<<Andor.Getwidth()<<" "<<Andor.Getdepth()<<std::endl;
UseObject(andor);
}
}
Another approach would be to use two pointers, in this case passing two pointers to UseObject(). One of the two pointers will always be a nullptr, and the other one a pointer to the instantiated object, with UseObject() coded to deal with whatever object is passed in.
That's also possible, but will result in ugly code, and if I was an instructor teaching C++, I would mark down anyone who handed in code that did that.
If the type of the object (Alma or Citrom) is decided at the startup, then it's a classic polymorphism, as other answers described:
https://stackoverflow.com/a/36218884/185881
What're you missing from your design is, to name the common ancestor with common behaviors (e.g. Gyumolcs).
If the object should once act as Alma and other times as Citrom, you should implement a single class, which have a flag or enum (ACT_AS_CITROM, ACT_AS_ALMA), or, if the behavior is limited to one method, then it should have a parameter, which tells which action to perform (alma-like or citrom-like).
You can do this with pointer semantic and type introspection with dynamic_cast. I extended your example to show how I would approach it.
Here is the Demo
#include <iostream>
#include <memory>
using namespace std;
class Alma{
public:
virtual int Getwidth() = 0;
};
class Birs: public Alma{
public:
int Getwidth() { return 1; }
int Getheight() { return 2; }
};
class Citrom: public Alma{
public:
int Getwidth() { return 3; }
int Getdepth() { return 4; }
};
shared_ptr<Alma> make_attila(bool birs)
{
if (birs)
return make_shared<Birs>();
else
return make_shared<Citrom>();
}
void test_attila(shared_ptr<Alma> attila)
{
cout << "width: " << attila->Getwidth() << "\n";
if (auto as_birs = dynamic_pointer_cast<Birs>(attila))
cout << "height: " << as_birs->Getheight() << "\n";
else if (auto as_citrom = dynamic_pointer_cast<Citrom>(attila))
cout << "depth: " << as_citrom->Getdepth() << "\n";
}
int main() {
shared_ptr<Alma> attila = make_attila(true);
test_attila(attila);
attila = make_attila(false);
test_attila(attila);
return 0;
}
Next step would be to make make_attila a template function taking the Derived class as a template parameter instead of a bool.
template <class Derived>
shared_ptr<Alma> make_attila()
{
return make_shared<Derived>();
}
Two things:
If you want to use it outside the if, you will have to declare it outside the if.
You need references or pointers for this kind of polymorphism.
unique_ptr<Alma> Andor;
if (b00lvar) {
Andor = make_unique<Birs>();
} else {
Andor = make_unique<Citrom>();
}
std::cout << Andor->Getwidth() << std::endl;
Some other answer suggested using shared_ptr but that's overkill here. 99% of the time unique_ptr is sufficient.
Polymorphism isn't always the way to go if an object is known to be either a B or a C. In this case, a boost::variant is often more succinct.
Having said this, if you want to go down the polymorphic route it's important to remember something that will guide the design.
Polymorphic means runtime polymorphic. I.e. the program cannot know the real type of the object. It also cannot know the full set of possible types the object could be, since another developer could manufacture a type that your module's code knows nothing about. Furthermore, when using the Alma interface, the code should not need to know anything more. Invoking magic such as "I know it'll be a Citrom because the bool is true" is laying the foundations for a code maintenance nightmare a few weeks or months down the line. When done in commercial, production code, it results in expensive and embarrassing bug-hunts. Don't do that.
This argues that all relevant information about any object of type Alma must be available in the Alma interface.
In our case, the relevant information is whether it has the concept of height and/or depth.
In this case, we should probably include these properties in the base interface plus provide functions so that the program can query whether the property is valid before using it.
Here is something like your example written this way:
#include <iostream>
#include <memory>
#include <typeinfo>
#include <string>
#include <exception>
#include <stdexcept>
// separating out these optional properties will help me to reduce clutter in Alma
struct HeightProperty
{
bool hasHeight() const { return impl_hasHeight(); }
int getHeight() const { return impl_getHeight(); }
private:
// provide default implementations
virtual bool impl_hasHeight() const { return false; }
virtual int impl_getHeight() const { throw std::logic_error("getHeight not implemented for this object"); }
};
struct DepthProperty
{
bool hasDepth() const { return impl_hasDepth(); }
int getDepth() const { return impl_getDepth(); }
private:
virtual bool impl_hasDepth() const { return false; }
virtual int impl_getDepth() const { throw std::logic_error("getDepth not implemented for this object"); }
};
class Alma : public HeightProperty, public DepthProperty
{
public:
Alma() = default;
virtual ~Alma() = default;
// note: nonvirtual interface defers to private virtual implementation
// this is industry best practice
int getWidth() const { return impl_getWidth(); }
const std::string& type() const {
return impl_getType();
}
private:
virtual int impl_getWidth() const = 0;
virtual const std::string& impl_getType() const = 0;
};
class Birs: public Alma
{
private:
// implement the mandatory interface
int impl_getWidth() const override { return 1; }
const std::string& impl_getType() const override {
static const std::string type("Birs");
return type;
}
// implement the HeightProperty optional interface
bool impl_hasHeight() const override { return true; }
int impl_getHeight() const override { return 2; }
};
class Citrom: public Alma
{
private:
// implement the mandatory interface
int impl_getWidth() const override { return 3; }
const std::string& impl_getType() const override {
static const std::string type("Citrom");
return type;
}
// implement the DepthProperty optional interface
bool impl_hasDepth() const override { return true; }
int impl_getDepth() const override { return 4; }
};
/*...*/
/*Using them*/
// generate either a Birs or a Citrom, but return the Alma interface
std::unique_ptr<Alma> make_alma(bool borc)
{
if (borc) {
return std::make_unique<Birs>();
}
else {
return std::make_unique<Citrom>();
}
}
void Useobjects()
{
for (bool b : { true, false })
{
std::unique_ptr<Alma> pa = make_alma(b);
std::cout << "this object's typeid name is " << pa->type() << std::endl;
std::cout << "it's width is : " << pa->getWidth() << std::endl;
if(pa->hasHeight()) {
std::cout << "it's height is: " << pa->getHeight() << std::endl;
}
if(pa->hasDepth()) {
std::cout << "it's depth is: " << pa->getDepth() << std::endl;
}
}
}
int main()
{
Useobjects();
return 0;
}
expected output:
this object's typeid name is Birs
it's width is : 1
it's height is: 2
this object's typeid name is Citrom
it's width is : 3
it's depth is: 4

Using C-like API in OOP

I am writing some classes in C++ to act as a personal small library and I encountered a problem.
Some of my objects make us of third-party libraries written in magnificent C style.
That means those libraries have functions like apiInit() and apiCleanup(), where the former must be called before any of the actual api functions and the latter must be called when you are not going to use them anymore.
What I want is to provide the classes that need a library with an access point to its functions ensuring apiInit() is called when the first needing class is created, or at least before any api function is used, and apiCleanup() is called when the last instance that uses the api is destroyed.
Keep in mind there are more than one class that makes use of a single library.
I could come with two solutions:
First, the obvious one, make the provider a singleton:
#include <iostream>
using namespace std;
class ContextProvider {
ContextProvider() {
cout << "Initializing API" << endl;
}
ContextProvider(ContextProvider const& rhs) = delete;
ContextProvider& operator=(ContextProvider const& rhs) = delete;
public:
~ContextProvider() {
cout << "Cleaning API" << endl;
}
static ContextProvider& getInstance() {
static ContextProvider instance;
return instance;
}
void useContext() {
cout << "Using API" << endl;
}
};
class ContextUser1 {
public:
ContextUser1() {
}
void doSomething() {
ContextProvider::getInstance().useContext();
}
};
class ContextUser2 {
public:
ContextUser2() {
}
void doSomethingElse() {
ContextProvider::getInstance().useContext();
}
};
The other one would be to keep a counter of context users, like so:
#include <iostream>
using namespace std;
class ContextProvider {
static unsigned int userCounter;
public:
ContextProvider() {
if (userCounter == 0)
cout << "Initializing API" << endl;
++userCounter;
}
~ContextProvider() {
--userCounter;
if (userCounter == 0)
cout << "Cleaning API" << endl;
}
void useContext() {
cout << "Using API" << endl;
}
};
unsigned int ContextProvider::userCounter = 0;
class ContextUser1 {
ContextProvider cp;
public:
ContextUser1() {
cp = ContextProvider();
}
void doSomething() {
cp.useContext();
}
};
class ContextUser2 {
ContextProvider cp;
public:
ContextUser2() {
cp = ContextProvider();
}
void doSomethingElse() {
cp.useContext();
}
};
int main() {
ContextUser1 cu11, cu12, cu13;
ContextUser2 cu21, cu22;
cu11.doSomething();
cu12.doSomething();
cu21.doSomethingElse();
cu22.doSomethingElse();
cu13.doSomething();
}
Both, when executed with the following main()
int main() {
ContextUser1 cu11, cu12, cu13;
ContextUser2 cu21, cu22;
cu11.doSomething();
cu12.doSomething();
cu21.doSomethingElse();
cu22.doSomethingElse();
cu13.doSomething();
}
yeld the expected result, that is:
Initializing API
Using API
Using API
Using API
Using API
Using API
Cleaning API
Now the obvious question is, which one is better, or which one should I use?
For example, some things that come to mind are...
Singleton method:
Advantages:
No need to store any counter.
No need to store any instance.
Disadvantages:
Syntaxis gets weird (ContextProvider::getInstance().use()).
It is a singleton, with all it's flaws.
Counter method:
Advantages:
The usage is straightfowrard.
The syntaxis is nice and clear (cp.use()).
Disadvantages:
Has to keep a counter of the number of users.
User classes have to store an instance of the ContextProvider class.
I mainly ask this question because I don't know which of these advantages/disadvantages weight more, if there are things I didn't account for, or maybe there is an obvious third method I couldn't come up with that is inherently better than those two, or, who knows.
Thank you for your time!
I'd use your second approach, with the following modifications:
class ContextUser1 {
std::shared_ptr<ContextProvider> cp;
public:
ContextUser1(const std::shared_ptr<ContextProvider>& cp)
: cp(cp) {
}
void doSomething() {
cp->useContext();
}
};
Making the dependency explicit makes your code better in terms of being testable. Also, using shared_ptr takes care of counting, so you don't even need to do this yourself.

Subclass unable to access parent class' variable

I'm making a program whereby I have a Square class which is a subclass of Shape class
But my program crashes when the subclass tries to access variable from parent class.
Here is my code:
class Shape2D
{
public:
string shape;
void setShape(string newShape);
string getShape();
string specialType;
void setSpecialType(string newSpecialType);
vector <int> shapeXCoordi;
void setshapeXCoordi(int newshapeXCoordi);
vector <int> shapeYCoordi;
void setshapeYCoordi(int newshapeYCoordi);
void toString();
virtual int computeArea()
{
return 0;
}
void displayArea();
};
For testing purpose, I only make this computeArea() return the x-coordinate.
class Square : public Shape2D
{
public:
int computeArea()
{
return shapeXCoordi[0];
}
};
int main()
{
if (aShape2D[0].getShape() == "Square")
{
Shape2D *pShape2D;
pShape2D = &aSquare;
cout << "Area: " << pShape2D -> computeArea() << endl;
}
}
I did a couple of test, if I were to change return shapeXCoordi[0]; to return 123;, it works fine.
I also tried return shape; but it will not display anything, although this time, it doesn't crash.
So I'm guessing there is something wrong when SquareClass is trying to access shapeXCoordi[0] from ShapeClass
Can anyone enlighten me on this situation?
You need to initialize the shapeXCoordi in your constructor by calling setshapeXCoordi first. Since you are accessing shapeXCoordi, an uninitialized vector, there are no elements in it. Hence when you access it using [0] it returns an error.
You can add a sanity check to computeArea() to ensure there is an element in shapeXCoordi before you access it:
int computeArea()
{
assert(shapeXCoordi.size() != 0);
return shapeXCoordi[0];
}
Also, I recommend using .at(0) instead of [0], this way you get actual error handling instead of a crash.