如何传递的unique_ptr设置我的对象的成员变量?

问题描述 投票:0回答:1

我正在写一个象棋应用。所述Board类包含Square的阵列,其中的每一个可以容纳Piece。类型特定类(PawnRook等)从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;
};
c++ oop pointers inheritance
1个回答
2
投票

问题是你身边掠过std::unique_ptr对象的值,而不使用std::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被分配所有权转移(例如,在拍摄Piece移动到另一个列表中,当一个Pawn提升为被回收)。

© www.soinside.com 2019 - 2024. All rights reserved.