向量

时间:2017-07-01 11:22:14

标签: c++ c++11 wxwidgets

我有一个名为Grid的类,它由Cells组成。每个单元格都有自己的格式(概念类似于MS Excel)。

网格中的格式保存在拥有所有格式的向量std::vector<std::unique_ptr<CellFormat>> m_CellFormatTable中,因此每当我需要读取单元格格式时,我都会从向量中读取它,每当有变化时,都会报告回到矢量。对不起,我是C ++ 11标准的新手,所以我的想法可能是错的。

由于网格是一个矩阵,当单元格格式发生变化时,每个单元属于矩阵的不同部分,它应该反映在矩阵的正确部分,即正确定位在向量中(CellFormatTable) 。因此,在这个阶段我不能使用向量的push_back方法。

CellFormat类:

struct CellFormat
{
    wxFont m_Font;
    wxColor m_BackgroundColor, m_TextColor;
    int m_HorizontalAlignment, m_VerticalAlignment;

    CellFormat(Grid* ws) {
        m_BackgroundColor = ws->GetDefaultCellBackgroundColour();
        m_TextColor=ws->GetDefaultCellTextColour();
        int horizontal = 0, vertical = 0;
        ws->GetDefaultCellAlignment(&horizontal, &vertical);
    }

    CellFormat(const CellFormat& other) {
        m_Font = other.m_Font;
        m_BackgroundColor = other.m_BackgroundColor;
        m_TextColor = other.m_TextColor;
        m_HorizontalAlignment = other.m_HorizontalAlignment;
        m_VerticalAlignment = other.m_VerticalAlignment;
    }

    CellFormat& operator=(const CellFormat& other) {
        if (this == &other) return *this;
        m_Font = other.m_Font;
        m_BackgroundColor = other.m_BackgroundColor;
        m_TextColor = other.m_TextColor;
        m_HorizontalAlignment = other.m_HorizontalAlignment;
        m_VerticalAlignment = other.m_VerticalAlignment;

        return *this;
    }
};

在Grid.h中

class Grid{
    std::vector<std::unique_ptr<CellFormat>> m_CellFormatTable;
    //
    CellFormat* GetCellFormat(int row, int column);
    void SetCellFormat(int row, int column, CellFormat format);
    void ApplyCellFormat(int row, int column, const CellFormat* format);
    CellFormat* CreateCellFormat(int row, int column);
    //rest is omitted
}

在Grid.cpp中

Grid(some arguments){
    m_CellFormatTable.resize(nrows*ncols);
    //rest is omitted
}

CellFormat* Grid::GetCellFormat(int row, int column)
{
    int ncols= GetNumberCols();

    return m_CellFormatTable[row*ncols+ column].get();
}

void Grid::SetCellFormat(int row, int column, CellFormat other)
{
    CellFormat* format = GetCellFormat(row, column);
    if (format == 0) format = CreateCellFormat(row, column);
    *format = other;
}

void Grid::ApplyCellFormat(int row, int column, const CellFormat * format)
{
    if (format == 0) {
        int ncols= GetNumberCols();
        //Set everything to default values
        //Omitted

        m_CellFormatTable[row*ncols+ column].reset();
    }
    else {
        wxColor bgcolor = format->m_BackgroundColor;
        if (bgcolor.IsOk()) SetCellBackgroundColour(row, column, bgcolor);
        SetCellTextColour(row, column, format->m_TextColor);
        SetCellFont(row, column, format->m_Font);
        SetCellAlignment(row, column, format->m_HorizontalAlignment, format->m_VerticalAlignment);
    }
}

CellFormat* Grid::CreateCellFormat(int row, int column)
{
    int ncols= GetNumberCols();
    CellFormat* format = new CellFormat(this);
    m_CellFormatTable.emplace(m_CellFormatTable.begin() + row*ncols+ column, std::move(format));

    return format;
}

每当我格式化一个单元格时,说它的背景颜色会改变,我会使用以下尝试:

CellFormat* format = ws->GetCellFormat(row, col);
if (format == 0) format = ws->CreateCellFormat(row, col);

if (ChangeFillColor) {
    ws->SetCellBackgroundColour(row, col, m_LastChosenFillColor);
    format->m_BackgroundColor = m_LastChosenFillColor;
}

代码在ApplyCellFormatformat->m_BackgroundColor处失败,因为应该是Cell的背景颜色的颜色无效。这告诉我,大多数且极有可能CreateCellFormat不会将CellFormat放在正确的位置。我尝试使用insert而不是emplace,但编译器(VS 2015)抱怨我所有的尝试。

