Hallo C++ler,
ich schreibe gerade ein Programm, das aus einer GUI "MainWindow" und
einer Datenverarbeitung "Core" besteht.
Ansich funktioniert alles, allerdings muss ich im Header von Core jede
verwendete Klasse vorwärtsdeklarieren.
Das finde ich äußerst merkwürdig, umständlich und vor allem hässlich :D
Tue ich das nicht, wird die Fehlermeldung "ISO C++ forbids declaration
of 'SerialTransmitter' with no type" ausgegeben.
Warum auch immer, wird also die Klasse nicht durch den Header
deklariert.
Könnt ihr mir weiter helfen, was habe ich übersehen?
Das Problem trat erst auf, seit ich mein Programm in GUI und Core
gesplittet hatte.
Irgendwie habe ich das Gefühl es hängt mit dem Namespace zusammen.
Gruß und Dank
Flo
main.cpp
1
#include<QApplication>
2
3
#include"core.h"
4
#include"mainwindow.h"
5
6
intmain(intargc,char*argv[])
7
{
8
QApplicationgui(argc,argv);
9
10
Core*theCore=newCore();
11
MainWindow*theMainWindow=newMainWindow(theCore);
12
theMainWindow->show();
13
14
returngui.exec();
15
}
Hier muss ich alle verwendeten Klassen vorwärtsdeklarieren, hier zwei
Beispielklassen:
core.h
Frage: passiert das auch, wenn main.cpp compiliert wird? Außerdem
vermisse ich ein "#include <QObject>" in core.h, denn woher soll der
Compiler wissen, was ein QObject ist?
Hallo radiostar,
Tatsache, QObject war nicht importiert, Danke für den Hinweis.
Dennoch funktioniert es nicht ohne Vorwärtsdefinitionen ...
Hallo Rufus,
hier SerialTransmitter:
serialtransmitter.h
Das ist merkwürdig. In serialtransmitter.h ist die Klasse deklariert,
und nach dem Einbinden davon verwendest Du nochmal eine
"Vorwärts"deklaration?
Was soll das?
Hallo Rufus,
mir kommt es genauso spanisch vor wie Dir!
Ohne die "Vorwärts"deklaration nach dem Einbinden des Headers compiliert
er nicht: "ISO C++ forbids declaration of 'myUglyClass' with no type"
Ich muss alle Klassen hinter Core nach"vorwärts"deklarieren, in
MainWindow funktioniert alles, wie es soll ...
Flo schrieb:> serialtransmitter.h:> #ifndef SERIALPORT_H> #define SERIALPORT_H
Der Include-Guard entspricht nicht dem Dateinamen. Gibt es evtl. mehrere
Dateien, die dank Copy/Paste SERIALPORT_H #definen?
Mit
#pragma once
wäre das nicht passiert.
Hallo Malte und Chris,
ihr habt Relikte aus der alten Namensgebung gefunden ;)
Das war aber leider auch nicht der ausschlaggebende Fehler ... :(
Trotzdem Danke!
Vielleicht gerade noch einmal eine etwas ausführlichere
Fehlerbeschreibung:
Wenn ich in core.h die "Vorwärts"deklaration "class SerialTransmitter;"
auskommentiere, erhalte ich genau folgende Ausgaben des Compilers:
In file included from serialtransmitter.h - serialtransmitter.h
from serialtransmitter.cpp - serialtransmitter.cpp
(!) ISO C++ forbids declaration of 'SerialTransmitter' with no type -
core.h
(!) expected ';' before '*' token - core.h
in SerialTransmitter hast Du eine Variable vom Typ Core und in Core eine
Variable vom Typ SerialTransmitter. Das kann nicht ohne
Vorwärtsdeklaration funktionieren, denn eine der beiden Klassen muß ja
zuerst definiert werden.
radiostar schrieb:> in SerialTransmitter hast Du eine Variable vom Typ Core und in Core eine> Variable vom Typ SerialTransmitter. Das kann nicht ohne> Vorwärtsdeklaration funktionieren, denn eine der beiden Klassen muß ja> zuerst definiert werden.
Ja, aber es reicht, eine der Klassen vorwärts zu deklarieren. Und eine
"Vorwärts"deklaration nach einbinden des Headers ist merkwürdig...
Aber klar:
Das #include "core.h" muss aus serialtransmitter.h raus oder das
#include "serialtransmitter.h" aus core.h und die jeweils andere Klasse
muss dann vorwärsdeklariert werden.
Den dazugehörigen Header dann nur in der .cpp-Datei einbinden.
Malte S. schrieb:> Ja, aber es reicht, eine der Klassen vorwärts zu deklarieren. Und eine> "Vorwärts"deklaration nach einbinden des Headers ist merkwürdig...
Das liegt an der Art, wie die header inkludiert werden:
core.h bindet serialtransmitter.h ein, das bindet core.h ein. Das aber
funktioniert nicht, weil CORE_H schon definiert ist. Also bleibt die
Klasse Core undefiniert in serialtransmitter.h. Eigentlich ganz logisch.
radiostar schrieb:> Malte S. schrieb:>> Ja, aber es reicht, eine der Klassen vorwärts zu deklarieren. Und eine>> "Vorwärts"deklaration nach einbinden des Headers ist merkwürdig...>> Das liegt an der Art, wie die header inkludiert werden:>> core.h bindet serialtransmitter.h ein, das bindet core.h ein. Das aber> funktioniert nicht, weil CORE_H schon definiert ist. Also bleibt die> Klasse Core undefiniert in serialtransmitter.h. Eigentlich ganz logisch.
Sag ich doch :)
Gegenseitiges #include ist schlecht fürs Karma.
a.h:
1
#pragma once
2
3
classB;
4
5
classA{
6
A();
7
B*myB;
8
};
b.h:
1
#pramga once
2
3
#include"a.h"
4
5
classB{
6
B();
7
A*myA;
8
};
a.cpp:
1
#include"a.h"
2
#include"b.h"
3
4
A::A()
5
:myB(newB()){
6
}
b.cpp:
1
#include"b.h"
2
3
B::B()
4
:myA(newA()){
5
}
Abgesehen vom entstehenden Speicherleck und minus Tipp- und sonstigen
Fehlern sollte das zeigen, wie du die Abhängigkeiten auflösen kannst.
* In a.h ist kein #include "b.h"
* Also darf die Klasse B im Header a.h auch nur als Zeiger oder Referenz
auftauchen.
Auch eine Variante.
Da halte ich wiederum dagegen, dass die Vorwärtsdeklaration sonst ja das
#include ersetzt und dadurch auch dokumentiert, dass eben nur
vorwärtsdeklariert wurde mit allen Einschränkungen, die das bringt. Bei
einem gegenseitigen #include mit magischen Vorwärtsdeklarationen wird
das versteckt.
Geschmackssache.
Ich mache eigentlich immer nur dann ein #include, wenn es dort auch
wirklich nötig ist. Wenn für ein File eine Vorwärtsdeklaration reicht,
mache ich nur die. Macht Qt selbst übrigens intern auch so. Das hält den
Rattenschwanz an inkludierten Headern kürzer, und die Probleme mit
zyklischen Abhängigkeiten ergeben sich gar nicht erst.