使用不完整类型“类”无效

时间:2018-01-07 16:21:15

标签: c++ qt forward-declaration

我知道有很多类似的问题,但不幸的是,经过数小时的谷歌搜索和浏览所有这些问题,我读到的答案都没有帮助。因此,我正在制作我自己的问题版本。我得到的错误消息是:“错误:无效使用不完整类型'std :: iterator_traits :: value_type {aka class Cell}'”我的代码:

cell.h

#ifndef CELL_H
#define CELL_H

#include <QPushButton>
#include <QMouseEvent>
#include <vector>

class Padding;

class Cell : public QPushButton
{
    Q_OBJECT

    public:

        friend class Padding;
        Cell(int x, int y, Padding* padding, QWidget* parent = 0) : QPushButton(parent), x(x), y(y),
            padding(padding)
        {
            setFixedSize(20, 20);
        }
        Cell(const Cell& object) : QPushButton(), x(object.x), y(object.y), padding(object.padding)
        {
            setFixedSize(20, 20);
        }
        int getX() { return x; };
        int getY() { return y; };
        bool hasMine() { return mine; };
        void setHasMine(bool mine) { this -> mine = mine; };
        bool isFlagged() { return flagged; };
        bool didExplode() { return exploded; };
        bool getHasBeenClicked() { return hasBeenClicked; };
        void clicked();
        ~Cell() {};
        Cell operator=(const Cell& object)
        {
            if(&object == this)
            {
                return *this;
            }
            padding = object.padding;
            x = object.x;
            y = object.y;
            mine = object.mine;
            flagged = object.flagged;
            exploded = object.exploded;
            hasBeenClicked = object.hasBeenClicked;
            setFixedSize(20, 20);
            return *this;
        }

    private:

        Padding* padding;
        int x;
        int y;
        bool mine = false;
        bool flagged = false;
        bool exploded = false;
        bool hasBeenClicked = false;
        void mousePressEvent(QMouseEvent* e);
        void rightClicked();
};

#endif // CELL_H

cell.cpp

#include "cell.h"
#include "padding.h"

void Cell::mousePressEvent(QMouseEvent* event)
{
    if(event -> button() == Qt::LeftButton)
    {
        clicked();
    }
    else if(event -> button() == Qt::RightButton)
    {
        rightClicked();
    }
}

void Cell::clicked()
{
    hasBeenClicked = true;
    // TODO: Set the button frame to flat. DONE.
    setFlat(true);
    // TODO: Make the button not click able. DONE.
    setEnabled(false);
    // TODO: Display appropriate number on the button, or mine and end the game. DONE.
    if(mine)
    {
        // TODO: Send game over signal and end the game.
        //setIcon(QIcon("mine_clicked.png"));
        setText("/");
        exploded = true;
        padding -> gameOver();
    }
    else
    {
        setText(QString::number(padding -> countMinesAround(this)));
    }
    if(padding -> countMinesAround(this) == 0)
    {
        // Trigger chain reaction; uncover many neighboring cells, if they are not mines.
        padding -> triggerChainReactionAround(this);
    }
}

void Cell::rightClicked()
{
    if(text() != "f")
    {
        setText("f");
        (padding -> minesLeft)--;
    }
    else
    {
        setText("");
        (padding -> minesLeft)++;
    }
    flagged = !flagged;
}

padding.h

#ifndef PADDING_H
#define PADDING_H

#include <QWidget>
#include <QGridLayout>
#include <vector>

class Cell;

class Padding : public QWidget
{
    Q_OBJECT

    public:

        friend class Cell;

        enum class Difficulty
        {
            Beginner,
            Intermediate,
            Advanced,
            Custom
        };

        Padding(QWidget* parent = 0);
        void newGame();
        void gameOver();
        void setLevel(Padding::Difficulty difficulty) { this -> difficulty = difficulty; };
        void setPaddingHeight(int height) { paddingHeight = height; };
        void setPaddingWidth(int width) { paddingWidth = width; };
        void setMines(int mines) { this -> mines = mines; };
        int getMinesLeft() { return minesLeft; };
        ~Padding() {};

    private:

        struct DifficultyLevelsProperties
        {
            struct BeginnerProperties
            {
                const int PADDING_HEIGHT = 9;
                const int PADDING_WIDTH = 9;
                const int MINES = 10;
            } Beginner;

            struct IntermediateProperties
            {
                const int PADDING_HEIGHT = 16;
                const int PADDING_WIDTH = 16;
                const int MINES = 40;
            } Intermediate;

