【问题标题】:C++ vector of vector of abstract class抽象类向量的C++向量
【发布时间】:2019-12-27 11:05:06
【问题描述】:

对于一个简单的国际象棋游戏,我想创建一个(国际象棋)棋子向量的二维向量。所以我的课看起来像

class board {
    private:
        int width, height; //dimensions
        vector<vector<piece> > pieces2D;

    public:
        board(int w=8, int h=8) 
        {
            width = w; height = h;
            vector<vector<piece>> pieces2D(w, vector<piece>(h, 0));
        }

piece 是一个抽象类,所以我不能使用数组。但我无法在构造函数中创建默认大小为 8x8 的pieces2D。缺什么?我也很欣赏存储 64 个(抽象)片段的其他解决方案。

【问题讨论】:

  • 您可以改用vector&lt;vector&lt;std::unique_ptr&lt;piece&gt;&gt; &gt; pieces2D;
  • "abstract" 是 "cannot create instances of that class" 的同义词,因此您不能在仅向量指针(或引用)中拥有 piece 实例
  • 关于次要问题,在构造函数vector&lt;vector&lt;piece&gt;&gt; pieces2D(w, vector&lt;piece&gt;(h, 0)); 中定义了一个 newdistinct 以及 local 变量,名为 @ 987654325@。它与同名的成员变量完全无关。我建议你花点时间研究一下构造函数初始化列表
  • 尽管语法相似,但 C++ 在基本方面与 Java 和 C# 非常不同。

标签: c++ vector 2d-vector


【解决方案1】:

您无法实例化抽象类 - 因此您无法构造包含抽象类型的向量。

这里的解决方案是存储一个指针向量: vector&lt;vector&lt;std::unique_ptr&lt;piece&gt;&gt;&gt;

【讨论】:

  • std::array 可能是更好的选择
  • @JamesPicone 板大小似乎可以在运行时配置
【解决方案2】:

首先,您不能将抽象类用作 std::array、std::vector 或任何其他 STL 容器类的模板。如果您想使用多态性,请使用 std::unique_ptr 或 std::shared_ptr 来存储指向对象的指针。

可以完成pieces2D成员的初始化

class board {
  private:
    int width, height; //dimensions
    vector<vector<piece> > pieces2D;

  public:
    board(int w=8, int h=8) 
      : pieces2D(w, vector<piece>(h, 0))
    {
        width = w; height = h;
    }
};

但是如果不将piece 替换为std::shared_ptr,它将无法工作。恕我直言,最好对这些片段使用平面(一维)数组,因为这样你只有一个堆块要管理。您可以使用 () 运算符(或简单的成员函数)按行和列访问片段:

class Board
{
private:
   int width, height;
   std::vector<std::shared_ptr<Piece>> pieces;

public:
   Board(int width_, int height_)
      : width(width_),
      height(height_),
      pieces(width_ * height_)
   {}

   std::shared_ptr<Piece>& operator()(int row, int col)
   {
      return pieces[row*width+col];
   }
};

并使用它:

Board board(8, 8);
board(1, 2) = std::make_shared<PawnPiece>();

【讨论】:

    【解决方案3】:

    类属性pieces2D的初始化不正确。

    您正在尝试做的是初始化类属性,但您实际上所做的是初始化构造函数的本地对象,该对象名为 pieces2D,当程序超出构造函数范围时将被销毁。

    此外,您不能实例化抽象对象的向量,因为没有对象可以从抽象类中实例化。 但是您可以实例化一个指向抽象对象的指针向量,并将指向派生自基本抽象类的具体对象的指针分配给它。

    您要查找的可能是pieces2D 的初始化列表。

    喜欢:

    class board {
    private:
        int width, height; //dimensions
        vector<vector<piece*> > pieces2D;
    
    public:
        board(int w=8, int h=8): pieces2D(w, vector<piece*>(h, 0))
        {
            width = w; height = h;
        }
    }
    

    【讨论】:

    • 您解决了代码中的一个问题,但您错过了回答实际问题,如果piece 是抽象的,您的示例将无法编译
    • 还有你为什么不使用widthheight 的初始化列表?
    • 其实widthheigth是多余的,应该一起去掉
    • 确实对于关于片段抽象的实际问题,我正在纠正它。我没有改变任何与问题无关的东西,所以我没有改变宽度和高度。我不能假设它们是多余的,可能显示的代码摘录是部分或简化的。
    • 有多余的我并不是说在 OPs 示例中两者都是8,但我的意思是向量已经知道它的大小并且单独存储大小需要不必要的簿记并且是错误的来源
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-11-26
    • 1970-01-01
    • 2020-03-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多