error: ISO C++ forbids declaration of 'xyz' with no type
-
Hallo,
EditorGUI ist recht lang (leider), besteht aus einer header und einer Implementierungsdatei.Das ist die Implementierungsdatei (ich habe mir schon gedacht, vllt liegt es an der Quervernkuepfung mit den includes, aber es aendert sich kaum was bei weglassen, hinzufuegen oder sonstigen Aenderungen.
#ifndef EDITORGUI #define EDITORGUI #include "MainGUI.hpp" #include "PnOption.hpp" #include "PnOptionCommon.hpp" #include "PnOptionNoun.hpp" #include "PnOptionVerb.hpp" #include "PnOptionAdjective.hpp" #include "Element.hpp" #include <iostream> // TODO rm class QDialog; class QVector<class T>; class QLabel; class QLineEdit; class QPushButton; class QRadioButton; class QStackedLayout; class EditorGUI : public QDialog { Q_OBJECT public: EditorGUI( MainGUI*, QVector<Element>* list=new QVector<Element>()); ~EditorGUI(); QVector<Element>* editableSelection(){ return pEditableSelection; }; Element* getElementCopy(){ return pElemCpy; }; void actualizeElement(); private slots: // buttons void slotNewWord(); void slotReset(); void slotAccept(); void slotEditWord(); void slotDeleteItem(); void slotCancel(){ reject(); }; // listWidget void slotSelect(){ init(listWidget->currentRow()); }; // radiobuttons void slotChangeToCommon(); void slotChangeToNoun(); void slotChangeToVerb(); void slotChangeToAdjective(); private: const quint16 NUMBER_OF_TYPES; MainGUI* pnParent; QVector<Element>* pEditableSelection; QListWidget* listWidget; Element* pElemCpy; QStackedLayout* staOptions; PnOption* pnCurrentOption; PnOptionCommon* pnOptionCommon; PnOptionNoun* pnOptionNoun; PnOptionVerb* pnOptionVerb; PnOptionAdjective* pnOptionAdjective; QLabel* lbTranslation; QLineEdit* leTranslation; QLabel* lbTranslationContext; QLineEdit* leTranslationContext; QLabel* lbWord; QLineEdit* leWord; QLabel* lbWordContext; QLineEdit* leWordContext; QPushButton *btNew; QPushButton *btReset; QPushButton *btCancel; QPushButton *btOk; QPushButton *btEdit; QPushButton *btDelete; QRadioButton* rb; void initGUI(); void init(qint16); void populateListWidget(); void readElem(const Element& element); void writeElem(Element* element); }; #endifDie Implementierung enthaelt folgende Includierungen:
#include <QtGui> #include "EditorGUI.hpp" #include <iostream> // TODO rm (...)Ich bin fuer jeden Tipp, was ich machen koennte oder Vermutung dankbar!!!
PS:
EditorGUI erzeugt eine Instanz einer abgeleiteten Klasse von PnOption. Das Parent dieser PnOption Ableitungen soll die Instanz von EditorGUI sein - auf diese soll auch jeweils der Zeiger (=pParent) dann zeigen (aber soweit kommt das Ding ja noch lange nich).
-
hi Fabeltier
Fabeltier schrieb:
Hallo,
EditorGUI* pParent; // wird nicht erkannt!!!
[/code]Diese Deklaration sagt nur, dass pParent auf etwas zeigen soll, was ein EditorGUI ist. Insbesondere wird der Konstruktor der Klasse nicht aufgerufen. (Aber das weist du bestimmt.)
Erst wenn du so etwas hast wie
EditorGUI etc; pParent = &etc;funktionierts. Vielleicht erklärt das, warum EditorGUI* pParent nicht erkannt wird.
Muss dann in void setParent(EditorGUI* p){ pParent = p; }; nicht auch & anstelle * stehen? Aufruf: setParent(*p).
vg tesu
-
@tesuji was hat dein Beitrag mit dem Thema zu tun?
class Foo; class Blaa { Foo* foo; }Das muss doch funktionieren.
Was macht den dieses Q_OBJECT Macro? Macros sind böse, böse, böööse
btw, verwendet doch die cpp-Tags.
PnOption.hpp:76: error: 'EditorGUI' has not been declared
Das lässt vermuten das der Compiler den EditorGUI-Typ nicht kennt.
Ausserdem hast du eine zyklische Referenz, in PnOption.hpp includest du EditorGUI.hpp und in EditorGUI.hpp includest du PnOption.hpp:
#include "Element.hpp" #include "EditorGUI.hpp" // hier#include "MainGUI.hpp" #include "PnOption.hpp" // hier #include "PnOptionCommon.hpp" #include "PnOptionNoun.hpp" #include "PnOptionVerb.hpp" #include "PnOptionAdjective.hpp" #include "Element.hpp" #include <iostream> // TODO rmIch weis nicht ob das Probleme bereitet, hab schon lang kein C++ Projekt geschrieben.
-
Die zyklischen includes sollten kein Problem darstellen, wenn:
- die Includes nicht nötig sind um Klassen bekannt zu machen
- du Include-Guards benutzt, was du scheinbar auch tust (#ifndef bla #define bla etv.)In diesem Fall scheints aber so zu sein, dass der erste Punkt zutrifft:
wenn der Compiler versucht, einen header zu lesen, der editorgui.h includiert, steht für ihn da in etwa folgendes:
... #include editorgui.h // hier packt der compiler den text von editorgui.h: #ifndef editorgui #define editorgui // editorgui ist damit DEFINIERT! #include pnoption.h // hier dann der text von pnoption.h #ifndef pnoption #define pnoption #include editorgui // ah, hier nochmal editorgui #ifndef editorgui // hier tut der includeguard was er soll, editorgui ist definiert //wird also übersprungen und NICHT gelesen! #endif //ende von editorgui ... Editorgui* pParent; //!!!! EDITORGUI ist hier UNBEKANNT! #endif //ende von pnoption class Editorgui {...}; //hier wird die Klasse erst bekannt... #endif //ende von editorguium sowas zu verhindern, gibts zwei wege:
- wenn du nur Zeiger auf eine Klasse hast und keine ihrer Methoden oder Membervariablen verwendest, ist es nicht nötig, dass der Compiler zu dem Zeitpunkt die ganze definition kennt. eine Deklaration
class EditorGUI;reint. die eigentliche Definition kann irgendwann anders kommen.
2) Damit bei den Kreisincludes soclhe fehler nicht passieren, kann man am Anfang jeden headers einfach dei KLasse kurz deklarieren, dann die Includes, dann die eigentliche KLassendefinition.Allerdings halte ich es für nicht besonders schönen Stil, header nur zur Klassendeklaration zu includieren, da dem Compiler dann mehr Quelltext zugemutet wird als nötig.
-
Hallo und Danke fuer die Beitraege an alle!!!!
@tesuji
Ja mir ist schon klar wie man Zeiger initialisiert, darum ging es aber in der Tat nicht. Man denkt vllt zuerst bei der Fehlermeldung an andere Dinge - ich dachte eben an einen vergessenen ; oder ) in einem includeten File, da ich sowas schon hatte - schliesslich wird man langsam wahnsinnig, weil man nichts findet und kontrolliert alles (auch die Initialisierungen) nochmal. Danke trotzdem
@DEvent:
Q_OBJECT Macro - Ich selber arbeite aesserst ungerne mit Macros, auch nicht um Code (etwa template Deklarationen) zu "verkuerzen". Das Macro ist notwendig fuer den Signal/Slot-Mechanismus bei Qt, einer Qt-eigenen Signalsteuerung fuer v.a. die GUI's.
Die "zyklische Referenz" bei den Includes ging voll in die richtige Richtung. Auch hier hatte ich schon einiges ausprobiert mit meinem Halbwissen, allerdings erfolglos.@pumuckl:
Die Erlaeuterung hat das Problem schliesslich geloest. Mir war gaenzlich unklar was eig der Unterschied zwischen einer #include Anweisung und einer (seichten) Forward Declaration eig ist. In diese Falle bin ich hineingetappt. Nun hab ich die EditorGUI.hpp, EditorGUI.cpp und PnOption.hpp noch einmal gruendlich angepasst, je nachdem, was im .hpp nicht benoetigt wurde (ausser als Pointer) laeuft und per Forward Declaration. Damit kompilierte es dann auch durch - WOW!
Es stellt sich allerdings doch etwas die Frage, bei mir, ob man sowas nicht eig auch mit Praeprozessoranweisungen loesen koennte (auch wenn das vllt etwas exotisch klingt, aber dafuer sind die doch eig auch da, oder?)?
-
Man kann auch eine "fwd.hpp" machen wo man forward declarations für alle Klassen und Strukturen reinpackt.
Wenn man in irgendeinem Headerfile dann irgendwelche forward declarations includiert man an der Stelle einfach "fwd.hpp".Macht die Headerfiles u.U. einiges kürzer und übersichtlicher.
Ich mache es immer so dass jede Library ein "common.hpp" bekommt, und "common.hpp" inkludiert irgendwo "fwd.hpp" oder enthält selbst die ganzen forward declarations.
Jedes andere Headerfile der Library inkludiert dann als erstes "common.h".Dadurch ist das Problem mit forward declarations darauf reduziert dass man bei neuen Klassen daran denken muss diese in "fwd.hpp" einzutragen.
Bei grösseren Libraries gibt es u.U. mehrere common.hpp und/oder fwd.hpp, z.B. eines pro grösserem Namespace.
-
Das kann man aber nur in kleinen Projekten machen. Wenn ich zum kompilieren 2 Stunden brauche nur weil ich eine forward decl. dazugefügt habe werde ich die Deklaration doch in mein eigenes headerfile schreiben
-
Forward-Deklarationen verlängern doch die Compilezeit nicht.
-
Forward-Deklarationen verlängern doch die Compilezeit nicht.
Doch, so wie templäd es beschrieben hat, und darauf bezieht sich ja hustbaer, d.h. wenn man in die common.h bzw. fwd.h eine neue Klasse (egal ob als Forward Deklaration oder nicht) einträgt, dann wird das ganze Projekt neucompiliert (wäre wie beim MSVC Einträge in der stdafx.h zu ändern)...
-
Nun gut, das ist richtig.
Header die in allen Projektdateien eingetragen sind sollten halt nicht oft geändert werden.