            struct AdvancedProperties
            {
                const int PADDING_HEIGHT = 16;
                const int PADDING_WIDTH = 40;
                const int MINES = 99;
            } Advanced;
        } LevelProperties;

        Difficulty difficulty = Difficulty::Beginner;
        int paddingHeight;
        int paddingWidth;
        int mines;
        // Mines that are not flagged.
        int minesLeft;
        // Time in seconds since the game was started.
        int secondsSinceStart;
        std::vector<Cell> cells;
        QGridLayout* paddingLayout;
        const int CELLS_HEIGHT = 20;
        const int CELLS_WIDTH = 20;
        int countMinesAround(Cell*);
        void triggerChainReactionAround(Cell*);
        void updateSecondsSinceStart();
};

#endif // PADDING_H

padding.cpp

#include "padding.h"
#include <QGridLayout>
#include <QTimer>
#include <QTime>
#include <QDebug>
#include "cell.h"

Padding::Padding(QWidget* parent) : QWidget(parent)
{
    newGame();
    paddingLayout = new QGridLayout(this);
    paddingLayout -> setSpacing(0);
}

void Padding::newGame()
{
    if(difficulty == Padding::Difficulty::Beginner)
    {
        paddingHeight = LevelProperties.Beginner.PADDING_HEIGHT;
        paddingWidth = LevelProperties.Beginner.PADDING_WIDTH;
        mines = LevelProperties.Beginner.MINES;
    }
    else if(difficulty == Padding::Difficulty::Intermediate)
    {
        paddingHeight = LevelProperties.Intermediate.PADDING_HEIGHT;
        paddingWidth = LevelProperties.Intermediate.PADDING_WIDTH;
        mines = LevelProperties.Intermediate.MINES;
    }
    else if(difficulty == Padding::Difficulty::Advanced)
    {
        paddingHeight = LevelProperties.Advanced.PADDING_HEIGHT;
        paddingWidth = LevelProperties.Advanced.PADDING_WIDTH;
        mines = LevelProperties.Advanced.MINES;
    }
    minesLeft = mines;
    cells.clear();
    for(int i = 0; i < paddingHeight; i++)
    {
        for(int j = 0; j < paddingWidth; j++)
        {
            // TODO: Use smart pointers instead of raw pointers.
            Cell* cell = new Cell(j + 1, i + 1, this);
            cells.push_back(*cell);
            delete cell;
        }
    }
    qsrand(QTime::currentTime().msec());
    for(int i = 0; i < mines; i++)
    {
        // TODO: Fix the randomness of the numbers. DONE.
        cells[qrand() % (paddingHeight * paddingWidth) + 1].setHasMine(true);
    }
    for(int i = 0; i < cells.size(); i++)
    {
        paddingLayout -> addWidget(&cells[i], cells[i].getY(), cells[i].getX());
    }
}

void Padding::gameOver()
{
    for(int i = 0; i < cells.size(); i++)
    {
        cells[i].setEnabled(false);
        if((cells[i].hasMine()) && (!cells[i].getHasBeenClicked()))
        {
            cells[i].clicked();
        }
    }
}

int Padding::countMinesAround(Cell*)
{
    int minesCounter = 0;
    for(int i = 0; i < cells.size(); i++)
    {
        qDebug() << QString::number(cells[i].getX());
        if(((x - cells[i].getX() == 0) || (x - cells[i].getX() == 1) || (x -
            cells[i].getX() == -1)) && ((y - cells[i].getY() == 0) || (y -
            cells[i].getY() == 1) || (y - cells[i].getY() == -1)) &&
            (cells[i].hasMine()))
        {
            minesCounter++;
        }
    }
    return minesCounter;
}

void Padding::triggerChainReactionAround(Cell*)
{
    for(int i = 0; i < cells.size(); i++)
    {
        if(((x - cells[i].getX() == 0) || (x - cells[i].getX() == 1) || (x -
            cells[i].getX() == -1)) && ((y - cells[i].getY() == 0) || (y -
            cells[i].getY() == 1) || (y - cells[i].getY() == -1)) &&
            (!cells[i].getHasBeenClicked()))
        {
            cells[i].clicked();
        }
    }
}

抱歉整件事情有多长,但我无法缩短它,因为我无法找到导致错误的原因。另外请忽略任何TODO或任何注释掉的行,我忘了删除它们。请帮忙!

1 个答案:

答案 0 :(得分:0)

当您转发声明类型时,您只能对该类型对象使用指针引用,因此 padding.h 中的这一行几乎没有编译:

2-3-4-1

我认为编译器投诉来自于它试图决定如何在向量中构建/销毁Cell对象的位置。为此,它需要有关类型的信息,通常来自类型声明(即头文件)。