不完整类型的使用无效 "class"
Invalid use of incomplete type "class"
我知道有很多这样的问题,但不幸的是,经过数小时的谷歌搜索和浏览所有这些问题后,none 我阅读的答案有所帮助。因此,我正在制作我自己的问题版本。我收到的错误消息是:"error: invalid use of incomplete type ‘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 或任何被注释掉的行,我忘了删除它们。请帮忙!
当你向前声明一个类型时,你只能使用 pointers 或 references 到那个类型的对象,所以 padding.h 几乎没有编译:
std::vector<Cell> cells;
我想编译器的抱怨来自于它试图决定如何 build/destroy 向量中的 Cell 对象。为此,它需要有关类型的信息,通常来自类型声明(即头文件)。
我知道有很多这样的问题,但不幸的是,经过数小时的谷歌搜索和浏览所有这些问题后,none 我阅读的答案有所帮助。因此,我正在制作我自己的问题版本。我收到的错误消息是:"error: invalid use of incomplete type ‘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 或任何被注释掉的行,我忘了删除它们。请帮忙!
当你向前声明一个类型时,你只能使用 pointers 或 references 到那个类型的对象,所以 padding.h 几乎没有编译:
std::vector<Cell> cells;
我想编译器的抱怨来自于它试图决定如何 build/destroy 向量中的 Cell 对象。为此,它需要有关类型的信息,通常来自类型声明(即头文件)。