-1

I am working on a assignment for an OOPs c++ course. This assignment is dealing with using set/get functions and constructors/persecutors.

I have some code that will compile with VS professional 2015(windows) and run but will not compile on our linux lab(I need it to compile here so I can run a test bed to make sure I have no styling errors before turning in, also if it won't compile I'll get some points off)

So what code I am working on is creating four different classes.

Address, Product, Customer, Order (Code)

Customer has a class private member variables that is an instance of Address. Order has two class private member variables, instance of Address and Customer.

As stated earlier the purpose of the assignment is to become more familiar with set/get functions.

My professor has made it clear that "get" functions should return a value not store a value(accessing private member variable).

For example in the class Address I use a "get" function to access the member variable street

string getStreet() { return street; }

Now when I need to make a get function for accessing a private member variable but that variable happens to be an instance of a class I wasn't sure what to do.

Sticking to my training I assumed that I would set something up like this(Customer Class).

Address getAddress() { return address; }

Likewise I setup a set function as follows

void setAddress(Address &address) 
{
        this->address.setStreet(address.getStreet());
        this->address.setCity(address.getCity());
        this->address.setState(address.getState());
        this->address.setZip(address.getZip());
}

Going one step deeper I then have a class called Order that has a private member variable instance of Customer. Now here is where I think I am getting into trouble.

I need to make a non-default constructor in which I pass in some instances where one of the instance is the customer class.

My constructor looks like so.

Order(Product &product, int quantity, Customer &customer)
    {
        this->product.setName(product.getName());
        this->product.setDescription(product.getDescription());
        this->product.setWeight(product.getWeight());
        this->product.setBasePrice(product.getBasePrice());
        this->quantity = quantity;
        this->customer.setName(customer.getName());
        this->customer.setAddress(customer.getAddress());
    }

Now this process raises no errors of flags when running in VS professional 2015 however when I try to compile on the linux lab I get the error.

In file included from order.cpp:3:0:
order.h: In constructor ‘Order::Order(Product&, int, Customer&)’:
order.h:25:51: error: no matching function for call to‘Customer::setAddress(Address)’
    this->customer.setAddress(customer.getAddress());
                                                   ^
order.h:25:51: note: candidate is:
In file included from order.h:7:0,
                 from order.cpp:3:
customer.h:32:8: note: void Customer::setAddress(Address&)
   void setAddress(Address &address)
        ^
customer.h:32:8: note:   no known conversion for argument 1 from ‘Address’ to ‘Address&’
In file included from order.cpp:3:0:
order.h: In member function ‘void Order::setCustomer(Customer&)’:
order.h:39:51: error: no matching function for call to ‘Customer::setAddress(Address)’
    this->customer.setAddress(customer.getAddress());
                                                   ^
order.h:39:51: note: candidate is:
In file included from order.h:7:0,
                 from order.cpp:3:
customer.h:32:8: note: void Customer::setAddress(Address&)
   void setAddress(Address &address)
        ^
customer.h:32:8: note:   no known conversion for argument 1 from ‘Address’ to ‘Address&’
In file included from assign05.cpp:16:0:
order.h: In constructor ‘Order::Order(Product&, int, Customer&)’:
order.h:25:51: error: no matching function for call to ‘Customer::setAddress(Address)’
    this->customer.setAddress(customer.getAddress()); 
.........

where the rest of the error can be found here

Now I am not sure what I am doing wrong but I feel that it has to do with how I am passing around the instance address and then trying to access it through the get function. Any insights on this would be much appreciated. Thanks

l33tHax0r
  • 1,384
  • 1
  • 15
  • 31
  • You are not passing the address. `Address getAddress() { return address; }` returns a copy of the variable `address`. `Address& getAddress()` returns a reference to that internal variable, but now you are getting into hot water conceptually. – Ceros May 18 '17 at 20:24
  • How would I then "cool the water" ? – l33tHax0r May 18 '17 at 20:28
  • And we are missing parts of the error. `customer.h:32:8: note: no known conversion for argument 1 from ‘Address’ to ‘Add ` this should be your clue – Ceros May 18 '17 at 20:28
  • By not returning reference to internal variable. You either return a copyof or you act like a [facade](https://en.wikipedia.org/wiki/Facade_pattern) – Ceros May 18 '17 at 20:29
  • @Ceros sorry, the error didn't copy all the way it should say `customer.h:32:8: note: no known conversion for argument 1 from ‘Address’ to ‘Address&’` – l33tHax0r May 18 '17 at 20:31
  • Since `getAddress` returns a copy and `setAddress` accept a reference only, you need to store the returned copy of `getAddress` and then use that variable for the `setAddress`. – Ceros May 18 '17 at 20:33

2 Answers2

3

Short answer: non-const lvalue reference to type Address cannot bind to a temporary of type Address.

Your Customer::getAddress returns a copy of address (temporary object/rvalue). But Customer::setAddress accepts lvalue (non-temporary object) reference.

The right solution is to make Custom::setAddress accept const lvalue reference. Since you are not modifing argument (and you should not do it) and const lvalue reference can bind to rvalue.

Note: Your code will not compile because of other error: you can't call non-const methods (getters in your case) on const object. Mark getters as const methods by adding const to end of declaration (like this: string getState() const { return state; }).

If you want to understand what is lvalue, rvalue exactly... What are rvalues, lvalues, xvalues, glvalues, and prvalues? and http://thbecker.net/articles/rvalue_references/section_01.html

fox.cpp
  • 376
  • 3
  • 5
  • +1 for the great answer @FoxCpp. People often forget (or don't even know) about lvalues and rvalues and what you are allowed to do with them per the standard. – mascoj May 18 '17 at 20:48
  • So I added const to all my get functions and then passed all and I am not longer passing the class instances by reference. – l33tHax0r May 19 '17 at 05:03
0

Since getAddress returns a copy and setAddress accept a reference only, you need to store the returned copy of getAddress and then use that variable for the setAddress

auto wAddress = customer.getAddress();
this->customer.setAddress(wAddress);
Ceros
  • 491
  • 3
  • 14