我的头文件中有一个错误:
field "ui" has incomplete type.
我试着让 ui
成为一个指针,但这不起作用。我觉得没必要这么做,因为我已经在命名空间 Ui
中定义了我的 MainWindowClass
。这是我的 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
的 转发声明,因此出现了 "incomplete type" 错误。
加入声明该类的头文件可以解决问题。
**编辑***
根据您的评论,以下代码:
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;
};
也同样有效。
注意这两个声明之间的区别。第一个声明使用了前向声明,而第二个声明实际上是在声明类(这里没有属性也没有方法)。