Hay un error en mi archivo de encabezado:
field "ui" has incomplete type.
He intentado hacer ui
un puntero, pero no funciona. No creo que deba hacer eso porque ya he definido my MainWindowClass
en el espacio de nombres Ui
. Este es mi 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
Respuestas:
Está utilizando una declaración de reenvío para el tipo
MainWindowClass
. Eso está bien, pero también significa que solo puede declarar un puntero o una referencia a ese tipo. De lo contrario, el compilador no tiene idea de cómo asignar el objeto principal, ya que no conoce el tamaño del tipo declarado hacia adelante (o si realmente tiene un constructor sin parámetros, etc.)Entonces, o quieres:
// forward declaration, details unknown class A; class B { A *a; // pointer to A, ok };
O, si no puede usar un puntero o una referencia ...
// declaration of A #include "A.h" class B { A a; // ok, declaration of A is known };
En algún momento, el compilador necesita conocer los detalles de
A
.Si solo está almacenando un puntero a,
A
entonces no necesita esos detalles cuando declaraB
. Los necesita en algún momento (siempre que elimine la referencia del punteroA
), que probablemente estará en el archivo de implementación, donde deberá incluir el encabezado que contiene la declaración de la claseA
.// 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(); }
fuente
El problema es que su
ui
propiedad usa una declaración de clase hacia adelanteUi::MainWindowClass
, de ahí el error "tipo incompleto".Incluir el archivo de encabezado en el que se declara esta clase solucionará el problema.
EDITAR
Basado en su comentario, el siguiente código:
namespace Ui { class MainWindowClass; }
no no declarar una clase. Es una declaración hacia adelante , lo que significa que la clase existirá en algún momento, en el momento del enlace.
Básicamente, solo le dice al compilador que el tipo existirá y que no debería advertir sobre él.
Pero la clase debe definirse en alguna parte .
Tenga en cuenta que esto solo puede funcionar si tiene un puntero a dicho tipo.
No puede tener una instancia asignada estáticamente de un tipo incompleto.
Entonces, o realmente desea un tipo incompleto, y luego debe declarar su
ui
miembro como un puntero: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; };
O desea una instancia de asignada estáticamente
Ui::MainWindowClass
, y luego debe declararse. Puede hacerlo en otro archivo de encabezado (generalmente, hay un archivo de encabezado por clase).Pero simplemente cambiando el código a:
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; };
también funcionará.
Note la diferencia entre las dos declaraciones. Primero usa una declaración hacia adelante, mientras que el segundo realmente declara la clase (aquí sin propiedades ni métodos).
fuente
MainWindowClass
.Ui::MainWindowClass
(variable miembro) se define enMainWindow
. No es realmente del mismo tipo.