89 votes

"Erreur "Field has incomplete type

Il y a une erreur dans mon fichier d'en-tête :

field "ui" has incomplete type.

J'ai essayé de faire ui un pointeur, mais cela ne fonctionne pas. Je ne pense pas avoir besoin de faire cela, car j'ai déjà défini ma fonction MainWindowClass dans l'espace de noms Ui . C'est mon 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

118voto

Ed S. Points 70246

Vous utilisez une déclaration forward pour le type MainWindowClass . C'est bien, mais cela signifie également que vous ne pouvez déclarer qu'un pointeur ou une référence à ce type. Sinon, le compilateur n'a aucune idée de la manière d'allouer l'objet parent, car il ne connaît pas la taille du type déclaré en avant (ou s'il a réellement un constructeur sans paramètre, etc.).

Donc, soit vous voulez :

// forward declaration, details unknown
class A;

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

Ou, si vous ne pouvez pas utiliser un pointeur ou une référence....

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

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

A un moment donné, le compilateur a besoin de connaître les détails de A .

Si vous ne stockez qu'un pointeur sur A alors il n'a pas besoin de ces détails lorsque vous déclarez B . Il en a besoin à un moment donné (lorsque vous déréférencez effectivement le pointeur vers A ), qui se trouvera probablement dans le fichier d'implémentation, où vous devrez inclure l'en-tête qui contient la déclaration de la classe 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();
}

23voto

Macmade Points 27414

Le problème est que votre ui utilise un déclaration prospective de la classe Ui::MainWindowClass d'où l'erreur de "type incomplet".

L'inclusion du fichier d'en-tête dans lequel cette classe est déclarée résoudra le problème.

EDITAR

Sur la base de votre commentaire, le code suivant :

namespace Ui
{
    class MainWindowClass;
}

hace PAS déclarer une classe. C'est une déclaration prospective ce qui signifie que la classe existera à un moment donné, au moment du lien.
En gros, il indique simplement au compilateur que le type existera, et qu'il ne doit pas l'avertir.

Mais la classe doit être défini quelque part .

Notez que cela ne peut fonctionner que si vous avez un pointeur à un tel type.
Vous ne pouvez pas avoir une instance allouée statiquement d'un type incomplet.

Donc soit vous voulez réellement un type incomplet, et alors vous devriez déclarer votre ui comme un pointeur :

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

Ou vous voulez une instance statiquement allouée de Ui::MainWindowClass et il doit ensuite être déclaré. Vous pouvez le faire dans un autre fichier d'en-tête (habituellement, il y a un fichier d'en-tête par classe).
Mais il suffit de changer le code en :

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

fonctionnera également.

Notez la différence entre les deux déclarations. La première utilise une déclaration directe, tandis que la seconde déclare réellement la classe (ici sans propriétés ni méthodes).

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X