Kopiermethode virtualisieren?



  • ne, const dazumachen

    this->steps = dynamic_cast<ObWave const*>(&ref)->getSteps();
    


  • xBlackKnightx schrieb:

    Object & operator=(const Object & ref)
    

    Wie hol ich hier die geerbten Werte aus ref? Muss ich hier upcast nehmen? Wenn ja, wie innerhalb Kopiermethode?

    Was genau treibst du denn da? Die Tatsache dass du dir überhaupt diese Frage stellst lässt sehr stark vermuten dass es nichts Gutes ist...



  • Du kannst die Klasse eines Objektes nicht verändern, nachdem es einmal erstellt ist. Dementsprechend wird dich operator= hier nicht weiterbringen - wenn Klassen B und C von A erben, wie sollen denn dann die Werte eines Objekts vom Typ B in eins vom Typ C geschrieben werden?

    Wenn du mit Zeigern (bzw. hoffentlich Smart-Pointern) arbeitest, ist die übliche Methode, den Klassen eine virtuelle clone-Methode der Form

    virtual classname *clone() const { return new classname(*this); }
    

    zu geben. Auf die Art lässt sich

    std::auto_ptr<A> ptr_d = new B;
    std::auto_ptr<A> ptr_s = new C;
    
    // ...
    
    ptr_d = ptr_s->clone();
    
    // ptr_d zeigt jetzt auf ein Objekt vom Typ C
    

    schreiben.



  • hm daran hab ich nicht gedacht.
    hatte so geschrieben

    Object & operator=( const Object & ref) {
    		Object::operator=(ref);
    		this->steps = dynamic_cast<ObWave const*>(&ref)->getSteps();
    		this->wavelenght = dynamic_cast<ObWave const*>(&ref)->getWavelenght();
            return *this;
        }
    

    dass mit C und B nicht geht habe ich noch nicht probiert
    Leider hab ich noch nie mit smart-pointern gearbeitet.

    hoffentlich ist std::auto_ptr plattformunabhängig?



  • Ja, std::auto_ptr ist im Standard definiert, aber ich habe gehört, daß es auf lange Sicht ersetzt werden soll.

    Zu deinem Code: Du solltest eventuell abfangen, ob der Cast wirklich funktioniert hat:

    Object & operator=( const Object & ref) {
      Object::operator=(ref);
      const ObWave* src = dynamic_cast<const ObWave*>(&ref)
      if(src)
      {
        this->steps = src->getSteps();
        this->wavelenght = src->getWavelenght();
        return *this;
      }
      else
      {
        //Fehlerbehandlung - das übergebene Objekt war kein ObWave
      }
    }
    


  • Ja, noch ist mein Programm schlicht, müsste immer funktionieren. Im Maincode ist so ein Kopiermechanismus, welcher mir allerdings auch nicht so gefällt. Wenn jedesmal ein neues geerbtes Objekt hinzukommt, muss diese else-if Anweisung verlängert werden.

    struct ObPointer {
    	Object *objp;
    };
    
    Object *obj_copy;
    
    	obj_copy = QVariant(parent_item->data(ObjectRole)).value<ObPointer>().objp; // Qt Zeile (anderes Thema)
    
    	ObPointer obp;
    
    	if (obj_copy->type() == 1)
    		obp.objp = new ObWave();
    	else if (obj_copy->type() == 2)
    		obp.objp = new ObSpiral();
    	else
    		obp.objp = new Object();
    
    	*obp.objp = *obj_copy;
    

    glaub mit clone wäre besser. aber dann müsste ich eher shared pointer nehmen, weil bestimmt mehrere Zeiger auf ein object gezeigt werden



  • Die Lösung dafür wurde doch schon genannt: Spendiere deinen Klassen eine eigene Clone()-Methode, die jeweils eine passende Kopie des Objekts erzeugt.



  • ja dachte ich, siehe edit oben.



  • CStoll schrieb:

    Zu deinem Code: Du solltest eventuell abfangen, ob der Cast wirklich funktioniert hat:
    (...)

    Ja, sollte er. Geht aber auch einfacher:

    Object & operator=( const Object & ref) {
      Object::operator=(ref);
      const ObWave& src = dynamic_cast<const ObWave&>(ref);
      this->steps = src.getSteps();
      this->wavelenght = src.getWavelenght();
      return *this;
    }
    

    😉



  • hustbaer schrieb:

    Ja, sollte er. Geht aber auch einfacher:

    Stimmt, aber ganz so extrem wollte ich die Aufgabe auch nicht lösen 😃



  • So extrem finde ich das jetzt nicht.
    OK, wenn man möchte dass ein von std::logic_error oder std::runtime_error abgeleiteter Fehler fliegt, dann ist es nicht gut.
    Ansonsten halte ich std::bad_cast für ausreichend.


Anmelden zum Antworten