Подтвердить что ты не робот

Ошибка "Поле имеет неполный тип"

В моем файле заголовка есть ошибка:

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
4b9b3361

Ответ 1

Вы используете форвардное объявление для типа 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();
}

Ответ 2

Проблема заключается в том, что ваше свойство ui использует декларацию класса Ui::MainWindowClass, следовательно, Ошибка "неполного типа".

Включение заголовочного файла, в котором объявлен этот класс, устранит проблему.

ИЗМЕНИТЬ

На основе вашего комментария, следующий код:

namespace Ui
{
    class MainWindowClass;
}

делает НЕ объявлять класс. Это forward декларация, что означает, что класс будет существовать в какой-то момент, во время ссылки.
В основном, он просто сообщает компилятору, что тип будет существовать и что он не должен предупреждать об этом.

Но класс должен быть определен где-то.

Обратите внимание, что это может работать, только если у вас есть указатель .
Вы не можете иметь статически выделенный экземпляр неполного типа.

Итак, либо вы действительно хотите неполный тип, а затем вы должны объявить свой 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 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;
};

также будет работать.

Обратите внимание на разницу между двумя объявлениями. Сначала используется форвардная декларация, а вторая фактически объявляет класс (здесь без свойств и методов).