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

时间:2019-02-05 21:40:51

标签: c++ oop pointers inheritance

我正在写国际象棋应用程序。 Board类包含一个Square数组,每个数组可以容纳一个Piece。特定于类型的类(PawnRook等)继承自Piece

为此,Square具有一个成员变量,该成员变量指向特定的Piece(正在占用那个Square)。

我遇到的麻烦是,当我尝试设置Board时,无法将我创建的unique_ptr分配给{{1}的成员变量}。

这是函数调用的一般流程:

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设置另一个对象的成员变量?

这里是每个类的头文件,以防万一。并且请原谅我的问题。我已经尽力做到了。

Board.hpp

unique_ptr

Square.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();
    ...
};

Piece.hpp

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

Pawn.hpp

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

1 个答案:

答案 0 :(得分:2)

问题是您正在按值传递}个对象而不使用std::unique_ptr,因此您尝试复制移动std::move()不能复制,只能复制,否则,单所有权语义将被破坏。这就是使std::unique_ptr“唯一”的原因-一次只能有1个std::unique_ptr可以引用内存中的给定对象。

请尝试以下类似操作:

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所有权,并且只有当新的{分配了{1}}(例如,将捕获的Piece移动到另一个列表,当提升Piece时将其回收)。