doppelt verkette Liste mit 'seltsamer Objektstruktur'



  • Hallo zusammen,

    ich hoffe Ihr könnt mir bei einem Problem weiterhelfen, dass ich mit einer Praktikumsaufgabe habe, da ich die Objektstruktur nicht ganz nachvollziehen kann.

    Eins vorweg: Die Aufgabe soll genauso gelöst werden, wie ich es beschreibe. Es wäre sicherlich einfacher die doppelt verkettete Liste anders umzusetzen, aber wenn der Prof es so will, kann ich mich sicher nicht darüber hinweg setzen ^^

    Aufgabenstellung:

    Die doppelt verkettete Liste setzt sich zusammen aus drei Klassen:

    1. Klasse DVL zur Steuerung. Hier können Elemente hinzugefügt, entfernt, verändert werden bzw. man kann sich Speicheradressen der Pointer besorgen.

    2. Klasse DVL_Elem, die die Zeiger zum vorigen bzw. nächsten Objekt enthält. Die Steuerungsklasse DVL soll auf genau diese Elemente zugreifen.

    3. Klasse Data_Elem ABGELEITET von DVL_Elem. Hier sollen die Daten enthalten sein.

    Problembeschreibung:

    Ich soll per DVL auf die DVL_Elem zugreifen, um Veränderungen an der Liste vorzunehmen. Allerdings weiss ich nicht, wie ich die einzelnen DVL_Elem mit den Data_Elem verknüpfen soll. Ich kann ja keinen Zeiger auf ein Data_Elem innerhalb von DVL_Elem erzeugen, da die Klasse dann noch nicht bekannt ist?
    Es wäre sicherlich einfacher, die Vererbung umzudrehen oder die DVL_Elem komplett wegzulassen, weil die nötigen Zeiger ja mit vererbt werden, aber das will der Prof nicht.

    In einer eMail vom Prof sagt er wortgetreu:

    Zitat:
    "der Hintergrund der Aufgabe 3 ist der Umgang mit verketteten Listen.
    Hierzu sind die beiden Klassen DVL_Elem und DVL gedacht. DVL realisiert
    eine doppelt verkettete Liste von Elementen der Klasse DVL_Elem mit
    allen erforderlichen Attributen und Methoden. Da DVL natürlich nicht
    losgelöst von Daten Sinn macht, müssen in irgend einer Form Daten damit
    verknüpft werden können. Da DVL allerdings eine allgemeine Klasse ist,
    kann sie keinerlei Daten-bezogene Methoden oder Attribute enthalten.
    Deshalb ist die Klasse Data_Elem erforderlich. Das bedeutet, die
    verkettete Liste wird ausschließlich mit DVL_Elem und DVL realisiert.
    Bei der gewünschten Anwendung müssen Sie dann gegebenenfalls mit
    Cast-Operationen die Klassen geeignet verwenden. Also ist die
    Vererbungshierarchie: class Data_Elem : ((public?)) DVL_Elem{...} richtig!"

    Allerdings verstehe ich das nicht :-(((

    Ich weiss nicht genau, wo und wann ich Objekte casten soll und wie das überhaupt gemeint ist. Ich dachte immer, dass wenn ich ein Objekt umcaste, sich auch der Speicherbedarf dafür ändert, so dass ich in Konflikt kommen könnte, wenn ich die unterschiedlich großen Objekte caste.

    Hat jemand von Euch eine Idee dazu?

    Vielen Dank im Voraus.

    Gruß,
    Aniruddha



  • Ich denke mal das DVL_Elem als so eine Art Interface gedacht ist. Jede Klasse (z.B. Data_Elem) die von diesem ableitet kann so in die Liste eingefügt werden. Du übergibst einen Pointer auf ein DVL_elem und das wird richtig eingehängt. Wenn du es wieder haben willst, bekommst du ein DVL_Elem und musst es dann auf deinen Typ casten.
    Mit templates würde das schöner gehen, aber die habt ihr wahrscheinlich noch nicht.



  • Du mußt mit Polymorphie arbeiten, dann klappt es auch so, wie dein Prof es will.

    Die Klasse DVL darf nur Zeiger auf DVL_Elem Objekte verwalten, d.h. beim Anlegen eines neuen Objektes muß dieses von extern mittels new erzeugt werden.
    Intern arbeitet die Klasse DVL dann nur mit DVL_Elem Objekten.

    Und die Klasse DVL_Data leitest du einfach (public) von DVL_Elem ab.

    So kannst du dann einfach DVL_Data Objekte in die Liste DVL einfügen, z.B.

    DVL_Data *pData = new DVL_Data(42); // Parameter entsprechend anpassen
    
    DVL dvl;
    
    dvl.Add(pData); // void DVL::Add(DVL_Elem *pElem)
    

    Ein Nachteil dieser Funktionsweise ist, daß du beim Löschen eines Elementes aus der DVL-Liste nur den Pointer löschst, d.h. der Aufrufer muß dann explizit noch mal 'delete' anwenden.

    Darum arbeitet die Klasse std::list ja auch mit eingebetteten Objekten (als Template).



  • @Aniruddha: du kannst keine Objekte "umcasten", sondern nur Zeiger auf Objekte.
    Wenn du z.B. folgenden Code hast:

    class A {};
    
    class B : public A
    {
    public:
        void test();
    };
    
    void foo(A* a)
    {
       // ...
    }
    
    void bar()
    {
        B b;
        foo(&b);
    }
    

    Hier bekommt "foo" einen Zeiger auf ein A ("A*") als Parameter übergeben. Wenn in "foo" aber bekannt ist dass dieser "Zeiger auf ein A" immer auf den "A Teil" von einem "B" zeigt, dann kann man dort den Zeiger casten, und auf den "B Teil" zugreifen:

    void foo(A* a)
    {
       // a zeigt immer auf ein B
       B* b = static_cast<B*>(a);
       b->test();
    }
    

    Das eigentliche Objekt (welches in dem Beispiel eine lokale Variable von "bar" ist) wird ja bei dem cast nicht verändert.

    Bei deiner Aufgabe ist der Fall ähnlich, du sollst die Liste ("DVL") so programmieren dass sie immer nur mit Zeigern auf "DVL_Elem" arbeitet. Natürlich kann die Liste dann auch nur Zeiger auf "DVL_Elem" zurückgeben. Wenn du daher irgendwas aus der Liste rausholen willst musst du den Zeiger entsprechend zurückcasten - du bekommst ja von der Liste nur einen DVL_Elem Zeiger, brauchst aber einen Data_Elem Zeiger damit du etwas damit anfangen kannst.


Anmelden zum Antworten