0

I have 4 classes, Customer, PickyCustomer, SegmentCustomer, and Delivery.

The Delivery class has a component within it called customer, like so:

    class Delivery {
      private:
        Customer *customer;

    Delivery(Customer *cust) // constructor

each of the Customer classes have a method called getAcceptable() that is overrideable and is overridden within PickyCustomer and SegmentCustomer

From what I've read this is the correct way to call the overridden method from the Delivery class. By keeping the customer as a pointer it allows Delivery to call the child methods that override the base class.

But when trying to use unique_ptr I keep getting the error no matching function for call to 'Delivery::Delivery(std::unique_ptr<Customer>*)'

when using the following bit of code to initialize

  unique_ptr<Customer> cust1(new Customer("Name", "Home", 1000.0, 25.0, fileProduce));

  shared_ptr<Delivery> cust1Delivery(new Delivery(cust1));

Can someone explain why I am getting this error, and show how I could fix this? Thanks.

  • 1
    Explain the ownership semantics, please. Are you trying to transfer ownership of the customer pointer into `Delivery`? Or are you trying to have the delivery object simply reference it (as a raw pointer)? If the former, be aware that a customer may only have a single delivery. If the latter, just pass `cust1.get()` but be aware that the customer must exist for at least as long as the `shared_ptr` to the Delivery. Otherwise you can end up with a dangling pointer. You may want to consider storing the customer as a `shared_ptr` instead. – paddy Mar 08 '22 at 03:34
  • 1
    A `unique_ptr` is not implicitly convertible to a raw pointer. See [here](https://stackoverflow.com/questions/33274922/how-to-move-unique-ptr-to-raw-pointer) for how to release a `unique_ptr` to obtain a raw pointer. However this defeats the purposes of having a `unique_ptr` in the first place. What you are doing here might be better accomplished with references. – ChrisD Mar 08 '22 at 03:34
  • @paddy I am trying to have delivery object reference the customer object. Because all I need is a few getMethods and a mutator. I don’t need or really want to change ownership – Flip The Ewok Mar 08 '22 at 03:48
  • 1
    Right, so either store a reference instead, or obtain the raw pointer, or make the customer a shared pointer instead and store that. Provided the lifetime of the Customer exceeds that of the Delivery (at least in terms of the Delivery object _using_ it), you can get away with a reference or raw pointer. If the lifetime of each object is decoupled, then use a `shared_ptr`. If the lifetime is decoupled and customer lifetime is centrally managed, you may want to consider storing a `weak_ptr` in Delivery. – paddy Mar 08 '22 at 03:55
  • Solved! Thanks @paddy for the help! using ```get()``` worked for me. Thank you! – Flip The Ewok Mar 08 '22 at 04:00
  • @paddy will definitely work on making sure all of the lifetimes are correct! For the most part the lifetime doesn't matter too much. But I'll definitely work on improving this! – Flip The Ewok Mar 08 '22 at 04:01
  • You're welcome. You got more than you bargained for here, but you must understand that pointer lifetime is very important. The managed pointer types since C++11 (`unique_ptr`, `shared_ptr`, `weak_ptr`) all assist with making ownership clearer and reducing the frequency of accidents. So, when you're converting to a raw pointer it must be a conscious decision. That is why a conversion is not implicit. Otherwise you'd end up with people making exactly the same mistakes programmers have been making for decades. – paddy Mar 08 '22 at 04:05

1 Answers1

0

Thanks to @paddy in the comments with the help! Using the get() function worked for me.

The below works for me.

unique_ptr<Delivery> cust1Delivery(new Delivery(cust1.get()));