Reputation: 471
So i thought i had the idea of passing by reference down, but it seems i'm still struggling with it a bit.
Here's my issue, i've been debugging my game for awhile, and i left the enemies section of my code untouched for ages. It's a long story but i thought my projectiles were doing damage to the enemies, I changed the enemies health to being very high, so i thought they were doing the damage but because of the high health, not killing it. Only now have i realised that they are not doing any damage and that the code is wrong :/
So here is were i begin:
void Towers::Update(std::vector<Enemies>& enemies, SDLib& lib, Map cMap)
Here i'm passing the enemies by reference, into my update function. Which then i go onto see if there is any enemy within range of the tower;
for (int numOfEnemies = 0; numOfEnemies < lib.numberOfEnemies; numOfEnemies++)
{
float y = pow(enemies[numOfEnemies].position.y - position.y, 2);
float x = pow(enemies[numOfEnemies].position.x - position.x, 2);
if (sqrt(y + x) < range && enemies[numOfEnemies].alive)
{
cEnemy = enemies[numOfEnemies];
acquiredTarget = true;
break;
}
}
cEnemy (currentEnemy), then holds the enemy that's within range. After this, i then create the projectile to fire, and here is were i think i'm messing up;
bullet = Projectile((float)position.x, (float)position.y - 8, 8, 8, 0, 0, damage, 1, speed, cEnemy);
And the function arguments for that are:
Projectile::Projectile(float x, float y, int w, int h, int sX, int sY, int dmg, int type, float mxSpeed, Enemies bulletTarget)
{
//....other values set.
target = bulletTarget;
}
(Target is the following)
Enemies target;
The idea here is that target should hold the reference to the initial enemy that i set it to via the function... But it isn't working as i want. I'm not too sure, but i'm guessing some form of pointer might be required here. It seems to be out of everything the concept i'm finding hardest to grasp *and have done for some time now.
Any help appreciated!
Upvotes: 1
Views: 133
Reputation: 20191
Your question is missing some information about the type of cEnemy and how you use the target, so I'm guessing that cEnemy
is defined as Enemies
and you need a reference for target
to update the correct object. In this case your problems are the following:
cEnemy = enemies[numOfEnemies];
makes a copy instead of a referencebulletTarget
is of type Enemies
bullet = Projectile((float)position.x, (float)position.y - 8, 8, 8, 0, 0, damage, 1, speed, cEnemy);
makes a copytarget
is type Enemies
target = bulletTarget;
makes a copyReferences generally only take addresses when they are constructed, later assignments make copies. So to solve the first item you need to make cEnemy
a pointer:
Enemies* cEnemy;
//some code
cEnemy = &enemies[numOfEnemies];
//some more code
The second item can be solved by defining the constructor as
Projectile::Projectile(float x, float y, int w, int h, int sX, int sY, int dmg, int type, float mxSpeed, Enemies& bulletTarget)
The third item can be solve by defining target as a reference and initialising it in an initialisation list (the last part is important), making it
Enemies& target;
Projectile::Projectile(float x, float y, int w, int h, int sX, int sY, int dmg, int type, float mxSpeed, Enemies& bulletTarget):target(bulletTarget)
{}
Since assignement to references is a copy operation (only the construction of a reference takes the address, if you can't initialise target
in the initialisation list, you need to make it a pointer:
Enemies* target;
Projectile::Projectile(float x, float y, int w, int h, int sX, int sY, int dmg, int type, float mxSpeed, Enemies& bulletTarget)
{
target = &bulletTarget;
}
`
Upvotes: 0
Reputation: 254431
You're passing the Enemies
argument to the Projectile
constructor by value, and then also storing it by value.
If you want target
to be a reference to cEnemy
, then both will need to be references. Also note that reference members have to be initialised in the constructor's initialiser list, as they can't be reassigned in the body as your code does.
class Projectile
{
public:
Projectile(/*lots of args*/, Enemies & target) :
target(target)
{}
private:
Enemies & target;
};
Upvotes: 0
Reputation: 55726
We are missing some information here, but one line that could cause that is:
cEnemy = enemies[numOfEnemies];
I don't know what is the type of cEnemy
but it seems you are copying your enemy object from the list instead of just refering to it.
Did you know you can create a local reference like that:
Enemies& cEnemy = enemies[numOfEnemis];
That is, cEnemy
will refer to the enemy in the list, and not to a copy.
If you do that, just beware, because cEnemy
is just a reference, and if you modify your list, this reference might be silently lost.
Are you sure your Enemies
class should be copiable ? If it should not, fixing it not to be copiable would make the compiler your best friend to find such "mistakes".
Upvotes: 0
Reputation: 72271
You are making a copy of the Enemies
object:
cEnemy = enemies[numOfEnemies];
Projectile
constructor, since it takes an Enemies
by value.target = bulletTarget;
To fix all of these, you need to consider what code "owns" an Enemies
object and makes sure it lives long enough for all code that tries to use it. If there is such a place, all other places should use a reference or pointer. If not, maybe you can give the responsibility to shared_ptr<Enemies>
.
Upvotes: 1