GCC zickt scheinbar ohne Grund
Sven_Mueller
- programmiertechnik
Hei,
also ich habe ein Programm das noch in den Startlöchern steckt.
Dabei gibt es eine Klasse und eine Funktion. Diese Funktion Instanziert ein Objekt der Klasse und genau das Klappt nicht.
class KlasseA
{
private:
// Membervariablen
public:
KlasseA(){}
~KlasseA() {]
// Methoden
};
// woanders im code
void FunktionA(void)
{
/*#*/ KlasseA Objekt; // hier soll der Fehler sein
}
Die # Zeile im Code erzeugt folgende Fehlermeldung:
|Datei|:|Zeile|: Fehler: Aggregat »KlasseA Objekt« hat unvollständigen Typ und kann nicht definiert werden
[sh@bash ~]# rpm -qa | grep gcc
libgcc-4.1.2-27.fc7
gcc-c++-4.1.2-27.fc7
gcc-objc++-4.1.2-27.fc7
gcc-4.1.2-27.fc7
gcc-objc-4.1.2-27.fc7
Wo liegt der Fehler? Was mach ich falsch?
Wenn ihr noch irgendwelche Infos braucht sagts einfach. Bin mir sicher das ich nicht alles gesagt habe was wichtig sein könnte.
Mit Google finde ich einfach gar nichts.
Sven Mueller
Hallo Sven,
class KlasseA
{
private:
// Membervariablen
public:
KlasseA(){}
~KlasseA() {]
// Methoden
};
// woanders im codevoid FunktionA(void)
{
/#/ KlasseA Objekt; // hier soll der Fehler sein
}
> Die # Zeile im Code erzeugt folgende Fehlermeldung:
> |Datei|:|Zeile|: Fehler: Aggregat »KlasseA Objekt« hat unvollständigen Typ und kann nicht definiert werden
Dein Code selbst verursacht diesen Fehler nicht (mal abgesehen von der falschen Klammer beim Destruktor). Allerdings vermute ich, dass Dein Problem daran liegt: Du definierst die Klasse vmtl. erst NACH der Funktion vollständig, bspw so:
~~~c++
class KlasseA;
void FunktionA(void) {
KlasseA Objekt;
}
class KlasseA {
private:
// Membervariablen
public:
KlasseA(){}
~KlasseA() {}
// Methoden
};
Das "Klasse erst nach Verwendung vollständig deklarieren" funktioniert nur bei Funktionsprototypen und Typdefinitionen, NICHT jedoch bei Funktionskörpern!
Beispielsweise fliegt folgendes genauso auf die Schnauze:
class KlasseA;
void FunktionA(KlasseA Objekt) {
// tu was
}
class KlasseA {
private:
// Membervariablen
public:
KlasseA(){}
~KlasseA() {}
// Methoden
};
Folgendes funktioniert dagegen:
class KlasseA;
void FunktionA(KlasseA Objekt);
class KlasseA {
private:
// Membervariablen
public:
KlasseA(){}
~KlasseA() {}
// Methoden
};
void FunktionA(KlasseA Objekt) {
// tu was
}
Nachdem Du die Klasse vmtl. in Header-Dateien separat definierst, wäre halt in diesem Fall zu überprüfen, in welcher Reihenfolge Deine Header-Dateien wo #includet werden. Um herauszufinden, was NACH dem Präprozessor (der die Includes behandelt) tatsächlich beim eigentlichen Compiler ankommt, kannst Du -E verwenden:
g++ -E -o datei.ii datei.cxx
Dann ist in datei.ii eine zusammengefügte C++-Datei, bei der schon alle Includes und Präprozessormakros ausgeführt wurden (was aber z.B. bei #include <iostream> schnell sehr unübersichtlich wird).
Mit Google finde ich einfach gar nichts.
Die deutschen Fehlermeldungen sind auch vmtl. nirngedwo wirklich dokumentiert. Du kannst jedoch auch eine englische Fehlermeldung forcieren, indem Du die Lokalisierung deaktivierst:
christian@cobalt ~/tmp/self $ LC_ALL=C g++ -Wall -c -o sm1.o sm1.cxx
sm1.cxx: In function 'void FunktionA()':
sm1.cxx:4: error: aggregate 'KlasseA Objekt' has incomplete type and cannot be defined
sm1.cxx:4: warning: unused variable 'Objekt'
Allerdings muss ich zugeben, dass beim ersten Überblicken die ersten paar Google-Suchergebnissse zu der englischen Fehlermeldung auch nicht sonderlich hilfreich sind...
Viele Grüße,
Christian
Hallo Christian,
Dein Code selbst verursacht diesen Fehler nicht (mal abgesehen von der falschen Klammer beim Destruktor).
Ja das war wohl ein Tippfehler ...
Ja also deine Antwort ist/war perfekt, du hast mir alles beantwortet was ich nicht wusste bzw. wissen wollte. Du hast auch erraten wie mein Code aufgebaut ist. Ja es ist genau so wie du es gesagt hast:
class KlasseA;
void FunktionA(KlasseA Objekt) {
// tu was
}class KlasseA {
private:
// Membervariablen
public:
KlasseA(){}
~KlasseA() {}
// Methoden
};
Ich hab das jetzt abgeändert. Damit das nicht noch einmal passiert habe ich gleich die #include-Reihenfolge und ein paar Inhalte von Dateien geändert.
> Die deutschen Fehlermeldungen sind auch vmtl. nirngedwo wirklich dokumentiert. Du kannst jedoch auch eine englische Fehlermeldung forcieren, indem Du die Lokalisierung deaktivierst:
>
> christian@cobalt ~/tmp/self $ LC\_ALL=C g++ -Wall -c -o sm1.o sm1.cxx
Ich werde das mal in betracht ziehen falls ich mal wieder Gelegenheit dazu habe.
Vielen Dank Christian.
Sven Mueller