1

In this code, Payment is an abstract base class of Credit. Any idea how to fix this assignment?

binary '=': no operator found which takes a right-hand operand of type 'Credit *' (or there is no acceptable conversion)

unique_ptr<Payment> p;
Credit c("<cardnumber>", "<expdate>", 9999.99);
p = &c;
Remy Lebeau
  • 555,201
  • 31
  • 458
  • 770
  • 2
    very related: https://stackoverflow.com/questions/16894400/how-to-declare-stdunique-ptr-and-what-is-the-use-of-it – NathanOliver Apr 16 '21 at 19:52
  • 2
    You're lucky. If that had succeeded the program would have deleted `c` twice. – Ted Lyngmo Apr 16 '21 at 19:54
  • Good question, and an easy mistake to make starting out with smart pointers. When you declare a local variable, you can think of it as though the function "owns" the variable. So if you want the `unique_ptr` to own it, you need to construct it inside the pointer. – Silvio Mayolo Apr 16 '21 at 19:56
  • 2
    @TedLyngmo — the program would have **deleted** the object once and **destroyed** it twice. – Pete Becker Apr 16 '21 at 20:39
  • @PeteBecker Yes, I agree. Sloppy wording on my part. – Ted Lyngmo Apr 16 '21 at 20:48

2 Answers2

3

You should use std::make_unique here:

std::unique_ptr<Payment> p = std::make_unique<Credit>("<cardnumber>", "<expdate>", 9999.99);

Remember that unique_ptr takes ownership of the pointer you give it. In your code, you allocate c as a local variable, so giving a raw pointer to that variable to a unique_ptr will cause the variable to be deleted, which is illegal.

Remy Lebeau
  • 555,201
  • 31
  • 458
  • 770
Cory Kramer
  • 114,268
  • 16
  • 167
  • 218
1

You need to allocate the Credit object using the new operator so that unique_ptr can delete it later. You are declaring c as a local variable, not via new. So even if the code could compile, it would not behave correctly at runtime.

std::unique_ptr does not have an operator= that takes a raw pointer as input, only another unique_ptr. That is why you are getting the compiler error.

If you have only a raw pointer available, you can use the unique_ptr::reset() method, eg:

unique_ptr<Payment> p;
...
Credit *c = new Credit("<cardnumber>", "<expdate>", 9999.99);
p.reset(c);

But it is better to not use a raw pointer at all, it should be wrapped in a unique_ptr from the very beginning, eg:

unique_ptr<Payment> p(new Credit("<cardnumber>", "<expdate>", 9999.99));

Or:

unique_ptr<Payment> p = std::make_unique<Credit>("<cardnumber>", "<expdate>", 9999.99);

If you want to declare and assign p separately, you can do that too, eg:

unique_ptr<Payment> p;
...
p = std::unique_ptr<Payment>(new Credit("<cardnumber>", "<expdate>", 9999.99));

Or:

unique_ptr<Payment> p;
...
p = std::make_unique<Credit>("<cardnumber>", "<expdate>", 9999.99);
Remy Lebeau
  • 555,201
  • 31
  • 458
  • 770