Konstruktor einer Klasse nach Instanzierung erneut aufrufen



  • Hallo,

    ein Frage bereitet mir gerade Kopfzerbrechen. Eigentlich geht es dabei um PHP. Weiss jetzt aber nicht genau wie es in C++ ist, denke mir aber dort könnte es auch zu treffen, deshalb in diesem Forum.

    Auf meiner Arbeit wird PHP programmiert und dort sehe ich häufiger folgender Konstruktionen. Eine Klasse wird initialisiert und im Konstruktor irgendwas übergeben. Dann an einer anderen Stelle im Code wird der Konstruktor der schon instanzierten Klasse nochmals aufgerufen und neue Werte übergeben die in der Klasse verarbeitet werden sollen.

    Ich löse das immer so, in dem ich eine set-Funktion einführe um die Werte in die Klasse zu bringen und nicht den Konstruktor aufzurufen.

    Leider finde ich nicht so recht Argumente um zu sagen, den Konstruktor explizit noch einmal aufzurufen, nach dem die Klasse instanziert wurde, ist falsch.

    Ist es falsch oder durchaus legitim?

    class A
    {
      protected $data
    
      // PHP - Konstruktor
      public function __construct(array $blubb)
      {
        $this->data = $blubb;
      }
    }
    
    $data   = array();
    $classA = new A();
    
    // ... was machen
    
    // neues Array erzeugen und den Konstruktor nochmals aufrufen
    $data2 = array();
    $classA->__construct($data2);
    


  • Mit PHP-Problemen bist du hier im falschen Board gelandet. In C++ ist es jedenfalls nicht üblich (und nur auf Umwegen möglich), den Ctor eines bereits existierenden Objekts nochmal neu aufzurufen. Da verwendet man normalerweise eine Initialisierungs-Funktion, die notfalls direkt aufgerufen werden kann (die muß nicht unbedingt init() oder set() heißen) - oder erzeugt ein neues Objekt und weißt es dem bestehenden zu:

    //Produktivbeispiel mit Initialisierung:
    ofstream ausgabe("daten1.txt");//Ctor-Aufruf
    ...
    ausgabe.clear();//Aufräumarbeiten
    ausgabe.open("daten2.txt");//und nun recyclen wir das Objekt
    
    //Beispiel mit Zuweisung;
    vector<int> data(100,10);
    ...
    data = vector(250,0x0815);
    /* alternativ ginge hier auch
    data.assign(250,0x0815);
    */
    


  • CStoll schrieb:

    In C++ ist es jedenfalls nicht üblich (und nur auf Umwegen möglich), den Ctor eines bereits existierenden Objekts nochmal neu aufzurufen.

    Davon abgesehen ist das undefiniert, wenn das Objekt zuvor nicht destruiert wird. Im Grunde löscht Du also das alte Objekt und erzeugst ein neues an der selben Speicherstelle.



  • meinste mit

    $classA->__construct($data2);
    

    nicht eigentlich

    $classA=new ClassA($data2);
    

    ?
    ja, sowas geht in c++ sogar auch.

    classA=data2;
    

    aber ganz so wie in php gehts nicht. du darfst den konstruktor nicht aufrufen, um ein objekt zu ändern.

    aber dein compiler macht bestimmt keinen ärger und das programm stürzt vermutlich nicht sofort ab. probier mal nur zum spaß

    //include <new>
    new(&classA) ClassA(data2);
    


  • CStoll schrieb:

    In C++ ist es jedenfalls nicht üblich (und nur auf Umwegen möglich), den Ctor eines bereits existierenden Objekts nochmal neu aufzurufen.

    Ist so nicht korrekt. Es ist nichtmal auf Umwegen moeglich, sondern unmoeglich (statt unueblich). Der Konstruktor fuer ein Objekt kann nur ein einziges mal aufgerufen werden, und das Objekt existiert erst nach Beenden des Konstruktors. Fuer existierende Objekte kann man nurnoch die Memberfunktionen und den Destruktor aufrufen. Nach Ausfuehren des Destruktors existiert das Objekt nichtmehr, ein erneuter Konstruktoraufruf (z.B. per placement-new) erzeugt ein neues Objekt, das zwar denselben Platz belegen kann und den identischen internen Status haben kann wie das Objekt, was dort vorher war, nichts desto trotz ist es ein anderes Objekt. Ist eine Frage der Objekt-Lebenszeit.

    Kurz: man kann nichts erzeugen, was schon existiert, und man kann nichts zerstoeren, was nicht existiert, Punkt.

    Sehr interessant zu dem Thema auch http://www.gotw.ca/gotw/ , Artikel 22 udn 23.



  • *duck* da habe ich mich wohl etwas schwammig ausgedrückt - mit dem "auf Umwegen" meinte ich auch den Weg "zerstören und mit placement-new neu erzeugen" - und mit solchen Feinheiten wie der Objekt-Lebenszeit wollte ich den Kollegen nicht gleich erschlagen.

    @LordJaxom: den Teil "wenn das Objekt zuvor nicht destruiert wird" hatte ich eigentlich als Teil des (Um)Wegs gesehen 😉

    @volkard: klar würde das so durch den Compiler kommen, aber verursacht zumindest ein Speicherleck, weil du das originale Objekt plattgemacht hast, ohne ihm die Chance zum Aufräumen zu geben.



  • volkard schrieb:

    probier mal nur zum spaß

    //include <new>
    new(&classA) ClassA(data2);
    

    😮 Dann liefer aber bitte auch "nur zum Spass" gleich ne grosse Kanone mit, um jeden der versucht ist, sowas in produktivem Code einzubauen, daran zu erinnern, dass er dann standrechtlich erschossen gehoert 😉



  • Naja, ich verstehe die Ursache der Fragestellung ned wirklich.

    Ich mein der Name Konstruktor deutet ja schon drauf hin, das man das ding bei der Erzeugung des Objects ausfuehrt (ausfuehren sollte) und nicht wenn ich grad mal Lust hab.

    Wird es nach der konstruktion nochmal benoetigt, dann gehoert es ja auch definitiv nicht in den CTor, oder ?

    Natuerlich ist es legitim, im CTor selber wieder funktionen aufzurufen, die komplexere Einstellungen taetigen die man an anderer stelle auch macht.

    Alles andere ist doch eher kritisch vom Design her ...
    Und mir faellt im Moment wirklich kein Grund ein, warum man sowas technisch brauchen sollte, der grund wird wohl eher sein, das man sich das geschreibse eines funktionsaufrufes und das auslagern des einstellens in ne eigene Funktion (inline, damit der compiler auch wirklich keinen ueberfluessigen code erzeugt) sparen will, oder ?

    Von der Warte her, wo kann man so ne Kanone bestellen, mag paar auf Vorrat haben 🙂

    Ciao ...


Anmelden zum Antworten