我正在尝试制作基于文本的大富翁游戏。对于板上的每个磁贴,我都有一个Tile或PropertyTile对象。 PropertyTile是Tile类的子级,具有其他属性。
最初,我有一个 vector 来容纳所有图块,包括Tile和PropertyTile,但后来发现由于对象 slice ,正确的方法是使用unique_ptr。
当我切换到unique_ptr时,我遇到了两个相同的错误:
Error C2280 'std::unique_ptr<Tile,std::default_delete<_Ty>> &std::unique_ptr<_Ty,std::default_delete<_Ty>>::operator =(const std::unique_ptr<_Ty,std::default_delete<_Ty>> &)': attempting to reference a deleted function
with
[
_Ty=Tile
] MonopolyFinal C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\VC\Tools\MSVC\14.22.27905\include\xutility 1768
通过将move()放在Map::getAllTiles()中来解决第一个问题,如下所示。
第二个错误指向Map.h的第30行,即(
vector<unique_ptr<Tile>> tiles;
)。对于Map.cpp Map::Map(),无论是否使用move(),我都尝试了emplace_back和push_back。
我不确定自己在做什么错。以下所有相关代码。提前致谢。
Map.h:
class Map
{
public:
Map();
void display(Player, Player, Player, Player);
vector<unique_ptr<Tile>> getAllTiles();
vector<vector<bool>> getAllTileValidty();
private:
vector<unique_ptr<Tile>> tiles;
vector<vector<bool>> tileValidity;
};
Map.cpp中的构造函数,用于填充图块 vector :
Map::tiles.push_back(move(unique_ptr<Tile>(new PropertyTile("Mediterranean Ave", 9, 10, "Brown", 60, 2, 50) )));
Map::tiles.push_back(move(unique_ptr<Tile>(new Tile("Community Chest", 8, 10)))); //Community Chest (usually gives you extra money)
瓷砖 vector 的 setter/getter :
vector<unique_ptr<Tile>> Map::getAllTiles()
{
return move(tiles);
}
最佳答案
问题的根源是std::unique_ptr
无法复制,只能移动。无法复制它,因为只有一个unique_ptr
可以拥有该对象。尽管如此,所有错误均归因于您尝试复制此类unique_ptr
对象的情况。当然,您可以将std::unique_ptr
替换为std::shared_ptr
,但是同一对象将在多个Map对象之间共享。从一个Map
修改指向的对象,它会影响另一个对象。不确定您是否想要那样。
您的搬家解决方案很可能是错误的:
std::vector<std::unique_ptr<Tile>> Map::getAllTiles()
{
return move(tiles);
}
这将破坏
tiles
对象中的Map
。函数名称错误,或者这不是您想要的。一种可能的解决方案是使用clone()
std::vector<std::unique_ptr<Tile>> Map::getAllTiles()
{
std::vector<std::unique_ptr<Tile>> result;
result.reserve(tiles.size());
for (const auto & tile_ptr: tiles)
{
result.push_back(tile_ptr->clone());
}
return result; // OK, a local is automatically moved, possibly elided
}
Tile及其所有后代在其中实现克隆:
class Tile {
...
virtual std::unique_ptr<Tile> clone() const
{
return std::make_unique<Tile>(*this);
}
..
};
class PropertyTile : public Tile {
...
std::unique_ptr<Tile> clone() const override
{
return std::make_unique<PropertyTile>(*this);
}
..
};
至于Map.h第30行的错误,即
(vector<unique_ptr<Tile>> tiles;)
,我怀疑这是由于自动生成的副本构造函数造成的。删除副本和分配:class Map {
public:
Map(const Map&) = delete;
Map& operator=(const Map&) = delete;
要么,要么通过克隆载体的所有元素一个接一个地正确实现它们。
此外,即使不是问题的根源,以下操作也不是最佳实践:
push_back(move(unique_ptr<Tile>(new PropertyTile(....
最好使用
std::make_unique
,它从C++ 14开始可用:push_back(std::make_unique<PropertyTile>("Mediterranean Ave", 9, 10,....
最后,切勿在代码中的任何地方写入
using namespace std
,也不要在头文件中写入using std::vector
。两者都是错误的:using namespace std
是一个噩梦,可以使代码与新版本的C++标准保持向前兼容。 using std::vector
是Map.h
用户的噩梦,他们可能希望使用具有不同 vector 类型的其他头文件,例如using std::pmr::vector
。这些将相互冲突。 关于c++ - 尝试使用unique_ptr的 vector 引用已删除的函数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59762763/