2

I have class car and I use car as an attribute in class App.

class Car{
private:
  string color;
public:
  //setter getter
  void setColor(string c){
     color = c;
  }
  string getColor(){
     return color;
  }
}

and

class App(){
private:
   Car car;
public:
   App():car(){
   }
   Car getCar(){
      return car;
   }
}

this is my main app

int main(){
  App app[2];

  app[0].getCar().setColor("red")
  //WHY RETURN NULL?
  cout << app[0]/getCar().getColor();
  return 0;
}

the setter is working well but why does the getter return null as if the object app[0] is reinstance? Thank You

Vishaal Shankar
  • 1,648
  • 14
  • 26
Mamen
  • 1,322
  • 5
  • 21
  • 44

2 Answers2

2

the setter is working well but, why the getter is return null like the object (app[0]) is reinstance?

You are having a problem because you are returning a temporary copy of your Car member variable rather than a reference to the member variable itself. More specifically, your member function getCar() returns Car rather than Car&. Your current version will copy the value of the member variable car into a temporary and return the temporary as its return value, not the member variable itself. So then in this code:

app[0].getCar().setColor("red");

You are actually modifying the contents of the temporary copy that getCar() returned. Since this is a temporary copy, the temporary will be destroyed at the end of the statement, and all your modifications will be lost. Moreover, the car member variable of app[0] will continue to have its default value.

What you want is to return a reference to the member variable itself that will allow you to edit its contents directly. To do this, you need to modify your App class in the following way:

class App(){
private:
   Car car;
public:
   App():car(){
   }
   Car& getCar(){
      return car;
   }
}

Now getCar() returns a reference to the member variable car, and modifying this reference will directly modify the car member variable of app[0], giving you your expected behavior.

Daniel
  • 1,291
  • 6
  • 15
  • omg thank you very much, i know the object is not referencing to App class,but i dont know the keyword to search on google lol – Mamen Feb 27 '18 at 06:18
0

In this specific case, return reference could solve your problem.

However, in general, return reference of a member variable is a bad practise.(see detail in this post).

In your case, I think you want the shared ownership when get car. So may be use shared_ptr for car is better than returning reference directly.

class App
{
public:
    App() : car(std::make_shared<Car>()){};
    std::shared_ptr<Car> getCar() {return car;}
private:
    std::shared_ptr<Car> car;
};
2power10
  • 1,259
  • 1
  • 11
  • 33
  • I agree the returned reference is not the best design, but your proposed design also breaks at least two out of three principles listed in the post you linked to. By returning a reference or shared_ptr, you are breaking the encapsulation of the private data since now code outside the class can manipulate the private data directly. The better design would be to have member functions in App that would handle setting the Car color instead. – Daniel Feb 27 '18 at 14:14