1

If a member of a class needs polymorphic behavior it needs to be either a pointer or a reference. If this member is initialized with a constructor parameter and should live as long as the class I see two options.

Option 1: Copy reference parameter into smart pointer

class A
{
private:
  std::unique_ptr<Type> _ptr;
public:
  A(Type& parameter) : _ptr(std::make_unique<Type>(parameter)) {}
};

Option 2: use a smart pointer as paramter

class A
{
private:
  std::unique_ptr<Type> _ptr;
public:
  A(std::unique_ptr<Type> parameter) : _ptr(parameter) {}
};

I think option 1 has the advantage that the caller can pass any object whereas option 2 does not need to copy the object. My question is now which option of the two is preferable?

5634
  • 95
  • 6
  • I don't think you can get the polymorphic behavior you want with Option 1. You won't be able to cast `_ptr` to anything other than a base class to `Type`. Because you made a copy of `Type` and not anything that `parameter` might also be. Option 2 doesn't have that bug, but you are relying on the caller to not make that same mistake. – selbie Apr 04 '20 at 18:54
  • You could make `A` a template. Your understanding of polymorphism does not seem to include compile-time polymorphism. – Tanveer Badar Apr 04 '20 at 23:09

1 Answers1

1

Option 1 is bad, because you are invoking Type copy constructor, hence loosing the information about the real type.

Option 2 is OK, but you forgot to move the unique_ptr, it should be

A(std::unique_ptr<Type> parameter) : _ptr(std::move(parameter)) {}

However, since you mentioned that polymorphic behavior is required, I assume that you would like to be able to test your application later on like that:

A system_under_test(fake_type);
ON_CALL(*fake_type, doSomething()).WillByDefault(Return(SomeResult));
system_under_test.run();

In that case, you should use the std::shared_ptr<Type> for your class field.

pptaszni
  • 5,591
  • 5
  • 27
  • 43