paper
paper

Reputation: 75

C++ OOP Basics - Returning an object reference properly?

I'm learning C++ and have a problem working with an object returned as a reference which I want to continue to use and modify.

I have two classes, University and Student.

University is instantiated and has method addStudent() which stores a new Student object in a private vector data member of University. I want the method to return a reference to the newly created Student object. I then want to call the Student::addCourse() method on the returend object to add some courses to the student's "transcript."

I thought that since I returned a reference to the Student object it would update itself stored in the _Students vector in the University object, and therefore the changes would be visible outside its scope, but it doesn't keep the changes.

When I call printTranscript() on the returned Student object, it properly shows the added courses.

But, when I call printRegistrar() on the University object, it shows that student has no courses.

This seems like I'm missing a fundamental OOP principle. What am I doing wrong, and how do I make it work?

(I already have this working using a student ID as a handle to reference a student between objects, but I thought this way seemed more elegant, if I could get it to work.)

The full code is here: http://pastebin.com/cjmC1UuL

// Create a new university called UHD.
University UHD;

// Add 4 students to UHD.
UHD.addStudent("Jim");
UHD.addStudent("Bill"); 
Student Bob = UHD.addStudent("Bob");
UHD.addStudent("Greg");

// Add 3 classes for Bob
Bob.addCourse("WRTG140");
Bob.addCourse("MATH009");
Bob.addCourse("BIOL101");       


// Shows Bob correctly has 3 classes.
Bob.printTranscript();

// BUG?: Shows Bob incorrectly has 0 classes.
UHD.printRegistrar();

Upvotes: 3

Views: 125

Answers (2)

JonPall
JonPall

Reputation: 814

Student Bob = UHD.addStudent("Bob");

This call triggers the copy constructor, and hence returns a copy of "Bob", but not the actual object you added to UHD.

Upvotes: 0

Joseph Mansfield
Joseph Mansfield

Reputation: 110778

UHD.addStudent("Bob")

The result of this expression is indeed a reference to the internal Student object.

Student Bob = UHD.addStudent("Bob");

Here, however, you are copying from that reference to construct the object Bob. If you want to continue to keep a reference, you need to make Bob a reference:

Student& Bob = UHD.addStudent("Bob");

Note, however, that Bob may not remain a valid reference for long. At most you can expect it to last until the UHD object is around, but adding new students may cause the vector to reallocate its elements, in which case the reference is no longer referring to a valid object. As @tenfour suggests in the comments, a std::list would avoid that problem because it does not reallocate its elements. However, I would suggest that leaking references to your internal objects is a bad way to do things anyway, and would instead suggest having a way of modifying the internal Student objects through the University interface (perhaps just a simple setter).

Upvotes: 4

Related Questions