“필드에 불완전한 유형이 있습니다”오류 : public QMainWindow { Q_OBJECT

내 헤더 파일에 오류가 있습니다.

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


답변

유형에 대해 앞으로 선언을 사용하고 있습니다 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();
}

답변

문제는 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;
};

또한 작동합니다.

두 선언의 차이점에 유의하십시오. 첫 번째는 정방향 선언을 사용하고 두 번째는 실제로 클래스를 선언합니다 (여기서는 속성이나 메서드가 없음).