I have a parent class in C++ with a method and declared two instances of its children classes. When I call this method on one child instance it makes changes to both children. Why is that, how to correct this?
Code is a bit too complicated to copy here, but I call this first child's method in other function where I move the instance of the child by pointers (first I receive it from other function by pointers too), so maybe there is something wrong with that.
[EDIT]
//Parent class:
class TWPerson : public TWObject
{
public:
...
void MakeDamage(int DamagePoints); //Function that causes problem
...
};
void TWPerson::MakeDamage(int DamagePoints)
{
LifePoints -= DamagePoints;
}
//Child class:
class TWSoldier : public TWPerson
{
...
public:
void Create(int SoldierID);
...
};
void TWSoldier::Create(int SoldierID)
{
UnitID = SoldierID;
LifePoints = 120;
IsAlive = true;
}
//Class that stores and uses arrays of TWSoldier class:
class TWArmy
{
private:
TWSoldier *InfantryDivision;
public:
TWSoldier* GetUnitPtrByID(int UnitID);
TWSoldier* CreateInfantryDivision();
};
TWSoldier* TWArmy::GetUnitPtrByID(int UnitID)
{
for (int SoldierNumber=0; SoldierNumber < SoldiersInitialNumber; SoldierNumber++)
{
if (InfantryDivision[SoldierNumber].GetUnitID() == UnitID)
{
return &InfantryDivision[SoldierNumber];
}
}
}
TWSoldier* TWArmy::CreateInfantryDivision()
{
static TWSoldier NewInfantryDivision[SoldiersInitialNumber];
for (int SoldierNumber = 0; SoldierNumber < SoldiersInitialNumber; SoldierNumber++)
{
IncreaseUnitID();
NewInfantryDivision[SoldierNumber].Create(CurrentUnitID);
}
return NewInfantryDivision;
}
//Class that gets TWSoldier* from two instances of TWArmy and conducts the problematic method:
class TWGameMode
{
private:
TWArmy AIArmy; // First instance of TWArmy that stores TWSoldier
TWArmy PlayerArmy; // Second instance of TWArmy that stores TWSoldier
public:
...
auto ReceivePlayerAttackCoordinates();
void PerformPlayerAttack();
void PerformAttack(TWSoldier* AttackingUnit, TWSoldier* AttackedUnit);
...
};
auto TWGameMode::ReceivePlayerAttackCoordinates()
{
struct Coordinates { // Declare a local structure
TWSoldier *OwnUnit, *OponentUnit;
};
int PlayerUnitID, AIUnitID;
...
TWSoldier* PlayerUnit = PlayerArmy.GetUnitPtrByID(PlayerUnitID);
TWSoldier* AIUnit = AIArmy.GetUnitPtrByID(AIUnitID);
return Coordinates{PlayerUnit, AIUnit};
}
void TWGameMode::PerformAttack(TWSoldier* AttackingUnit, TWSoldier* AttackedUnit)
{
... // RandomNumber and others calculated here
if (RandomNumber < AttackingUnitAimCapability)
{
AttackedUnit->MakeDamage(AttackingUnitDamage * AttackedUnitDefence);
}
...
}
I exaplained some stuff in comments in the code but also quick summary:
TWPerson is the parent class of TWSoldier with a method MakeDamage. TWArmy has array of TWSoldier class instances. There are two different instances of TWArmy (PlayerArmy and AIArmy) in class TWGamemode. Class TWGamemode receives pointers to two different TWSoldiers from different TWArmies and calls MakeDamage method on one of them (AttackedUnit which is a TWSoldier* of AIArmy instance) but changes of this method are visible on the same soldiers in both PlayerArmy and AI
Army arrays of TWSoldiers.
Let me know if you would need some additional information or I missed something.
Related
I have to modify my program and create a new (Gamefigures) class from which my current classes(Rabbit and Hedg) inherit. The code is a small game where two animals race until they reach the goal, but in the second task I have to make sure that it is possible that multiple iterations of these animals can race. (5 vs 5 or X vs X for instance). I am allowed to move some variables or methods to the Gamefigures class. Both of the animals use different rules to walk. How do I make a new class which creates multiple objects dynamically of the same class from which my current classes inherit?
I have tried to use the new expression to create a new object but I don't know if it is the right thing to do.
I tried:
Hedg* nHedg = new Hedg[numFigures];
Here is the rest of my code:
class Hedg: public Gamefigures
{
private:
int salat = 1;
protected:
int position1 = 0;
public:
bool turn(int fields)
{
int counter = 10;
if (fields < 11)//Less than 10 fields
{
while ((counter > 0))
{
if (counter < fields)//max 10 fields
{
fields = counter;
}
position1 += fields;//walk
counter -= fields;
if (counter <= 0)
{
salat = 0;
}
}
getSalat();
return true;
}
else
return false;
}
Hedg()
{
}
int getPosition1()
{
return position1;
}
int getSalat()
{
return salat = 1;
}
int getStock1()
{
return salat;
}
~Hedg()
{
}
};
class Game :public Hedg, public Rabbit
{
private:
int goal = 0;
int numFields = 0;
protected:
Rabbit theRabbit;
Hedg theHedg;
public:
Game();
Game(int numFields);
int getGoal();
int dice();
void doyourturn();
bool getStand();
~Game();
};
Here is the error message:
Error code C4430 missing typespecifier
I think that the polymorphism is what you need for your use case and will solve your problems.
Let's suppose you have a base class for your animals:
class Animal
{
// ...
// Create all the (pure) virtual methods to be redefined by a derived class
virtual void walk() = 0; // For example
};
Then you defines your two specific animals, the rabbit and the hedgehog:
class Rabbit : public Animal
{
// ...
// Redefine here the (pure) virtual methods of Animal for a Rabbit
void walk() override;
};
class HedgeHog : public Animal
{
// ...
// Redefine here the (pure) virtual methods of Animal for a HedgeHog
void walk override;
};
And you can use polymorphism to handle your list of animals:
std::vector<Animal*> race_competitors;
race_competitors.push_back(new Rabbit);
race_competitors.push_back(new HedgeHog);
And this way, when you will call the walk() method over a competitor, it will automatically execute the proper walking rule of the corresponding animal.
Of course, at the end of the race, don't forget to delete the content of the vector because the animals was created with new ("manually" allocated memory, on the heap).
Just for information, the Game class doesn't have to inherit from Rabbit and HedgeHog, it just has to know them as class members, or even better, store a std::vector<Animal*> as a list of competitors.
I hope it will help you to improve your design and solve your problems.
I have a map of type < lookup_ID, vector< parentclass*>> each location in the map holds a vector of type child class. The idea behind this system is the ability to add a child into its associated map using an add(parentclass*) function and it would be able to find its associated vector of child type. I tried using templates and casting to get the vector to recognized the type of child input into the add function with no luck. I don't want to have to declare an add function for each child of parent, and no matter how I did it I had to declare a function for each type. I could take them out of the map but then again I'm left with the issue of calling each child for any function I want to implement. Is their no way to match types of polymorphic structures into dynamically allocated lists?`
class Piece
{
public:
pieceType ID;
//...
}
class Infantry :
public Piece
{
public:
//...
};
class Artillery :
public Piece
{
public:
//...
};
//...
//In some other classes somewhere
std::map<pieceType, std::vector<Piece*>*> units;
units.emplace(Infantry_, new std::vector<Infantry*>);
units.emplace(Artillery_, new std::vector<Artillery*>);
//...
template<typename T>
std::vector<T*> operator+(std::vector<T*> a, Piece * b) {
a.push_back(static_cast<T*>(b));
return a;
}
add(Piece * piece){
units.at(piece->ID) = units.at(piece->ID) + piece;
}
Also I am aware that this code has some errors, it was more for an example of what i'm trying to say.
You have to use virtual funciton to get the ID for each child class
class Piece
{
public:
virtual PieceType ID() const = 0;
}
class Artillery
{
public:
virtual PieceType ID() const override { /* return your ID for Artillery */ }
}
class Infantery
{
public:
virtual PieceType ID() const override { /* return your ID for Infantery */ }
}
There's no relation between std::vector<Piece*> and either of std::vector<Infantry*> or std::vector<Artillery*>, so your map can only contain std::vector<Piece*>s.
This is for good reason. Imagine you have a std::vector<Infantry*>, and put a pointer to it into your std::map<pieceType, std::vector<Piece*>*>. You could then insert an Artillery * into that through the map.
Rather than exposing the std::vector<Piece*> directly, you could expose a (read only) view of it that casts to the particular subtype.
Using the ranges library
auto asInfantry = ranges::view::transform([](Piece * p){ return static_cast<Infantry *>(p); });
auto asArtillery = ranges::view::transform([](Piece * p){ return static_cast<Artillery *>(p); });
class PieceMap
{
std::map<pieceType, std::vector<Piece*>> units;
public:
auto Infantry() { return units.at(Infantry_) | asInfantry; }
auto Artillery() { return units.at(Artillery_) | asArtillery; }
};
This may be impossible so alternative solutions to the problem will suffice as well
I have a list of activities that I want to keep track of
class Activity {
public:
virtual void DoSomething() = 0 ;
};
std::vector<Activity*> activities;
Let's say I have the following child classes
class GraphicsActivity : public Activity {
public:
virtual void DoSomething() { }
void HandleGraphics() { /* do some management */; }
};
class UpdateActivity : public Activity {
public:
virtual void DoSomething() { ; }
};
class PhysicsActivity : public Activity {
public:
virtual void DoSomething() { ; }
};
Now let's say we want to grab one of these activities from our list. A function would look like
template<typename T> T* GetActivity() {
for(int i = 0; i < activities.size(); i++) {
T* cast = dynamic_cast<T*>(activities[i]);
if(cast != nullptr) {
return cast;
}
}
return nullptr;
}
We could use it like so:
activities.push_back(new GraphicsActivity());
activities.push_back(new PhysicsActivity ());
activities.push_back(new UpdateActivity ());
GraphicsActivity* g = GetActivity<GraphicsActivity>();
Let's say we have another activity that needs to use polymorphism to use some of the base class's methods.
class 3DGraphicsActivity : public GraphicsActivity {
public:
void Handle3DGraphics() {
/* Utilize base class function */
this->HandleGraphics();
/* do some extra work */
}
};
Now we want to acquire the same activity as before and our list now looks like the following in the exact order:
activities.push_back(new GraphicsActivity3D());
activities.push_back(new GraphicsActivity());
activities.push_back(new PhysicsActivity ());
activities.push_back(new UpdateActivity ());
But we want the original type of GraphicsActivity, so we go to acquire it:
GraphicsActivity* g = GetActivity<GraphicsActivity>();
We'll actually get a pointer to the first entry in the list because it shares a base class of type GraphicsActivity.
Herein lies the problem: how can I write such a list whose items must share the same base class Activity while also be able to acquire the exact type from the list without falling into the dynamic_cast trap we just explained?
The typeid operator can be used to check if a polymorphic object has a certain exact most-derived type.
#include <typeinfo>
// ...
template<typename T> T* GetActivity() {
for(int i = 0; i < activities.size(); i++) {
auto* act = activities[i];
if (act != nullptr && typeid(*act) == typeid(T)) {
return dynamic_cast<T*>(act);
}
}
return nullptr;
}
Use this pattern with caution, because it limits the ability to make a class which acts exactly like another class except for specific changes. But it might be appropriate in your interface.
I would like to create a simple framework for throwing and catching events in a game. Events could be things like a Collision which (according to the type) can take several arguments (note that every Event type may take another amount of arguments, not just two as in the example).
I would then like to implement functions/classes/... to deal with a Collision, based on polymorphism. This example should illustrate the problem:
#include <iostream>
#include <vector>
class Entity {};
class Player: public Entity {};
class Bomb: public Entity {
public:
bool exploded;
};
class MineSweeper: public Entity {};
// For now, I only included Collisions, but I eventually want to extend it to
// more types of Events too (base class Event, Collision is derived class)
void onCollision(Player* p, Bomb* b) {
if (! b->exploded) {
std::cout << "BOOM";
b->exploded = true;
}
}
void onCollision(Entity* e, Entity* f) {
std::cout << "Unhandled collision\n";
}
// Possibility for Collision between Minesweeper and Bomb later
class Game {
public:
std::vector<Entity*> board; // some kind of linear board
Game() {
board = {new Player, new Bomb, new MineSweeper};
}
void main_loop() {
onCollision(board[0], board[1]); // player and bomb!
onCollision(board[1], board[2]);
}
};
int main() {
Game g;
g.main_loop();
}
Note that I understand perfectly well why the above code doesn't work as intended, I included this example solely to illustrate my problem better.
The above example uses functions for the events, but I'm perfectly fine with classes or any other solution that is maintainable.
I hope it is clear that I would like C++ to decide which event handler to use based on the types of the arguments (presumably at runtime).
My question: How can I do this in C++? An example would be appreciated.
(not my question: fix my code please)
user2864740 provided enough clues for me to find a solution myself. Multiple dispatch was indeed the missing piece.
The following code works as intended, making use of dynamic_cast to dispatch correctly.
#include <iostream>
#include <vector>
class Entity {
virtual void please_make_this_polymorphic() {}
// although this function does nothing, it is needed to tell C++ that it
// needs to make Entity polymorphic (and thus needs to know about the type
// of derived classes at runtime).
};
class Player: public Entity {};
class Bomb: public Entity {
public:
bool exploded;
};
class MineSweeper: public Entity {};
// For now, I only included Collisions, but I eventually want to extend it to
// more types of Events too (base class Event, Collision is derived class)
void onCollision(Player* p, Bomb* b) {
if (!b->exploded) {
std::cout << "BOOM\n";
b->exploded = true;
}
}
void onCollision(Entity* e, Entity* f) {
std::cout << "Unhandled collision\n";
}
void dispatchCollision(Entity* e, Entity* f) {
Player* p = dynamic_cast<Player*>(e);
Bomb* b = dynamic_cast<Bomb*>(f);
if (p != nullptr && b != nullptr) {
onCollision(p, b); // player and bomb
} else {
onCollision(e, f); // default
}
}
class Game {
public:
std::vector<Entity*> board; // some kind of linear board
Game() {
board = {new Player, new Bomb, new MineSweeper};
}
void main_loop() {
dispatchCollision(board[0], board[1]); // player and bomb
dispatchCollision(board[1], board[2]);
}
};
int main() {
Game g;
g.main_loop();
}
Although it works, I'd like to point out some problems with this code:
Manual editing of dispatchCollision needed when adding new Collisions.
Currently, the dispatcher using a simple kind of rule-based system. (Does it fit rule 1? What about rule 2? ...) When adding loads of different functions it needs to dispatch, that may have an impact on the performance.
A collision between A and B should be the same as a collision between B and A, but that isn't properly handled yet.
Solving these problems is not necessarily in the scope of this question IMHO.
Also, the example given should work just as well for more than 2 arguments. (Multiple dispatch, not just double dispatch.)
You should decide first what event subscription model you need.
It could be signal/slot mechanism and you can find plenty of libraries:
https://code.google.com/p/cpp-events/ , http://sigslot.sourceforge.net/ and the like.
Or it could be bubbling/sinking events like in HTML DOM when event gets propagated on parent/child chain ( from event source element to its containers).
Or even other schema.
It is quite easy to create whatever you need with std::function holders in modern C++.
Maybe a good structure for your case could be something like this:
class Entity{
public:
virtual int getType() = 0;
};
enum EntityTypes {
ACTOR,
BOMB,
MINESWEEPER,
};
class Actor : public Entity{
public:
virtual int getType() {return int(ACTOR);}
void applyDamage() {
std::cout << "OUCH";
}
};
class Bomb : public Entity{
public:
Bomb() : exploded(false) {}
virtual int getType() {return int(BOMB);}
void explode() {
this->exploded = true;
}
bool isExploded() {
return this->exploded;
}
protected:
bool exploded;
};
class MineSweeper : public Entity{
public:
virtual int getType() {return int(MINESWEEPER);}
};
class CollisionSolver {
public:
virtual solve(Entity* entity0, Entity* entity1) = 0;
};
class ActorBombCollisionSolver : public CollisionSolver {
public:
virtual solve(Entity* entity0, Entity* entity1) {
Actor* actor;
Bomb* bomb;
if (entity0->getType() == ACTOR && entity1->getType() == BOMB) {
actor = static_cast<Actor*>(entity0);
bomb = static_cast<Bomb*>(entity1);
}else if (entity1->getType() == ACTOR && entity0->getType() == BOMB) {
actor = static_cast<Actor*>(entity1);
bomb = static_cast<Bomb*>(entity0);
}else {
//throw error;
}
if (!bomb->isExploded()) {
bomb->explode();
actor->applyDamage();
}
}
};
class CollisionDispatcher {
public:
CollisionDispatcher() {
CollisionSolver* actorBombCollisionSolver = new ActorBombCollisionSolver;
this->solvers[ACTOR][BOMB] = actorBombCollisionSolver;
this->solvers[BOMB][ACTOR] = actorBombCollisionSolver;
// this part wouldn't be necessary if you used smart pointers instead of raw... :)
this->solvers[BOMB][MINESWEEPER] = 0;
this->solvers[MINESWEEPER][BOMB] = 0;
this->solvers[ACTOR][MINESWEEPER] = 0;
this->solvers[MINESWEEPER][ACTOR] = 0;
}
void dispatchCollision(Entity* entity0, Entity* entity1) {
CollisionSolver* solver = this->solvers[entity0->getType()][entity1->getType()];
if (!solver) {
return;
}
solver->solve(entity0, entity1);
}
protected:
unordered_map<int, unordered_map<int, CollisionSolver*> > solvers;
};
class Game {
public:
std::vector<Entity*> board; // some kind of linear board
Game() : dispatcher(new CollisionDispatcher)
{
board = {new Player, new Bomb, new MineSweeper};
}
void main_loop() {
dispatcher->dispatchCollision(board[0], board[1]);
dispatcher->dispatchCollision(board[0], board[2]);
dispatcher->dispatchCollision(board[1], board[2]);
}
protected:
CollisionDispatcher* dispatcher;
};
int main() {
Game g;
g.main_loop();
}
This way you can easily add new collision solvers, just define the class, and register t in the CollisionDispatcher constructor.
If you use smart pointers you won't need to set zeroes in the map entries not registered, but if you use raw pointers you have to set them to zero OR use unordered_map::find method instead of just grabbing the solver using operator []
Hope it helps!
For some reason the following doesn't crash like my program does, but I'm pretty sure it's similar in design. For one, the output's not correct. It outputs something similar to:
0x537ff4 5471612
While the main program outputs (nil) for the pointer address.
The key to the problem might be display_ in Drv.
Here's the code:
#include <iostream>
#include "debug.h"
class LCDText {
public:
int rows_;
LCDText() { rows_ = 10; };
};
class Generic {
LCDText *lcdText_;
public:
Generic(LCDText *lcdText) { lcdText_ = lcdText; };
void Setup() {
Error("%p %d", lcdText_, lcdText_->rows_);
}
};
class Display : public LCDText {
Generic *visitor_;
public:
Display(Generic *visitor) { visitor_ = visitor; };
};
class Drv : public Generic {
Display *display_;
public:
Drv() : Generic((LCDText *)display_) {
display_ = new Display((Generic *)this);
};
~Drv() { delete display_; };
};
int main()
{
Drv drv;
drv.Setup();
return 0;
}
This code:
Drv() : Generic((LCDText *)display_) {
display_ = new Display((Generic *)this);
};
first runs the parent class's ctor, with a yet-uninitialized value of display_, then independently sets display_, but, too late to change the parent class. So the pointer held by the parent class will never be set correctly. I guess you need to add a protected setter method (or make the parent-class-held pointer member itself protected).
Your Drv constructor passes the garbage, uninitialized value of Drv::display_ to Generic before initializing it in the constructor body. You can do a couple of things here, my preferred would be:
class Drv : public Generic {
Display* display() { return (Display*)lcdText_; }
public:
Drv() : Generic(new Display(this)) {}
}
Because it doesn't result in a duplicate field, but you can also have an abstract getLcdText() in Generic, which could be better if you are already using virtual methods.
In the constructor for Drv, when you first call the constructor for Generic display_ is still uninitialized. You don't new the pointer until later.