2017-06-07 1 views
1

Ich versuche zu verstehen, wie Referenzen in C++ arbeiten, also habe ich ein paar Dateien mit zwei verschiedenen Objekten erstellt. Einer ist ein Tier und ein anderer ist ein Tierpfleger. Mein Ziel ist es, eine Referenz eines Tieres an einen Tierpfleger weiterzuleiten und den Zoowärter den Namen des Tieres ändern zu lassen und sich trotzdem im ursprünglichen Tierobjekt wiederzufinden. Wie wird dies mit Referenzen gemacht? Hier sind die Dateien, die ich benutze.Wie übergebe ich eine Referenz von einem Objekt an ein anderes und modifiziere dieses erste Objekt noch?

Source.cpp

#include <iostream> 
#include <string> 
#include "Animal.h" 
#include "zookeeper.h" 

using namespace std; 

int main() { 

    Animal animal; 
    Animal& animalRef = animal; 

    printf("animal's name before it is assigned to a zookeeper: %s\n", animal.getName()); 

    Zookeeper aZookeeper = Zookeeper(animalRef); 
    aZookeeper.changeMyAnimalsName("Fred"); 

    printf("animal's name after it is assigned to a zookeeper: %s\n", animal.getName()); 

    //Keep cmd window open 
    int j; 
    cin >> j; 
    return 0; 
} 

Animal.h

#pragma once 
#include <string> 

using namespace std; 

class Animal { 

    string name = ""; 
    int height = 0; 
public: 
    string getName() { return name; } 
    int getHeight() { return height; } 

    void setName(string n) { name = n; } 
    void setHeight(int h) { height = h; } 
}; 

zookeeper.cpp

#include "zookeeper.h" 

using namespace std; 

Zookeeper::Zookeeper(Animal& a) { 
    _myAnimal = a; 
} 

void Zookeeper::changeMyAnimalsName(string newName) { 
    _myAnimal.setName(newName); 
} 

zookeeper.h

#pragma once 

#include "Animal.h" 

class Zookeeper { 
    Animal _myAnimal; 
public: 
    Zookeeper(Animal& a); 
    void changeMyAnimalsName(std::string newName); 
}; 
+0

Referenzen hav Es hat nichts mit Dateien zu tun, also wenn Sie untersuchen wollen, wie sie funktionieren, legen Sie all Ihren Code in eine Datei. –

+0

Sie erstellen eine Kopie, wenn Sie '_myAnimal = a;' im 'Zookeeper'-Konstruktor ausführen, da' _myAnimal' keine Referenz ist. – Barmar

+2

'Animal & _myAnimal;' (beachten Sie das kaufmännische Und) und 'Zookeeper :: Zookeeper (Tier & a): _myAnimal (a) {}' –

Antwort

0

Ihre Klasse Zookeeper definiert das Datenelement _myAnimal vom Typ Animal (und nicht vom Typ Animal&). Wenn Sie also in Ihrem Konstruktor _myAnimal = a zuweisen, wird a - obwohl es eine Referenz ist - kopiert, weil _myAnimal keine Referenz ist. Um den Verweis auf die an den Konstruktor übergebene Objekt zu halten, dann würden Sie müssen Daten Mitglied _myAnimal als Referenz definieren, auch:

class Zookeeper { 
    Animal &_myAnimal; 
public: 
    Zookeeper(Animal& a) : _myAnimal(a) { }; 
    void changeMyAnimalsName(std::string newName); 
}; 
+0

Sie müssen auch ändern, wie das Mitglied initialisiert wird. Siehe https://StackOverflow.com/Questions/15403815/How-To-Initialize-the-Reference-Member-Variable-of-Alass – Barmar

+0

@Barmar: Recht, danke! –

1

Ihre Argumentation richtig ist, aber man am Ende eine Kopie machen von das Tier gibt:

class Zookeeper { 
    Animal _myAnimal; 

Wenn Sie hatte:

Animal& _myAnimal; 

dann würden Sie die referen halten ce zum ursprünglichen Tier, das möglich macht, damit die Namensänderung in main() widerspiegelt wird.

Danach sollten Sie Ihren Konstruktor dies ändern:

Zookeeper(Animal& a) : _myAnimal(a) {} 

, wo ich eine Initialisierungsliste verwendet, die für Referenzen wesentlich ist, wie Sie in How to initalize the reference member variable of a class?


aber lesen können, das ist nicht genug. Wenn Sie -Wall -Wextra Flagge benutzt hatte, zu ermöglichen, Warnungen würden Sie dies sehen:

Source.cc: In function 'int main()': 
Source.cc:13:88: warning: format '%s' expects argument of type 'char*', but argument 2 has type 'std::__cxx11::string* {aka std::__cxx11::basic_string<char>*}' [-Wformat=] 
    printf("animal's name before it is assigned to a zookeeper: %s\n", animal.getName()); 
                         ^
Source.cc:18:87: warning: format '%s' expects argument of type 'char*', but argument 2 has type 'std::__cxx11::string* {aka std::__cxx11::basic_string<char>*}' [-Wformat=] 
    printf("animal's name after it is assigned to a zookeeper: %s\n", animal.getName()); 
                        ^

In wir in der Regel mit std::cout, wie dieser Druck:

int main() { 

    Animal animal; 
    Animal& animalRef = animal; // not needed, Zookeeper(animal) OK too 

    std::cout << "animal's name before it is assigned to a zookeeper: " << animal.getName() << std::endl; 

    Zookeeper aZookeeper = Zookeeper(animalRef); 
    aZookeeper.changeMyAnimalsName("Fred"); 

    std::cout << "animal's name after it is assigned to a zookeeper: " << animal.getName() << std::endl; 
    return 0; 
} 

Oder, wenn Sie wirklich brauchen verwenden printf(), dann könnten Sie c_str(), verwenden, die eine C-Kette von std::string zurückgibt, wie folgt aus:

printf("animal's name before it is assigned to a zookeeper: %s\n", animal.getName().c_str()); 
Verwandte Themen