übergibt dies von der Konstruktorinitialisierungsliste

8

Gibt es Probleme bei der Übergabe von 'this' an ein anderes Objekt in der Initialisierungsliste im folgenden Code?

%Vor%

Wenn es unsicher ist, das zu tun, was ist die beste Alternative?

    
markh44 15.05.2009, 15:16
quelle

6 Antworten

10

Wenn Sie extrem vorsichtig sind, wird das gut funktionieren. Sie werden in große Schwierigkeiten geraten, wenn Sie anfangen, virtuelle Methoden aufzurufen oder Methoden zu verwenden, die von anderen Objekten des Typs abhängen. Aber wenn Sie nur eine Referenz setzen, sollte das gut funktionieren.

Eine sicherere (aber nicht völlig sichere) Alternative besteht darin, b später zu setzen, sobald der Konstruktor fertiggestellt ist. Dies wird Vtable-Probleme nicht beseitigen, aber Probleme wie den Zugriff auf andere Member-Variablen, bevor sie erstellt werden, entfernen.

%Vor%     
JaredPar 15.05.2009, 15:20
quelle
6

Wenn die andere Klasse nur den Zeiger / Referenz speichert, wie in Ihrem Fall, ist es sicher. Sie müssen jedoch sicher sein, dass die Konstruktoren / Funktionen, denen Sie this übergeben, nicht versuchen, auf das referenzierte Objekt zuzugreifen, bevor der Konstruktor von A beendet ist. Das A -Objekt ist noch nicht vollständig konstruiert, und der Aufruf von Methoden von A und der Zugriff auf Eigenschaften kann zu undefinierten Ergebnissen führen.

    
sth 15.05.2009 15:21
quelle
4

Es ist im Allgemeinen sicher, wenn Sie nur den Zeiger für die spätere Verwendung weg speichern. Ich habe das getan. Ich würde keines der folgenden Dinge tun:

  • Verwenden Sie diese Option, um auf Basis- oder abgeleitete Klassendaten zuzugreifen (die Konstruktoren konnten nicht ausgeführt werden)
  • Etwas polymorphes machen, die vtable darf nicht initialisiert werden.

Hier ist ein großartiger Artikel aus der C ++ - FAQ, der die Probleme beschreibt mit "this" in Konstruktoren.

    
Doug T. 15.05.2009 15:21
quelle
3

Das Starten von Threads in Konstruktoren, die Code im noch nicht im Bau befindlichen Objekt ausführen, ist gefährlich. Der von Ihnen präsentierte Code funktioniert ordnungsgemäß, aber die Lösung ist fragil.

Wenn DoCallback eine virtuelle Methode in A aufruft, kann dies zu unerwarteten Ergebnissen führen, abhängig davon, wie schnell der Thread ausgeführt wird. Wenn die aufgerufene Methode rein virtuell ist, dann stirbt die Anwendung, wenn sie nicht rein ist, wird die A Version der Methode anstelle der abgeleiteten Version aufgerufen. Das ist genau der gleiche Grund, warum Sie niemals eine virtuelle Methode von einem Konstruktor aufrufen sollten.

Der sicherere Ansatz besteht darin, dass der Benutzer den Thread aufruft. Das ist auch der Ansatz in der boost :: thread library und dem kommenden Standard. Erstellen und initialisieren Sie das Objekt, das ausgeführt werden soll, und übergeben Sie es dann an den laufenden Thread:

%Vor%     
quelle
2

Es ist sicher genug, wenn man bedenkt, dass das Objekt this noch nicht vollständig erstellt wurde. Wenn Ihre B -Klasse nur den Zeiger speichert, ohne irgendwelche Funktionen im Konstruktor aufzurufen, sind Sie in Sicherheit. Wenn Sie versuchen, auf den Zeiger von Bs Konstruktor zuzugreifen, müssen Sie sehr vorsichtig sein und achten Sie auf die Reihenfolge, in der die Mitglieder von A initialisiert werden.

    
jalf 15.05.2009 15:23
quelle
0

Solange Sie sicherstellen, dass die Referenz noch gültig ist, ist dies sehr ähnlich zu einem Idiom namens Double Dispatch. Es könnte in diesem Fall übertrieben sein, aber es gibt nichts an sich falsch.

    
rlbond 15.05.2009 15:20
quelle

Tags und Links