Как передать unique_ptr, чтобы установить переменную-член моего объекта? - PullRequest
0 голосов
/ 06 февраля 2019

Я пишу шахматную заявку.Класс Board содержит массив Square, каждый из которых может содержать Piece.Специфичные для типа классы (Pawn, Rook и т. Д.) Наследуются от Piece.

. Для этого Square имеет переменную-член, которая указывает на конкретный Piece (который занимает это Square).

Проблема, с которой я сталкиваюсь, заключается в том, что, когда я пытаюсь настроить Board, я не могу назначить unique_ptr, который я создал, дляпеременная-член Square.

Вот общий поток вызовов функций:

void Board::setBoard()
{
    // White Pawn Placement
    std::unique_ptr<Piece> wp1 = std::make_unique<Pawn>(PAWN, WHITE);
    Board::setPiece("a2", wp1);
}

Pawn::Pawn(Type t, Color c) : Piece(t, c) {}

void Board::setPiece(const std::string &coords, std::unique_ptr<Piece> piece)
{
    squareMap[coords].setPiece(piece);
}

void Square::setPiece(std::unique_ptr<Piece> piece)
{
    Square::piece = std::move(piece);
}

Я получаю следующую ошибку, когда пытаюсь скомпилировать в строке, содержащей Board::setPiece("a2", wp1);

error: call to implicitly-deleted copy constructor of 'std::unique_ptr<Piece>'

, что, разумеется, немного глотает.

ЕстьВ Интернете есть хорошая документация о наследовании, абстрактных классах, использовании unique_ptr и т. д., но я не смог понять, как все эти вещи сочетаются друг с другом.

Итак, вопрос:

Как я могу создать объект, присвоить ему unique_ptr, а затем использовать этот unique_ptr для установки переменной-члена другого объекта?

Вот файлы заголовков длякаждый класс, в случае, если это освещение.И, пожалуйста, прости меня за длину моего вопроса.Я сделал это так коротко, как только смогу.

Board.hpp

class Board {
public:
    Board();
    void printBoard();
    Piece getPiece(const std::string &coords);
    void setPiece(const std::string &coords, std::unique_ptr<Piece> piece);
    ~Board();
    ...
};

Square.hpp

class Square
{
public:
    void setPiece(std::unique_ptr<Piece> piece);
    Piece* getPiece() const;
protected:
    std::unique_ptr<Piece> piece;
    ...
};

Piece.hpp

class Piece
{
public:
    Piece();
    Piece(Type, Color);
    virtual bool movePiece() = 0; // abstract class
protected:
    Color color;
    Type type;
    bool moved;
    ...
};

Pawn.hpp

class Pawn : public Piece
{
public:
    Pawn(Type t, Color c);
    bool movePiece() override;
};

1 Ответ

0 голосов
/ 06 февраля 2019

Проблема в том, что вы передаете вокруг std::unique_ptr объекты по значению без использования std::move(), поэтому вы пытаетесь копировать их вместо move им.std::unique_ptr не может быть скопировано, только перемещено, иначе семантика единоличного владения будет нарушена.Это то, что делает std::unique_ptr «уникальным» - только 1 std::unique_ptr может одновременно ссылаться на данный объект в памяти.

Вместо этого попробуйте что-то вроде этого:

class Pawn : public Piece
{
public:
    Pawn(Color c);
    ...
};

Pawn::Pawn(Color c) : Piece(PAWN, c) {}

class Square
{
public:
    ...

    // for accessing the current Piece without moving it around the Board
    // (for printing, drawing, etc)...
    const Piece* getPiece() const;

    // for moving Pieces around the Board...
    std::unique_ptr<Piece> setPiece(std::unique_ptr<Piece> piece);

    ...

protected:
    std::unique_ptr<Piece> piece;
    ...
};

const Piece* Square::getPiece() const
{
    return piece.get();
}

std::unique_ptr<Piece> Square::setPiece(std::unique_ptr<Piece> piece)
{
    std::unique_ptr<Piece> old = std::move(this->piece);
    this->piece = std::move(piece);
    return std::move(old);
}

class Board {
public:
    ...

    // for accessing a current Piece without moving it around the Board
    // (for printing, drawing, etc)...
    const Piece* getPiece(const std::string &coords) const;

    // for moving Pieces around the Board...
    std::unique_ptr<Piece> setPiece(const std::string &coords, std::unique_ptr<Piece> piece);

    ...

protected:
    std::map<std::string, Square> squareMap;
    ...
};

void Board::setBoard()
{
    ...

    // White Pawn Placement
    std::unique_ptr<Piece> wp1 = std::make_unique<Pawn>(WHITE);
    setPiece("a2", std::move(wp1));

    // or simply:
    //setPiece("a2", std::make_unique<Pawn>(WHITE));

    ...
}

const Piece* Board::getPiece(const std::string &coords) const
{
    auto iter = squareMap.find(coords);
    return (iter != squareMap.end())
        ? iter->second.getPiece()
        : nullptr;
}

std::unique_ptr<Piece> Board::setPiece(const std::string &coords, std::unique_ptr<Piece> piece)
{
    return squareMap[coords].setPiece(std::move(piece));
}

Это позволяет Squareсохранить владение того, что ему в данный момент назначено Piece, и это владение передается только при назначении нового Piece (например, для перемещения захваченного * 1039)* в другой список, который будет восстановлен при повышении Pawn).

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