В моем заголовочном файле есть ошибка:
field "ui" has incomplete type.
Я пробовал сделать ui
указателем, но это не работает. Я не думаю, что мне нужно это делать, потому что я уже определил свой MainWindowClass
в пространстве имен Ui
. Это мой mainwindow.h
:
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QtGui/QMainWindow>
#include "ui_mainwindow.h"
namespace Ui {
class MainWindowClass;
}
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
MainWindow(QWidget *parent = 0, Qt::WFlags flags=0);
~MainWindow();
public slots:
void slideValue(int);
private:
Ui::MainWindowClass ui; //error line
};
#endif // MAINWINDOW_H
Вы используете прямое объявление для типа MainWindowClass
. Это прекрасно, но это также означает, что вы можете объявить только указатель или ссылку на этот тип. В противном случае компилятор не имеет понятия, как выделить родительский объект, поскольку он не знает размер объявленного вперед типа (или есть ли у него конструктор без параметров и т.д.).
Итак, вы либо хотите:
// forward declaration, details unknown
class A;
class B {
A *a; // pointer to A, ok
};
Или, если вы не можете использовать указатель или ссылку....
// declaration of A
#include "A.h"
class B {
A a; // ok, declaration of A is known
};
В какой-то момент компилятору нужно узнать подробности A
.
Если вы храните только указатель на A
, то ему не нужны эти подробности, когда вы объявляете B
. Они понадобятся в какой-то момент (когда вы действительно разыменуете указатель на A
), который, скорее всего, будет в файле реализации, куда вам нужно будет включить заголовок, содержащий объявление класса A
.
// B.h
// header file
// forward declaration, details unknown
class A;
class B {
public:
void foo();
private:
A *a; // pointer to A, ok
};
// B.cpp
// implementation file
#include "B.h"
#include "A.h" // declaration of A
B::foo() {
// here we need to know the declaration of A
a->whatever();
}
Проблема в том, что ваше свойство ui
использует переднее объявление класса Ui::MainWindowClass
, отсюда и ошибка "неполного типа".
Включение заголовочного файла, в котором объявлен этот класс, устранит проблему.
EDIT
Основываясь на вашем комментарии, следующий код:
namespace Ui
{
class MainWindowClass;
}
не НЕ объявляет класс. Это переднее объявление, означающее, что класс будет существовать в какой-то момент, во время соединения.
По сути, это просто говорит компилятору, что тип будет существовать, и что он не должен предупреждать об этом.
Но класс должен быть где-то определен.
Обратите внимание, что это может работать, только если у вас есть указатель на такой тип.
Вы не можете иметь статически выделенный экземпляр неполного типа.
Так что либо вам действительно нужен неполный тип, и тогда вы должны объявить член ui
как указатель:
namespace Ui
{
// Forward declaration - Class will have to exist at link time
class MainWindowClass;
}
class MainWindow : public QMainWindow
{
private:
// Member needs to be a pointer, as it's an incomplete type
Ui::MainWindowClass * ui;
};
Либо вы хотите статически выделенный экземпляр Ui::MainWindowClass
, и тогда его нужно объявить.
Вы можете сделать это в другом заголовочном файле (обычно на класс приходится один заголовочный файл).
Но просто измените код на:
namespace Ui
{
// Real class declaration - May/Should be in a specific header file
class MainWindowClass
{};
}
class MainWindow : public QMainWindow
{
private:
// Member can be statically allocated, as the type is complete
Ui::MainWindowClass ui;
};
тоже сработает.
Обратите внимание на разницу между двумя объявлениями. Первое использует прямое объявление, а второе фактически объявляет класс (здесь нет ни свойств, ни методов).