我的标头文件中有错误:
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
答案 0 :(得分:88)
您正在使用类型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();
}
答案 1 :(得分:14)
问题是,您的ui
媒体资源使用Ui::MainWindowClass
类namespace Ui
{
class MainWindowClass;
}
,因此出现“不完整类型”错误。
包含声明此类的头文件将解决问题。
修改强>
根据您的评论,以下代码:
ui
NOT 声明一个类。这是一个前向声明,这意味着该课程将在某个时间点,链接时存在 基本上,它只是告诉编译器类型将存在,并且它不应该警告它。
但必须在某处定义 。
请注意,这只适用于此类型的指针 您不能拥有静态分配的不完整类型的实例。
所以要么你实际上想要一个不完整的类型,那么你应该将你的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;
};
实例,然后需要声明它。
您可以在另一个头文件中执行此操作(通常,每个类有一个头文件)
但只需将代码更改为:
{{1}}
也可以。
注意两个声明之间的区别。首先使用前向声明,而第二个实际声明类(这里没有属性或方法)。