Другая проблема: передача аргумента по ссылке - PullRequest
1 голос
/ 18 ноября 2011

Так что я подумал, что у меня была идея перейти по ссылке вниз, но, похоже, я все еще немного борюсь с этим.

Вот моя проблема, я некоторое время отлаживал свою игру, и я целую вечность оставлял раздел с врагами в моем коде нетронутым. Это длинная история, но я думал, что мои снаряды наносят урон врагам, я изменил здоровье врагов до очень высокого, поэтому я подумал, что они наносят урон, но из-за высокого здоровья, а не убивают его. Только теперь я понял, что они не наносят ущерба и что код неверен: /

Так вот, где я начинаю:

void Towers::Update(std::vector<Enemies>& enemies, SDLib& lib, Map cMap)   

Здесь я передаю врагов по ссылке, в мою функцию обновления. Который тогда я иду, чтобы видеть, есть ли враг в пределах досягаемости башни;

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), затем удерживает противника, находящегося в пределах досягаемости. После этого я создаю снаряд для стрельбы, и вот, думаю, я все испорчу;

bullet = Projectile((float)position.x, (float)position.y - 8, 8, 8, 0, 0, damage, 1, speed, cEnemy);

И аргументы функции для этого:

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;
}

(цель следующая)

Enemies target;

Идея в том, что цель должна содержать ссылку на первоначального врага, которого я установил с помощью функции ... Но она не работает так, как я хочу. Я не слишком уверен, но я предполагаю, что здесь может потребоваться указатель. Кажется, из всей концепции, которую мне труднее всего понять *, и которая уже давно используется.

Любая помощь приветствуется!

Ответы [ 4 ]

1 голос
/ 18 ноября 2011

Вы делаете копию объекта Enemies:

  • Вкл. cEnemy = enemies[numOfEnemies];
  • При передаче значения конструктору Projectile, поскольку оно принимает значение Enemies по значению.
  • Вкл. target = bulletTarget;

Чтобы исправить все это, вам нужно рассмотреть, какой код «владеет» объектом Enemies и убедиться, что он живет достаточно долго для всего кода, который пытается его использовать. Если такое место есть, все остальные места должны использовать ссылку или указатель. Если нет, то, возможно, вы можете передать ответственность shared_ptr<Enemies>.

0 голосов
/ 18 ноября 2011

В вашем вопросе отсутствует некоторая информация о типе cEnemy и о том, как вы используете цель, поэтому я предполагаю, что cEnemy определен как Enemies, и вам нужна ссылка для target, чтобы обновить правильный объект , В этом случае ваши проблемы следующие:

  1. cEnemy = enemies[numOfEnemies]; делает копию вместо ссылки
  2. , поскольку bulletTarget имеет тип Enemies bullet = Projectile((float)position.x, (float)position.y - 8, 8, 8, 0, 0, damage, 1, speed, cEnemy); делает копию
  3. , поскольку target имеет тип Enemies target = bulletTarget; делает копию

Ссылки обычно берут адреса только тогда, когда они созданы, более поздние назначения копируют. Итак, чтобы решить первый пункт, вам нужно сделать cEnemy указатель:

Enemies* cEnemy;
//some code
cEnemy = &enemies[numOfEnemies];
//some more code

Второй пункт можно решить, определив конструктор как

Projectile::Projectile(float x, float y, int w, int h, int sX, int sY, int dmg, int type, float mxSpeed, Enemies& bulletTarget)

Третий элемент можно решить, определив цель в качестве ссылки и инициализировав ее в списке инициализации (последняя часть важна), сделав ее

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)
{}

Поскольку присваивание ссылкам является операцией копирования (адрес берется только при создании ссылки, если вы не можете инициализировать target в списке инициализации, вам нужно сделать его указателем:

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;
}

`

0 голосов
/ 18 ноября 2011

Вы передаете аргумент Enemies конструктору Projectile по значению, а затем сохраняете его по значению.

Если вы хотите, чтобы target было ссылкой на cEnemy, тогда оба должны быть ссылками. Также обратите внимание, что ссылочные элементы должны быть инициализированы в списке инициализатора конструктора, поскольку они не могут быть переназначены в теле, как это делает ваш код.

class Projectile 
{
public:
    Projectile(/*lots of args*/, Enemies & target) :
        target(target)
    {}

private:
    Enemies & target;
};
0 голосов
/ 18 ноября 2011

Мы упускаем некоторую информацию здесь, но одна строка, которая может вызвать это:

cEnemy = enemies[numOfEnemies];

Я не знаю, к какому типу относится cEnemy, но кажется, что вы копируете вражеский объект из списка, а не просто ссылаетесь на него.

Знаете ли вы, что вы можете создать локальную ссылку следующим образом:

Enemies& cEnemy = enemies[numOfEnemis];

То есть cEnemy будет ссылаться на врага в списке, а не на копию.

Если вы сделаете это, просто остерегайтесь, потому что cEnemy - это просто ссылка, и если вы измените свой список, эта ссылка может быть молча потеряна.

Вы уверены, что ваш класс Enemies должен быть копируемым? Если этого не произойдет, исправление, чтобы оно не копировалось, сделало бы компилятор вашим лучшим другом для поиска таких «ошибок».

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...