Problem mit Headern



  • Mein Dev-C++ behauptet, er kenne die Typen nicht, die ich in den Headern definiert habe.

    Ich weiß leider nicht, wo der fehler liegt, deshalb ein längerer Code:

    //main.cpp
    
    #include "main_h.hpp"
    #include <iostream>
    
    using namespace std;
    
    int main() {
      Byte b=64; //test;
    };
    
    /////////////////////////////////////
    //main_h.hpp
    
    #ifndef MAIN_H
    #define MAIN_H
    
    #include <SDL/SDL.h>
    #include "ship_h.hpp"
    #include "space_h.hpp"
    
    typedef unsigned char Byte;
    
    struct Pos {
      int x,y;
    };
    
    struct Size {
      Byte w,h;
    };
    
    #endif
    
    /////////////////////////////////////
    //sprite.cpp
    
    #include "sprite_h.hpp"
    
    void Sprite::setPos(Pos pos) {
      this->pos = pos;
    };
    
    /////////////////////////////////////
    //sprite_h.hpp
    
    #ifndef SPRITE_H
    #define SPRITE_H
    
    #include <SDL/SDL.h>
    #include "main_h.hpp"
    
    class Sprite {
      public:
        void setPos(Pos pos);
        void show();    
      private:
        Pos pos;
        SDL_Surface* bild;
    };
    
    #endif
    
    /////////////////////////////////////
    //animsprite.cpp
    
    #include "animsprite_h.hpp"
    
    Animsprite::setAnim(Byte index) {
      bild = bilder[index];
    };
    
    /////////////////////////////////////
    //animsprite_h.hpp
    
    #ifndef ANIMSPRITE_H
    #define ANIMSPRITE_H
    
    #include "sprite_h.hpp"
    #include <SDL/SDL.h>
    
    class Animsprite : public Sprite {
      public:
        void setAnim(Byte index);
      private: 
        Byte anzAnim;
        SDL_Surface** bilder;
    };
    
    #endif
    
    /////////////////////////////////////
    //ship.cpp
    
    #include "ship_h.hpp"
    
    Ship::Ship(SDL_Surface** bilder,Byte anzAnim,Byte leben,Byte speedX,Byte speedY) {
      bilder = new SDL_Surface*[anzAnim];
      this->anzAnim = anzAnim;
      this->leben = leben;
      this->dx = speedX;
      this->dy = speedY;
    };
    
    Ship::~Ship() {
      delete[] bilder;
    };
    
    void Ship::show() {
      //noch nichts
    };
    
    void Ship::move() {
      //noch nichts
    };
    
    /////////////////////////////////////
    //ship_h.hpp
    
    #ifndef SHIP_H
    #define SHIP_H
    
    #include <SDL/SDL.h>
    #include "main_h.hpp"
    #include "animsprite_h.hpp"
    
    class Ship : public Animsprite {
      public:
        Ship(SDL_Surface* bild,Byte leben,Byte speedX,Byte speedY);
        ~Ship();
        void move();
      private:
        Byte dx,dy;
        Byte leben;
    };
    
    #endif
    

    Compiler schrieb:

    9 sprite_h.hpp: variable or field setPos' declared void 9 sprite_h.hpp: expected;' before '(' token
    12 sprite_h.hpp: `Pos' does not name a type

    9 animsprite_h.hpp: variable or field setAnim' declared void 9 animsprite_h.hpp: expected;' before '(' token
    11 animsprite_h.hpp: `Byte' does not name a type

    10 ship_h.hpp: Byte' has not been declared 10 ship_h.hpp: ISO C++ forbids declaration ofleben' with no type
    10 ship_h.hpp: ISO C++ forbids declaration of speedX' with no type 10 ship_h.hpp: ISO C++ forbids declaration ofspeedY' with no type

    15 ship_h.hpp: `Byte' does not name a type //Doch!!! 😕



  • Soll ich die Frage anders formulieren?

    Generell:
    Brauchen normale .cpp Dateien haben nur ein #include, weil alle anderen in den Header reinkommen,
    oder
    muss ich in jeder Datei alle Header einbinden, von denen ich die Typen/Klassen in gerade dieser Datei brauche?

    Der Fehler liegt höchstwarscheinlich bei irgend etwas, was mit einem "#" markiert ist. Das schränkt die Suche doch schon mal ein.



  • Dein Problem ist, daß sich die Header gegenseitig einbinden - "main_h.hpp" inkludiert "ship_h.hpp" und "space_h.hpp", diese verwenden wiederum die "main_h.hpp". Durch die Art, wie der Präprozessor sich durch diese #includes (und die Include-Guards) hangelt, kommt dann womöglich die Reihenfolge der Deklarationen durcheinander, so daß z.B. der Typedef von 'Pos' erst hinter der Sprite-Klasse landet. Diese zyklischen Abhängigkeiten mußt du auf jeden Fall aufbrechen - mitunter reicht es, einige überflüssige #includes aus den Headern in die .CPP Files zu verlagern, im Extremfall helfen nur Forward-Deklarationen.

    (PS: Ans Ende einer Funktionsdefinition kommt kein Semikolon)



  • Danke, das hat mir schon weitergeholfen.

    Ich habe den Verdacht, dass ich in abgeleiteten Klassen keine privaten Attribute der "Mutterklasse" benutzen kann. Was für einen Sichtbarkeitsbereich benutze ich denn dann?

    Protectet. Google war schneller. 😉

    Nochwas: Ich möchte, dass jedes Sprite die Funktion "show" hat, die Implementierung aber von der "Endklasse" abhängt. Der Compiler meckert, dass ship keine show methode hätte, hat es aber, weil es ja auf Umwegen auch ein Sprite ist.
    Wie mach ich dem das Klar?



  • Deine Objekte sind überhaupt nicht polymorph. Mach mal wenigstens den Sprite-Dtor virtual:

    class Sprite {
      public:
        void setPos(Pos pos);
        void show();    
        virtual ~Sprite()
        {
           // leer
        }
      private:
        Pos pos;
        SDL_Surface* bild;
    };
    


  • Hmm du zwingst den dazu dir ne Fehlermeldung zu bringe, wenn du eine reinvirtuelle Funktion hast und du sie in der abgeleiteten Klasse nicht implementiert hast. Mit einer virtuellen Funktion kannst du sie überschreiben ..

    class human 
    {
    public:
        virtual bool run(void) = 0;
        virtual bool sing(void); 
    };
    
    class child : public human
    {
    public:
        bool say(const std::string&);    
    
    public:
        // virtual bool run(void) {} // Wenn du "run" rauslässt, bekommst du ne Fehlermeldung ;)
        // Wenn du "sing" rauslässt wird die Funktion der Basisklasse genommen ...
    };
    


  • OK 👍

    undefined reference to `vtable for sprite´

    Was könnte das bedeuten?



  • Halleluja!
    Alles Klar.
    Der Thread kann gelöscht werden.


Anmelden zum Antworten