“字段的类型不完整”错误


79

我的头文件中有一个错误:

field "ui" has incomplete type.

我尝试过创建ui一个指针,但这不起作用。我认为我不需要这样做,因为我已经MainWindowClass在名称空间中定义了my 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

3
此外,这与QtCreator完全无关
weberc2 2013年

Answers:


104

您正在使用类型的前向声明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();
}

我想补充一点,您可以通过模板实现相同的目标。第一个示例(rextester.com/TLPEJW28982)将A声明为全局类,并在类模板定义之后对其进行定义。优点是,您不必担心在哪里定义结构A,并且避免耦合。第二个示例(rextester.com/PJCD69132)将A视为B的嵌套结构。之所以编译并运行良好,是因为实例化模板时发生了两阶段查找。有关更多详细信息,请参阅《 C ++模板:完整指南,10.3.1两阶段查找》。
Constantinos Glynos

20

问题是您的ui属性使用class 的前向声明Ui::MainWindowClass,因此出现“不完整类型”错误。

包括在其中声明此类的头文件将解决此问题。

编辑

根据您的评论,以下代码:

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;
};

也可以。

请注意两个声明之间的区别。第一个使用前向声明,而第二个实际上声明类(此处没有属性或方法)。


谢谢。这是我唯一的头文件。我已经在#includes之后声明了上面的MainWindowClass类。我应该创建一个新的头文件吗?
IsabellaW 2012年

没有前向声明,问题在于声明当前正在定义的相同类型的成员变量。
Ed S.

没关系,我迷上了花括号,没有看到这实际上是在的正向声明下面声明的类MainWindowClass
Ed S.

Ui::MainWindowClass(成员变量)在中定义MainWindow。并非完全相同。
Macmade 2012年

但是,如果您使用的是前向声明,那么我不会那样做,那么该变量必须是指针或对前向声明类型的引用。否则,如果不能接受,则需要包括包含类型声明的标头。
Ed S.
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.