任何想法都赞赏。

4 个答案:

答案 0 :(得分:1)

你有几个问题。
一个是您添加CellFormat*,但您的矢量存储unique_ptr;因此您需要std::make_unique新格式。

问题:你确定你需要一个指针向量而不是对象吗?

其他是你假定向量包含所有单元格的所有数据,如果它们尚未设置则为0。那是错的。向量只有你拥有的元素和推送的元素一样多。或者&#39;安放&#39;
我们说你已经推动了#39;单元格(0,0)的格式。现在你要设置(5,2)的格式,即(比如你有10个cols)矢量中的第52个元素,但你只有一个。因此vector[51]未定义(vector.at(51)会引发错误)。
首先添加所有单元格格式,其中某些值= 0表示尚未设置。或者重新考虑你的策略。

顺便说一句,你可以使用wxGridCellAttr来提供你自己编码的内容。

答案 1 :(得分:1)

由于您使用vector unique_ptr(而不是对象),我推断并非矩阵的所有元素都被实际占用。在这种情况下,最好使用std::map(或矩阵非常大的std::unordered_map)对象(不是unique_ptr s)。

template<typename T>
struct grid
{
    using index = std::pair<unsigned, unsigned>;

    // insert element if not already present
    // returns if insertion occurred
    template<typename...Args>
    bool insert(index const&i, Args&&...args)
    {
        return data.emplace(std::forward<Args>(args)...).second;
    }

    // remove element (if it exists)
    void remove(index const&i)
    {
        data.erase(i);
    }

    // get pointer to element, may be nullptr
    T* get(index const&i)
    {
        auto it = data.find(i);
        return it==data.end() ?
            nullptr : std::addressof(*it);
    }
  private:
    std::map<index,T> data;
};

答案 2 :(得分:0)

我在代码的这一部分中看到您的代码失败的原因是:

CellFormat* format = ws->GetCellFormat(row, col);
if (format == 0) format = ws->CreateCellFormat(row, col);

if (ChangeFillColor) {
    ws->SetCellBackgroundColour(row, col, m_LastChosenFillColor);
    format->m_BackgroundColor = m_LastChosenFillColor;
}

是由于您的课程定义如何:

class Grid{
    std::vector<std::unique_ptr<CellFormat>> m_CellFormatTable;
    //
    CellFormat* GetCellFormat(int row, int column);
    void SetCellFormat(int row, int column, CellFormat format);
    void ApplyCellFormat(int row, int column, const CellFormat* format);
    CellFormat* CreateCellFormat(int row, int column);
    //rest is omitted
}

默认情况下,您的班级将其成员和功能设置为private:

将您的班级更改为:

class Grid {
public:
    typedef std::vector<std::unique_ptr<CellFormat>> Format;
private:
    Format m_CellFormatTable;

public:
    CellFormat* getCellFormat( int row, int column );
    void        setCellFormat( int row, int column, const CellFormat& format );
    void        applyCellFormat( int row, int column, const CellFormat& format );

   // Add This Function If Needed
   Format getCellFormatTable() const { return m_CellFormatTable; }
};

所以你的类的成员函数被声明为public:然后外部和非朋友对象现在可以访问这个类的成员函数,并能够通过一个返回数据结构得到方法。

答案 3 :(得分:0)

感谢所有有用的评论和帖子。最后它按预期工作。

正如Ripi2所建议的那样,向量中的CellFormat个对象没有被初始化,所以在构造函数中我初始化它们。这里也没有提到,我在代码中的某个地方有一个未初始化的对象矢量,所以也纠正了那个部分。

虽然循环遍历网格的所有行和列并创建默认格式并不是最好的主意,但我未来的工作将是Walter的建议,即使用集合。

Grid(some arguments){
    for (int i = 0; i < nrows*ncols; i++) {
        m_CellFormatTable.emplace_back(new CellFormat(this));
    }
   //Rest is omitted
}

也在下面的代码中进行了更正:

CellFormat* Grid::CreateCellFormat(int row, int column)
{
    int ncols = GetNumberCols();
    CellFormat* format = new CellFormat(this);
    std::unique_ptr<CellFormat> ptr(format);
    m_CellFormatTable.emplace(m_CellFormatTable.begin() + row*ncols + column,std::move(ptr));

    return format;
}

跟踪格式的一种方法是:

CellFormat* format = ws->GetCellFormat(i, j);
if (ChangeFillColor) {
    ws->SetCellBackgroundColour(i, j, m_LastChosenFillColor);
    format->m_BackgroundColor = m_LastChosenFillColor;
}