[gelöst]Problem mit Verschattung



  • In meiner Windows-IDE Dev-C++ stürzt mein Programm immer wieder ab ohne das der Compiler was dazu sagt.

    template <class T> class slistElement
    {
      private:
        T data;
        slistElement<T>* next;
    
      public:
        slistElement(T wert)
        {
             data = wert;
             next = NULL;
        }
        T getData()
        {
             return data;
        }
        void setData(T data)
        {
             this->data = data;
        }
    
        slistElement<T>* getNext()
        {
             return next;
        }
        void setNext(slistElement<T>* next)
        {
             this->next = next;
        }
    };
    

    Ich hab den Fehler soweit eingegrenzt das es an diesem "this" in Zeile 19 und 28 liegen muss, aber ich weiß nicht wie ich es beheben kann. This ist bisher das einzige was wir gelernt haben um mit Verschattung umzugehen und Google liefert Solarenergielösungen 😡

    Hat jemand eine Idee warum das nicht funktioniert und wie man das beheben kann?

    EDIT: Ich darf die Namen alle nicht ändern, also ich komm nicht um die Verschattung drum rum.



  • benny111 schrieb:

    Dev-C++

    Dev-C++ ist veraltet

    benny111 schrieb:

    Ich hab den Fehler soweit eingegrenzt das es an diesem "this" in Zeile 19 und 28 liegen muss, aber ich weiß nicht wie ich es beheben kann.

    Dann kann ich nur raten, das du einen uninitialisierten Zeiger auf ein solches Element verwendest (this daher ungültig ist). Der Begriff "Verschattung" ist mir übrigens noch nie über den Weg gelaufen.

    P.S: Zudem bitte in Zukunft statt den code-Tags die cpp-Tags verwenden (Button "C/C++").



  • Das mit der Verschattung haste doch gut gelöst.
    Das Prog stürzt wohl aus anderen Gründen ab.
    Vielleicht im Konstruktor der Liste den anker nicht auf NULL gesetzt?

    Und wenn irgend möglich verlasse Dev-C++.



  • bin auch dabei auf codeblocks umzusteigen (selbe Fehlermeldung)
    ich schreib hier mal den ganzen Code auf, vielleicht könnt ihr da mehr erkennen als ich:

    main.cpp

    #include <iostream>
    using namespace std;
    
    #include "lists.h"
    
    int main()
    {
        sList<int> test;
        slistElement<int> ele(18);
        test.append(&ele);
        test.ausgabe();
    
        cin.ignore();
        cin.get();
    }
    

    lists.h:

    template <class T> class slistElement
    {
      private:
        T data;
        slistElement<T>* next;
    
      public:
        slistElement(T wert)
        {
             data = wert;
             next = NULL;
        }
        T getData()
        {
             return data;
        }
        void setData(T data)
        {
             this->data = data;
        }
    
        slistElement<T>* getNext()
        {
             return next;
        }
        void setNext(slistElement<T>* next)
        {
             this->next = next;
        }
    };
    
    template <class T> class sList
    {
      private:
        slistElement<T>* head;
    
      public:
        /* Konstruktor */
        sList()
        {
               head = NULL;
        }
    
        /* Anhaengen eines Listenelements an das Ende */
        void append(slistElement<T>* e)
        {
             //Ans Ende springen
             slistElement<T>* current = head;
             while (current != NULL)
                   current = current->getNext();
             //Element anhängen
             T wert = e->getData();
             current->setData(wert);
             current->setNext(NULL);
        }
    
        /* Ausgabe der List */
        void ausgabe()
        {
             slistElement<T>* current = head;
             while (current != NULL)
             {
                   cout << current->getData() << " ";
                   current = current->getNext();
             }
        }
    };
    


  • benny111 schrieb:

    ich schreib hier mal den ganzen Code auf, vielleicht könnt ihr da mehr erkennen als ich:

    Ich habe da schon mehrere Kommentare.

    1. Normalerweise sind die Implementierungsdetails der Listenelemente nicht Teil der Schnittstelle, ich würde erwarten das der append-Aufruf mit int, nicht mit Listenelementen arbeitet.

    // statt
    sList<int> test;
    slistElement<int> ele(18);
    test.append(&ele);
    
    // erwarte ich eher
    sList<int> test;
    test.append(18);
    

    2. Die Ausgabe sollte in der Regel von der Liste getrennt werden. Was ist, wenn du die Liste mal irgendwann in einem Windowsprogramm nutzen willst? So müsstest du die Liste ändern.

    3. Du solltest dich mal mit der Initialisierungsliste eines Konstruktors auseinander setzen.

    template <class T> class slistElement
    ...
    
    //statt
        slistElement(T wert)
        {
             data = wert; // <-- Zuweisung, nicht initialisierung
             next = NULL;
        }
    
    // besser:
        slistElement(T wert)
        :   data(wert), // <-- Initialisierungskiste
            next(NULL)
        {
        }
    

    4. Du weist dem ersten Element initial eine NULL zu (In sList::sList, "head = NULL"), und überlege dir mal was du dann in append damit machst.

    void append(slistElement<T>* e)
    {
        //Ans Ende springen
        slistElement<T>* current = head; // current ist anschließend NULL
        // ...
        current->setData(wert); // Zugriff auf undefiniertes Element!
        // ...
    };
    

    Mit Anmerkung 1 zusammen würde ich mehrere Dinge ändern:

    // UNGETESTET AUS DEM KOPF GESCHRIEBEN!
    void append(T element)
    {
        // Wenn kein Element existiert ein neues anlegen
        if(head == null) {
            head = new slistElement<T>(element);
            return;
        }
    
        // Ansonsten an den Elementvorgänger anhängen
        // - Vorgänger (letztes Element) ermitteln
        slistElement<T> * parent = head;
        while(parent->next)
            parent = parent->next;
        // - An letztes Element anhängen
        parent->next = new slistElement<T>(element);
    };
    


  • Du bist mit der Schleife gelaufen, bis current==NULL war, das war eins zu weit. Und ich sehe gar nicht, wie Du die Verkettung gebastelt hast.

    if(head==NULL)
                //einfach
             else
             {
                //Ans Ende springen
                slistElement<T>* current = head;
                while (current->getNext() != NULL)
                      current = current->getNext();
                //Element anhängen
                current->setNext(e);
                e->setNext(NULL);
           }
    


  • Habs hinbekommen, danke für eure 🙂 👍



  • benny111 schrieb:

    Mein Problem ist, das ich die ganzen Variablennamen und Funktionsköpfe usw. nicht verändern darf.

    Was gerade bei der Listenschnittstelle eine sehr schwachsinnige Anforderung ist, da die Listenelemente auch zwangsweise mit neu erzeugt werden müssen, und dies unter keinen Umständen vergessen werden darf.

    Gute Schnittstellen sind Schnittstellen, die möglichst keine Fehler erlauben. Zudem sollte die Allozierung und Freigabe immer an einer Stelle erfolgen, auch dieses Prinzip wird hier verletzt.

    Dein Lehrer/Dozent ist entweder schlecht, oder er baut absichtlich diesen Fallstrick ein, um ihn später aufzulösen.

    benny111 schrieb:

    Hab jetzt versucht sämtliche Ratschläge zu beherzigen, das ist dabei raus gekommen:

    Leider sind teile der Ratschläge nur mit einer geänderten Schnittstelle sinnvoll.

    ...
        void append(slistElement<T>* e)
        {
            T wert = e->getData();
            // Wenn kein Element existiert ein neues anlegen
            if(head == NULL)
            {
                head = new slistElement<T>(wert);
                return;
            }
    ...
    

    Da in diesem Fall das Element übergeben wird, darf im Append kein neues angelegt werden, sondern muss e verwendet werden.

    ...
        void append(slistElement<T>* e)
        {
            // Wenn kein Element existiert, e als erstes nehmen
            if(head == NULL)
            {
                head = e;
                return;
            }
    ...
    

    Den Rest lasse ich dir dennoch erst einmal als Denkaufgabe...


Anmelden zum Antworten