试图引用具有unique_ptr向量的已删除函数

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

我正在尝试制作基于文本的大富翁游戏。对于板上的每个磁贴,我都有一个Tile或PropertyTile对象。 PropertyTile是Tile类的子级,具有额外的属性。最初,我有一个向量来容纳所有图块,包括Tile和PropertyTile,但后来发现由于对象切片,正确的方法是使用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中的构造方法:

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<unique_ptr<Tile>> Map::getAllTiles()
{
    return move(tiles);
}
c++ vector polymorphism unique-ptr
1个回答
0
投票

[最有可能,您的移动解决方案是错误的:

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

而且,即使不是问题的根源,以下也不是最佳实践:

push_back(move(unique_ptr<Tile>(new PropertyTile(....

更好地使用std::make_unique,自C ++ 14起可用:

push_back(std::make_unique<PropertyTile>("Mediterranean Ave", 9, 10,....

关于Map.h第30行的错误,即(vector<unique_ptr<Tile>> tiles;),我怀疑这是由于自动生成的副本构造函数造成的。删除副本和分配:

class Map {
 public:
    Map(const Map&) = delete;
    Map& operator=(const Map&) = delete;

要么删除它们,要么通过克隆所有元素来正确实现它们。

最后,永远不要在代码中的任何地方写入using namespace std,也不要在头文件中写入using std::vector。两者都是错误的:

  • [using namespace std是一个噩梦,它使代码与新版本的C ++标准保持向前兼容。
  • using std::vectorMap.h用户的噩梦,他们可能想使用具有不同矢量类型的其他头文件,例如using std::pmr::vector。这些会互相冲突。
© www.soinside.com 2019 - 2024. All rights reserved.