Невозможно удалить элемент из вектора, пытаясь сослаться на удаленную функцию - PullRequest
0 голосов
/ 20 марта 2020

Я делаю свою «версию» Space Invaders в C ++ с использованием библиотеки SFML, но у меня возникает проблема при попытке удалить захватчика. У меня есть эта ошибка в моем коде:

Enemy &Enemy::operator =(const Enemy &)': attempting to reference a deleted function

Я пытался проверить другие решения, которые были рекомендованы на этом форуме, но я либо не понял их, либо это был другой случай.

EnemyControler. cpp

EnemyControler::EnemyControler()
{
    Enemy::Type types[] = {
        Enemy::Type::Squid, Enemy::Type::Crab, Enemy::Type::Crab,
        Enemy::Type::Octopus, Enemy::Type::Octopus
    };


    for (int y = 0; y < 5; y++) { // Add enemies to the vector
        for (int x = 0; x < 11; x++){
            float enemyX = x * 40 + (gapBetweenEnemies * x * 3) + Enemy::enemyWidth; // Make horizontal gap between them
            float enemyY = y * 40 + (gapBetweenEnemies * y) + Enemy::enemyHeight; // Make vertical gap between them
            enemies.emplace_back(sf::Vector2f{ enemyX, enemyY }, types[y]); // Add them to the vector
        }
    }
}
void EnemyControler::destroyEnemy()
{
    for (auto iterator = begin(enemies); iterator != end(enemies);) {
        auto& enemy = *iterator;
        if (enemy.isAlive()) {
            iterator++;
        }
        else {
            iterator = enemies.erase(iterator);
        }
    }
}

Проблема в функции destroyEnemy. В частности, iterator = enemies.erase(iterator);

EnemyControler.h

class EnemyControler
{
public:
    EnemyControler();

    void destroyEnemy();
private:
    const int gapBetweenEnemies = 10;

    std::vector<Enemy> enemies;
};

Enemy. cpp

Enemy::Enemy(sf::Vector2f startingPosition, Type type) : 
Collidable(enemyWidth, enemyHeight), newPosition(startingPosition), enemyType(type), startingPosition(startingPosition)
{
}

Enemy.h

class Enemy : public Collidable
{
public:
    enum class Type // enum for different looking enemies
    {
        Crab, Octopus, Squid
    };
    Enemy(sf::Vector2f startingPosition, Type type);

    constexpr static float enemyWidth = 30.0f;
    constexpr static float enemyHeight = 30.0f;

private:
    sf::Vector2f newPosition;
    Type enemyType;

    const sf::Vector2f startingPosition;
};

Складной . cpp

Collidable::Collidable(float width, float height) :
 spriteSize(width, height)
{
}

Collidable.h

class Collidable
{
public:
    Collidable(float width, float height);
private:
    sf::Vector2f spriteSize;
};

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

1 Ответ

0 голосов
/ 20 марта 2020

Если у класса есть переменная-член const, то оператор копирования для этого класса operator= удаляется компилятором по умолчанию.

С https://en.cppreference.com/w/cpp/language/copy_assignment:

Оператор присваивания по умолчанию для класса T определяется как удаленный, если выполняется любое из следующих условий:
- T имеет элемент данных non-stati c, не относящийся к классу ( или их массив), который является const;

Это связано с тем, что компилятор не может угадать, что означает копировать объект присвоения A в объект B, если объекты их класса содержат переменную-член const. Должен ли компилятор просто игнорировать эту конкретную переменную-член? Если компилятор угадает, что вы имеете в виду const, за исключением случаев, когда назначается копирование, тогда это нормально, только один раз - я посмотрю в другую сторону? Компилятор не знает, что бы вы предпочли, поэтому он просто удаляет его.

Один из вариантов - явное определение оператора присваивания для вашего класса.

Однако startingPosition уже объявлен частный, так что маловероятно, что что-то за пределами класса случайно изменит его. Я рекомендую просто удалить спецификатор const.

Почему оператор копирования имеет значение? Я пытаюсь удалить вещи, а не копировать, назначить их

Когда элемент стирается из vector, все элементы в vector "выше" стертого элемента необходимо переместить вниз, чтобы заполнить разрыв. Это происходит с помощью оператора копирования.

С https://en.cppreference.com/w/cpp/container/vector/erase:

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

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