我正在写一个象棋应用。所述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;
};
问题是你身边掠过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
提升为被回收)。