2017-05-21 7 views
-2

Ich habe eine Klasse A, die einige Instanzvariablen enthält, und eine Klasse B, die einen Verweis auf der Klasse nimmt und die Instanzvariablen ändert. Nachdem Klasse B diese Variablen geändert hat, würden Sie denken, dass diese in der ursprünglichen Instanz der Klasse geändert würden, in diesem Fall jedoch nicht. Warum passiert das und wie kann ich das beheben?C++ das Ändern einer Klasse, die als Referenz übergeben wird, ändert das ursprüngliche Objekt nicht

class Foo { 
public: 
    int x; 
    int y; 
    Foo() { 

    } 
    Foo(int x, int y) { 
     this->x = x; 
     this->y = y; 
    } 
}; 

class Bar { 
public: 
    Foo foo; 
    Bar() { 

    } 
    Bar(Foo& foo) { 
     this->foo = foo; 
    } 
    void Swap() { 
     int tmp = foo.x; 
     foo.x = foo.y; 
     foo.y = tmp; 
    } 
}; 
int main() 
{ 
    Foo foo(4, 8); 
    Bar bar(foo); 

    std::cout << "this is x: " << foo.x << std::endl; //prints 4 
    std::cout << "this is y: " << foo.y << std::endl; //prints 8 

    bar.Swap(); 
    std::cout << "this is x: " << foo.x << std::endl; //prints 4, but should print 8 
    std::cout << "this is y: " << foo.y << std::endl; //prints 8, but should print 4 
} 
+0

Willkommen bei Stack Overflow. Bitte nehmen Sie sich die Zeit, [The Tour] (http://stackoverflow.com/tour) zu lesen und beziehen Sie sich auf das Material aus der [Hilfe] (http://stackoverflow.com/help/asking), was und wie Sie können fragen Sie hier. –

+0

Das richtige Werkzeug, um solche Probleme zu lösen, ist Ihr Debugger. Sie sollten Schritt für Schritt durch Ihren Code * gehen, bevor Sie auf Stack Overflow nachfragen. Für weitere Hilfe lesen Sie bitte [Wie kleine Programme zu debuggen (von Eric Lippert)] (https://ericlippert.com/2014/03/05/how-to-debug-small-programs/). Zumindest sollten Sie Ihre Frage so bearbeiten, dass sie ein [minimales, vollständiges und überprüfbares] (http://stackoverflow.com/help/mcve) Beispiel enthält, das Ihr Problem zusammen mit den Beobachtungen, die Sie im Debugger gemacht haben, reproduziert . –

+2

'Bar' enthält eine Kopie der Quelle' Foo', keine Referenz auf die Quelle 'Foo'. Das 'Foo' wurde durch Verweis in die Funktion übernommen, wurde dann aber kopiert. – user4581301

Antwort

3

Klasse B ‚s Konstruktor dauert foo (der Parameter) Bezug genommen wird, sondern sofort kopiert sie in eine separate Instanz A (insbesondere in das foo Element); Swap arbeitet dann auf dem foo Mitglied, das, wie oben gesagt, nur eine Kopie des ursprünglichen Objekts ist.

Um Ihren Code zu verhalten, wie Sie erwarten, dass Sie auch das Mitglied foo eine Referenz machen müssen (oder ein Zeiger):

class Bar { 
public: 
    Foo &foo; 
    Bar() { 

    } 
    Bar(Foo& foo) : foo(foo) { 
    } 

(Hinweis, dass ich musste the member initialization list syntax weil Referenzen cannot be default-initialized and then reseated)

+0

Danke für die Hilfe, von C# nach C++ zu gehen war ein wenig schwierig mit der Art, wie C++ Zeiger und Referenzen behandelt. –

0

Sie übergeben einen Verweis auf den Konstruktor bar foo, aber dann zuweisen (Kopie), um die foo, die Sie unter Bezugnahme auf bar.foo bestanden haben.

Sie möchten es als Referenz auf ein Foo-Objekt deklarieren (oder darauf verweisen), kein separates Foo-Objekt.

0

Das Problem ist hier.

Foo foo; 
    Bar(Foo& foo) { 
     this->foo = foo; 
    } 

Auch wenn Sie durch Verweis die foo Argument, können Sie es zu einem Nicht-Referenzwert zuweisen, die in einer Kopie führt und Konten für das Problem Sie gestellt. Der erste Schritt zur Lösung besteht darin, Ihr Instanzfeld durch Verweis zu deklarieren.

Foo& foo; 

Dies führt jedoch zu einem Fehler, wenn Sie versuchen, es zuzuweisen. Zu diesem Zweck möchten wir eine spezielle Konstruktorinitialisierungssyntax verwenden. Es funktioniert im Grunde genommen genauso wie eine Zuweisung, führt aber eher eine Konstruktion aus als eine normale Zuweisung. Schreiben Sie Ihren Konstruktor wie folgt.

Bar(Foo& foo) : foo(foo) {} 

Sie werden auch Bar() vollständig den Standardkonstruktor entfernen müssen, da die meisten C++ Compiler Code ablehnen wird, die in einem nicht initialisierten Referenz führen könnte.

Verwandte Themen