Vererbungs-Problem



  • [edit]
    Aaargh, ich Trottel! Umm... da hab ich wohl mal wieder zu früh gepostet -- ich das das Problem. Es muss natürlich if(!next) heissen und nicht if(next). Sorry! Ich denke, der Thread kann gelöscht werden...
    [/edit]

    Hallo!

    Wir alle kennen das Prinzip verketteter Listen. Um den Stress zu sparen, den man hat, wenn man die gesamte Kette bearbeiten will (nämlich sicherzustellen, dass das Objekt, das man hat, auch wirklich der Anfang der Kette ist), erstelle ich diese Listen gewöhnlich in Ringform. (Dann gibt es keinen Anfang. :D)
    Um nicht jedesmal, wenn ich eine Klasse implementiere, die ganzen Funktionen zum Einfügen in den Ring und zum Wieder-Herauslöschen etc. neu schreiben zu müssen, dachte ich, ich könnte eine Ring-Klasse schreiben, die dieses ganze Zeug schon mal bereit stellt, und dann alle Ringe später bloss noch davon erben lassen. Daher habe ich zwei Klassen erstellt: Ring, die Basis-Ring-Klasse und Foo, einen Test-Ring, dessen Elemente nichts als einen Namen haben.
    Allerdings gibt es beim Einfügen von Foos in den Foo-Ring Access Violations:

    #include <iostream>
    #include <string>
    
    class Ring {
      public:
        Ring();
        void insert(Ring* p);
        void remove();
        void make();
        Ring* pop();
    
        Ring* prev;
        Ring* next;
    };
    
    Ring::Ring() {
        prev = next = NULL;
    }
    
    void Ring::insert(Ring* p) {
        if(next) {              // Diese Zeile verursacht den Fehler
            prev = next = p;
            p->prev = p->next = this;
        } else {
            prev->next = p;
            p->prev = prev;
            p->next = this;
            prev = p;
        }
    }
    
    void Ring::remove() {
        if(next) {
            if(next == prev) {
                prev->next = NULL;
                next->prev = NULL;
            } else {
                prev->next = next;
                next->prev = prev;
            }
        }
        delete this;
    }
    
    void Ring::make() {
        this->insert(new Ring);
    }
    
    Ring* Ring::pop() {
        return next;
    }
    
    class Foo : public Ring {
        string name;
      public:
        Foo(string n);
        void dump();
        void dump(Foo* daddy);
        void make(string n);
    };
    
    Foo::Foo(string n) : Ring::Ring(), name(n) { }
    
    void Foo::dump() {
        cout << name << endl;
        if(next)
            ((Foo*)next)->dump(this);
    }
    
    void Foo::dump(Foo* daddy) {
        if(this == daddy)
            return;
        cout << name << endl;
        ((Foo*)next)->dump(daddy);
    }
    
    void Foo::make(string n) {
        this->insert(new Foo(n));
    }
    
    int main() {
        Foo first("first");
        first.make("second");
        first.dump();
        return 0;
    }
    

    Die Zeile "if(next)" in der Funktion Ring::insert() verursacht den Fehler, aber ich habe keine Ahnung warum. Ich hab schon versucht, den Aufruf first.make("second"); (der ja Ring::insert() aufruft) "auseinanderzunehen":

    • Die Anweisung first.make("second") ruft Foo::make(string) auf.
    • Foo::make() erstellt einen neuen Foo und ruft, da Foo ja kein insert() hat, Ring::insert(Ring)* auf. Der erzeugte Foo wird als Ring* an Ring::insert() übergeben, was aber OK ist, da ja jeder Foo ein Ring ist.
    • Ring::insert() greift auf next zu, was als this->next interpretiert wird. Da sowohl make() als auch insert() auf first aufgerufen werden, ist dieses this->next also first.next, dass ja aufgrund des Aufrufs Ring::Ring() in Foo::Foo() NULL ist. Demnach sollte die Zeile als if(NULL) interpretiert werden -- und keinen Fehler verursachen.


  • Hi,

    trotzdem mal ne Frage. Warum nicht std::list, da brauchst Du keinen Ring erstellen, damit Du auch ja von vorne bis hinten durcharbeiten kannst.

    grüße Con@n



  • Uhh... Ich kenne mich mit diesen ganzen std-Klassen nicht so toll aus, auch was man da immer sieht mit bla.begin() und weiss der Henker was alles... Ich weiss ja nicht, wie das alles funktioniert...



  • Dann kann ich Dir nur empfehlen, setz Dich mit der STL ein wenig auseinander. Sie kann einem das Leben ungemein erleichtern.

    grüße Con@n



  • Danke, ich werd's mir mal anschaun...


Anmelden zum Antworten