ошибка C2280: попытка сослаться на удаленную функцию (попытка вызвать vector.erase)

Я новичок в С++. Я разрабатываю клон прорыва с SFML и Box2D, и я получаю эту ошибку при компиляции. Подробности ошибки:

c:\program files (x86)\visual studio express 2013\vc\include\xutility(2420): error C2280: 'Tile &Tile::operator =(const Tile &)' : attempting to reference a deleted function
c:\users\harry\documents\visual studio 2013\projects\cpp-breakout\cpp-breakout\entities\tile.hpp(27) : compiler has generated 'Tile::operator =' here

Ошибка возникает, когда я пытаюсь стереть объекты Tile из std::vector‹ Tile> с помощью vector.erase.

Tile.h

class Tile : public Entity {
public:
    Tile(b2World* world, float posX, float posY);
    void draw(sf::RenderWindow& window);

    const float PTM_RATIO = 32.f;
    const int HALF_WIDTH = 32;
    const int HALF_HEIGHT = 16;
    int armor;
    bool flaggedToErase = false;

    b2Body* tileBody;
    sf::Sprite sprite;
};

Tile.cpp

Tile::Tile(b2World* world, float posX, float posY)
{
    // Define a body.
    b2BodyDef tileBodyDef;
    tileBodyDef.type = b2_staticBody;
    tileBodyDef.position.Set((posX + HALF_WIDTH) / PTM_RATIO, (posY + HALF_HEIGHT) / PTM_RATIO);

    // Use the body definition to create the actual body instance.
    tileBody = world->CreateBody(&tileBodyDef);
    tileBody->SetUserData(this);
    // Define shape.
    b2PolygonShape tileShape;
    tileShape.SetAsBox(HALF_WIDTH / PTM_RATIO, HALF_HEIGHT / PTM_RATIO);

    // Define fixture.
    b2FixtureDef tileFixtureDef;
    tileFixtureDef.shape = &tileShape;
    tileFixtureDef.density = 10.0f;
    tileFixtureDef.restitution = 0.1f;
    tileFixtureDef.friction = 0.0f;
    //tileFixtureDef.isSensor = true;

    bUserData* bud = new bUserData;
    bud->entityType = TILE;
    tileFixtureDef.userData = bud;

    // Create fixture.
    tileBody->CreateFixture(&tileFixtureDef);
}

Я подталкиваю плитки к вектору в

Level.cpp

std::vector<Tile> solidTiles;

void Level::loadLevel(b2World* world) {
    // Loop through the map and set the tile position and sprites to the tiles.
    for(unsigned int i = 0; i < map.size(); i++) {
        for(unsigned int j = 0; j < map[i].size(); j++) {
            // Set sprites to the tiles in every grid cell which is not -1,-1.
            if(map[i][j].x != -1 && map[i][j].y != -1) {
                Tile tempTile(world, j * TILE_WIDTH, i * TILE_HEIGHT);
                tempTile.sprite = tiles;
                tempTile.sprite.setOrigin(sf::Vector2f(HALF_WIDTH, HALF_HEIGHT));
                tempTile.sprite.setTextureRect(sf::IntRect(map[i][j].x * TILE_WIDTH, map[i][j].y * TILE_HEIGHT, TILE_WIDTH, TILE_HEIGHT));
                tempTile.sprite.setPosition(sf::Vector2f(tempTile.tileBody->GetPosition().x * PTM_RATIO, tempTile.tileBody->GetPosition().y * PTM_RATIO));
                solidTiles.push_back(tempTile);
            }
        }
    }
}

И я пытаюсь стереть плитки в

PlayState.cpp

void PlayState::removeSprites() {
    for(unsigned int i = 0; i < level1.solidTiles.size(); i++) {
        if(level1.solidTiles[i].flaggedToErase == true) {
            level1.solidTiles.erase(level1.solidTiles.begin() + i);
        }
    }
}

Проблема как-то связана с перемещением конструктора/назначения?


person lefti    schedule 23.07.2014    source источник
comment
Я не знаю, какая часть вашего класса вызывает это (Entity? sf::Sprite?), но ваш класс, похоже, не копируется. Если вы не используете С++ 11, вы не можете использовать его в векторе. При использовании C++11 векторы можно использовать с типами только для перемещения.   -  person chris    schedule 24.07.2014
comment
Ваши const участники Tile, вероятно, должны быть статичными.   -  person Brian Bi    schedule 24.07.2014
comment
@ Брайан, очень верно, однако ему все равно может понадобиться написать оператор присваивания копии, в зависимости от семантики b2Body* tileBody;   -  person M.M    schedule 24.07.2014


Ответы (2)


Поскольку класс Tile имеет константные элементы данных, его неявно определяемый оператором присваивания копирования компилятора определяется как удаленный.

Вы должны сами определить оператор присваивания копии явно.

person Vlad from Moscow    schedule 23.07.2014
comment
Спасибо! Я пытался прочитать о конструкторе копирования/перемещения и операторах присваивания, и, исходя из фона Python и С#, я просто очень запутался. Особенно когда у меня такое количество кода в конструкторе Tile. Можете ли вы привести пример, как это сделать, или какие-нибудь хорошие ссылки, чтобы прочитать об этом для кого-то, кто плохо знаком с С++, чтобы я мог это реализовать? - person lefti; 24.07.2014

В ошибке явно упоминается Tile &Tile::operator =(const Tile &), поэтому речь идет об операторе присваивания, а не об операторе перемещения-присваивания. Вам нужно реализовать его для Tile. Вам также не хватает конструктора копирования Tile.

Цитата из здесь:

Неявно объявленный или заданный по умолчанию оператор присваивания копии для класса T определяется как удаленный в любом из следующих случаев:

  • T имеет нестатический член данных, который является константой
  • T имеет нестатический член данных ссылочного типа.
  • T имеет нестатический элемент данных, который не может быть назначен копированием (имеет удаленный, недоступный или неоднозначный оператор присваивания копирования)
  • T имеет прямой или виртуальный базовый класс, который не может быть назначен копированием (имеет удаленный, недоступный или неоднозначный оператор присваивания перемещения)
  • T имеет объявленный пользователем конструктор перемещения
  • T имеет объявленный пользователем оператор присваивания перемещения
person Quentin    schedule 23.07.2014