Referenzen in abstrakten und davon abgeleiteten Klassen



  • Hallo mal wieder,

    bin gerade ziemlich gefrustet, denn so langsam aber sicher bringt mich das Referenzkonzept von C++ um! Die Sprache ist doch schon komplex und schwierig genug!

    Hatte mir folgendes überlegt:

    Eine abstrakte Basisklasse stellt wiederverwendbare Methoden für 2 Objekte zur Verfügung und bekommt dazu 2 protected Referenzen als Klassenvariablen.
    In den Konstruktoren der speziellen abgeleiteten Klassen werden diese dann initialisiert.
    Der Compiler meckert nun aber, dass in der abstrakten Basisklasse die Referenzen nicht initialisiert sind. Und er hat ja auch recht, falls man dieses in den abgeleiteten Klassen vergisst!
    Ich hatte allerdings gehofft, er erkennt, dass es sich um eine abstrakte Klasse handelt, die nicht instanziiert werden kann und prüft dann die Initialisierung nur in den abgeleiteten Klassen!
    Also die Verwendbarkeit von Referenzen scheint mir doch sehr stark eingeschränkt! Worin liegt denn der Vorteil gegenüber Zeigern?

    Hier mal etwas Bsp.-Code, vielleicht ist ja das ganze Konzept von mir nicht so glücklich:

    // Abstrakte Klasse
    #ifndef USERACTIVITY_H
    #define USERACTIVITY_H
    
    #include "ActivityC.h"
    #include "AnimObjectC.h"
    #include "PlayerC.h"
    
    class UserActivityC : public ActivityC
    {
    	public:
            UserActivityC();
            virtual ~UserActivityC() = 0;
    
        protected:
        	void changeCursorObject(const int type);
    
        private:
        	AnimObjectC& cursor;
        	PlayerC& humanPlayer;
    };
    #endif
    
    // Implementierung
    #include "UserActivityC.h"
    
    UserActivityC::UserActivityC()
    {
    }
    
    UserActivityC::~UserActivityC() {}
    
    void UserActivityC::changeCursorObject(const int type)
    {
    	cursor.setActiveAnimationType(type);
    	cursor.toggleVisible();
    }
    
    // Spezielle Klasse
    #ifndef TOWERGADGETACTIVITY_H
    #define TOWERGADGETACTIVITY_H
    
    #include "UserActivityC.h"
    #include "AnimObjectC.h"
    #include "PlayerC.h"
    
    class TowerGadgetActivityC : public UserActivityC
    {
    	public:
            TowerGadgetActivityC(AnimObjectC& cursorObject, PlayerC& human);
            ~TowerGadgetActivityC();
    
            void activate();
    };
    #endif
    
    // Implementierung
    #include "TowerGadgetActivityC.h"
    
    TowerGadgetActivityC::TowerGadgetActivityC(AnimObjectC& cursorObject, PlayerC& human) : cursor(cursorObject), humanPlayer(human)
    {
    }
    
    TowerGadgetActivityC::~TowerGadgetActivityC() {}
    
    void TowerGadgetActivityC::activate()
    {
    	changeCursorObject(GFX_TOWERCURSOR);
    }
    

    Kann ich in solchen Fällen denn nur mit Zeigern arbeiten? Oder gibt es noch andere Möglichkeiten?

    Vielen Dank schon einmal!

    Ciao



  • Auf das übliche Base/Derived-Beispiel (bin zu faul deine Klassen zu übernehmen 😛

    class Base {
        Identifier& ref;
    public:
        Base(Identifier& id)
         : ref(id)  // Elementinitialisierer notwendig
        {}
    };
    
    class Derived : public Base {
    public:
        Derived(Identifier& id)
         : Base(id)  // Basisinitialisierer notwendig
        {}
    };
    


  • Genau so hatte ich es in einer ersten Version auch. Das hat zwar mit dem Kompilieren geklappt, leider gab es zur Laufzeit Probleme!
    Bin allerdings nicht dazu gekommen rauszufinden, wieso, da ich noch keine Möglichkeit gefunden hatte zu prüfen,
    ob die Referenzvariablen überall auf die gleichen Objekte verweisen (s. mein anderer Thread dazu).

    Dann halt wieder zurück und dort den Fehler weiter suchen!



  • Das Objekt, welches du referenzierst, muss aber mindestens genauso lange leben, wie das Objekt, das die Referenz hält! Kann es sein, dass du irgendwie sowas gemacht hast?

    class DerivedUser {
        Derived d;
    public:
        void funny() {
          Identifier id;
          d = Derived(id);
        }  // hier ist id zerstört, die Referenz in Derived ungültig
    };
    

    edit:
    Beiespiel war doof, geändet 😃



  • So nun endlich mal meine Antwort.

    Mein Fehler war, dass eine Referenz keinen gültigen Wert erhalten hatte. Der Grund dafür ist, dass beim Aufruf des Konstruktors für beide Referenzvariablen jeweils ein Zeiger auf eines der Objekte in der aufrufenden Klasse dereferenziert wird.
    Nun hatte aber einer der Zeiger noch nicht auf ein gültiges Objekt gezeigt (war noch nicht angelegt). Das führte zu dem Fehler!

    Vielen Dank nochmal für eure Hilfen!


Anmelden zum Antworten