我正在写国际象棋应用程序。 Board
类包含一个Square
数组,每个数组可以容纳一个Piece
。特定于类型的类(Pawn
,Rook
等)继承自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;
...
};
答案 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
时将其回收)。