ChatGPT解决这个技术问题 Extra ChatGPT

"Field has incomplete type" error

c++

There is an error in my header file:

field "ui" has incomplete type.

I have tried making ui a pointer, but that doesn't work. I don't think I need to do that because I have already defined my MainWindowClass in the namespace Ui. This is my 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
Also, this is wholly unrelated to QtCreator

E
Ed S.

You are using a forward declaration for the type MainWindowClass. That's fine, but it also means that you can only declare a pointer or reference to that type. Otherwise the compiler has no idea how to allocate the parent object as it doesn't know the size of the forward declared type (or if it actually has a parameterless constructor, etc.)

So, you either want:

// forward declaration, details unknown
class A;

class B {
  A *a;  // pointer to A, ok
};

Or, if you can't use a pointer or reference....

// declaration of A
#include "A.h"

class B {
  A a;  // ok, declaration of A is known
};

At some point, the compiler needs to know the details of A.

If you are only storing a pointer to A then it doesn't need those details when you declare B. It needs them at some point (whenever you actually dereference the pointer to A), which will likely be in the implementation file, where you will need to include the header which contains the declaration of the class 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();
}

I would just like to add that you can achieve the same goal via templates. The first example (rextester.com/TLPEJW28982) declares A as a global class and defines it after the class template definition. As an advantage, you don't have to worry about where you define struct A and you avoid coupling. The second example (rextester.com/PJCD69132) considers A as a nested struct of B. The reason this compiles and runs fine is because of the two-phase lookup that occurs when instantiating a template. For more details, please refer to C++ Templates: The Complete Guide, 10.3.1 Two-Phase Lookup.
M
Macmade

The problem is that your ui property uses a forward declaration of class Ui::MainWindowClass, hence the "incomplete type" error.

Including the header file in which this class is declared will fix the problem.

EDIT

Based on your comment, the following code:

namespace Ui
{
    class MainWindowClass;
}

does NOT declare a class. It's a forward declaration, meaning that the class will exist at some point, at link time. Basically, it just tells the compiler that the type will exist, and that it shouldn't warn about it.

But the class has to be defined somewhere.

Note this can only work if you have a pointer to such a type. You can't have a statically allocated instance of an incomplete type.

So either you actually want an incomplete type, and then you should declare your ui member as a pointer:

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

Or you want a statically allocated instance of Ui::MainWindowClass, and then it needs to be declared. You can do it in another header file (usually, there's one header file per class).
But simply changing the code to:

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

will also work.

Note the difference between the two declarations. First uses a forward declaration, while the second one actually declares the class (here with no properties nor methods).


Thanks. This is the only header file I have. I have declared the class MainWindowClass above, right after the #includes. Should I create a new header file?
There is no forward declaration, the problem is declaring a member variable of the same type that is currently being defined.
Nevermind, I got lost on curly braces, didn't see that this was actually a class declared below the forward declaration of MainWindowClass.
Ui::MainWindowClass (member variable) is defined in MainWindow. Not really the same kind.
However, I would not that, if you're using a forward declaration, then the variable must be a pointer or reference to the forward declared type. Otherwise, if that is unacceptable, you need to include the header which contains the declaration of the type.

关注公众号,不定期副业成功案例分享
Follow WeChat

Success story sharing

Want to stay one step ahead of the latest teleworks?

Subscribe Now