Sven_Mueller: GCC zickt scheinbar ohne Grund

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

  1. Hallo Sven,

    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  
      
    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

    1. 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