Vererbung und ein merkwürdiger Fehler



  • Hallo !

    Könnte sich das vielleicht jemand anschaun ? 🙂

    Ich versuche eine Klasse von einer anderen erben zu lassen und dann Objekte beider Klassen zu erzeugen.

    Die Basisklasse:

    #include <string.h>
    
    class Fahrzeug
    {
    	public:
    		Fahrzeug(int age, int performance);
    		~Fahrzeug();
    
    	private:
    		int age;
    		int performance;
    };
    

    Der Konstruktor dazu sieht dann so aus:

    Fahrzeug::Fahrzeug(int age_in, int performance_in)
    {
    	age = age_in;
    	performance = performance_in;
    }
    

    Die davon abgeleitete Klasse:

    #include <string.h>
    #include "Fahrzeug.h"
    
    class PKW : public Fahrzeug
    {
    	public:
    		PKW(int age, int performance,int seat,bool child_carrier);
    		~PKW();
    
    		void set_child_carrier(bool x);
    
    	private:
    		int seat;
    		bool child_carrier;
    };
    

    und der Konstruktor der abgeleiteten Klasse:

    PKW::PKW(int age_in, int performance_in, int seat_in, bool child_carrier_in) 
    	: Fahrzeug(age_in,performance_in)
    {
    	seat = seat_in;
    	child_carrier = child_carrier_in;
    }
    

    Die Fehlermeldung die ich erhalte lautet:

    fahrzeug.h(4) : error C2011: 'Fahrzeug' : 'class'-Typ-Neudefinition

    Zeile vier ist bei mir die geschwungene Klammer direkt unter dem Klassennamen....ich bin ratlos 😞



  • Gawan schrieb:

    Könnte sich das vielleicht jemand anschaun ? 🙂

    Nein, Ich lese den Beitrag nicht ja gerade nicht. 🤡

    PKW(int age, int performance,int seat,bool child_carrier);
    

    ➡ ⚠

    PKW::PKW(int age_in, int performance_in, int seat_in, bool child_carrier_in) ...
    

    🙄

    Man sollte beides mal auch die gleichen Parameter Bezeichner verwenden oder sie beim ersten mal weg lassen



  • Ich dachte ich kann die im Konstruktor nennen wie ich will solange die Datentypen übereinstimmen ?

    edit: ich hab jetzt alle Namen gleichgesetzt - das Problem hab ich aber noch immer 🙂



  • Gawan schrieb:

    fahrzeug.h(4) : error C2011: 'Fahrzeug' : 'class'-Typ-Neudefinition

    Zeile vier ist bei mir die geschwungene Klammer direkt unter dem Klassennamen.

    Hast du Include-Guards in Fahrzeug.h?



  • da ich nicht weiß was das ist sag ich einfach mal: nein 🙂



  • ICh weis nicht ob das der fehlr ist, aber villeicht wäre ein virtueller Destruktor in der Superklasse sinnvoll



  • ich habe ja einen Destruktor in der Fahrzeug-Klasse:

    ~Fahrzeug();



  • Gawan schrieb:

    da ich nicht weiß was das ist sag ich einfach mal: nein 🙂

    Das ist ein Gerüst um den Inhalt von Headerdateien, der verhindert, dass dieselbe Headerdatei mehrfach in eine Übersetzungseinheit eingebunden wird.

    Sieht in etwa so aus:

    #ifndef EINDEUTIGES_DEFINE_FUER_DIESE_HEADERDATEI
    #define EINDEUTIGES_DEFINE_FUER_DIESE_HEADERDATEI
    
    // Hier der Inhalt der Headerdatei
    
    #endif
    

    Manche Compiler bieten einfachere Mechanismen an, z.B. ein einzelnes #pragma once am Anfang der Datei (MSVC).



  • Gawan schrieb:

    ich habe ja einen Destruktor in der Fahrzeug-Klasse:

    ~Fahrzeug();

    Er meint das du virtual davor schreiben sollst ( in der deklaration )



  • egal wo ich virtual davorschreibe - der Fehler bleibt unverändert - und zwar nur wenn ich bei meinen includes

    #include <iostream>
    #include <vector> 
    #include <string.h>
    #include "Fahrzeug.h";
    //#include "PKW.h";
    

    den PKW mit hineinnehme - wenn er draußen bleibt läufts

    kann es damit zusammenhängen dass ich in der Oberklasse Methoden habe und die in der Unterklasse nicht auf irgendeine Art und Weise behandle ?



  • Gawan schrieb:

    egal wo ich virtual davorschreibe - der Fehler bleibt unverändert - und zwar nur wenn ich bei meinen includes

    den PKW mit hineinnehme - wenn er draußen bleibt läufts

    Lass mich raten: In PKW.h steht #include "Fahrzeug.h"?

    Dann fehlen dir die Include-Guards in Fahrzeug.h. In deinen anderen Headerdateien vermutlich auch, aber da hat es sich noch nicht bemerkbar gemacht.



  • ja - damit hast du in beiden Fällen recht 🙂

    Setze ich diese include-Guards dann um das gesamte H-File, um die Definitionen oder nur um die includes ?

    Also Variante 1:

    #ifndef DEF 
    #define DEF 
    
    #include <string.h>
    #include "Fahrzeug.h"
    
    class PKW : public Fahrzeug
    {
    	public:
    		PKW(int age, int performance,int seat,bool child_carrier);
    		~PKW();
    
    		void set_child_carrier(bool x);
    
    	private:
    		int seat;
    		bool child_carrier;
    };
    
    #endif
    

    Variante 2:

    #ifndef DEF 
    #define DEF 
    
    #include <string.h>
    #include "Fahrzeug.h"
    
    #endif
    
    class PKW : public Fahrzeug
    {
    	public:
    		PKW(int age, int performance,int seat,bool child_carrier);
    		~PKW();
    
    		void set_child_carrier(bool x);
    
    	private:
    		int seat;
    		bool child_carrier;
    };
    

    oder Variante 3:

    #include <string.h>
    #include "Fahrzeug.h"
    
    #ifndef DEF 
    #define DEF 
    
    class PKW : public Fahrzeug
    {
    	public:
    		PKW(int age, int performance,int seat,bool child_carrier);
    		~PKW();
    
    		void set_child_carrier(bool x);
    
    	private:
    		int seat;
    		bool child_carrier;
    };
    
    #endif
    


  • Variante 1, um die gesamte Datei. DEF ist allerdings ein ziemlich schlechter Name. Das ist sehr kurz und nicht eindeutig auf diese Datei bezogen, könnte also schon an anderer Stelle benutzt worden sein. Häufig sieht man so etwas:

    #ifndef DEINPROJEKT_PKW_H_INCLUDED
    


  • super - das läuft jetzt 🙂

    gehört diese Klammerung um jedes H-File oder nur um die Superklassen ?

    Den Nutzen hab ich nämlich noch nicht ganz verstanden 🙂



  • Gawan schrieb:

    super - das läuft jetzt 🙂

    Schön 🙂

    gehört diese Klammerung um jedes H-File oder nur um die Superklassen ?

    Man braucht sie nicht überall, aber sie schadet nicht. Ob man sie braucht, hängt aber nicht vom Inhalt der Headerdatei ab, sondern von der Struktur der #include-Direktiven.

    Den Nutzen hab ich nämlich noch nicht ganz verstanden 🙂

    Ich mal's mal auf 😉

    Eine Datei, nennen wir sie mal main.cpp wird kompiliert. Da drin steht:

    #include "Fahrzeug.h"
    #include "PKW.h"

    An die Stelle dieser Direktiven setzt der Präprozessor den Inhalt dieser Dateien. In PKW.h steht wieder

    #include "Fahrzeug.h"

    Auch das wird durch den Inhalt von Fahrzeug.h ersetzt. Dadurch steht der Inhalt von Fahrzeug.h zweimal in der Datei, die der Compiler jetzt zu Fressen bekommt. Und was sieht der?

    class Fahrzeug
    {
    };
    
    // später
    
    class Fahrzeug
    {
    };
    

    Das mag er nicht. Er beschwert sich über eine Redefinition der Klasse Fahrzeug.

    Mit den Include-Guards sieht das ganze so aus:

    #ifndef FAHRZEUG_H_INCLUDED 
    #define FAHRZEUG_H_INCLUDED
    class Fahrzeug
    {
    };
    #endif
    
    // später
    
    #ifndef FAHRZEUG_H_INCLUDED
    #define FAHRZEUG_H_INCLUDED
    class Fahrzeug
    {
    };
    #endif
    

    Ein Block, der zwischen #ifndef und #endif steht, wird komplett ausgeblendet, wenn das betreffende Symbol definiert ist. Das passiert im ersten Block. Im zweiten Block ist FAHRZEUG_H_INCLUDED bereits definiert, darum wird der zweite Block ausgeblendet. Weg ist die Mehrfachdefinition, und der Compiler ist zufrieden.



  • ah...habs scheinbar verstanden :):)

    der Compiler merkt sich alle Include_Guards und wenn schon mal einer verarbeitet wurde lässt er den bei einem eventuellen weiteren Auftreten links liegen 😃

    Danke !



  • Hat mir echt sehr geholfen, danke! 🙂 🙂 🙂 🙂 🙂
    Egal obs schon n paar Jahre her ist. 🙂


Log in to reply