C ++ 11 virtual copy constructor

I read Mark Joshi's C ++ Design Patterns and Derivatives Pricing and implement his C ++ 11 code. Everything went pretty well until I got into Chapter 4, where he discusses virtual copy constructors.

PayOffDoubleDigital thePayOff(Low, Up); VanillaOption theOption(thePayOff, Expiry); 

The problem here is that VanillaOption contains a link to thePayOff . If this case and someone modifies thePayOff , theOption behavior can be changed involuntarily. The solution he recommends is to create a virtual copy constructor in the base class PayOffDoubleDigital , PayOff , so theOption contains its own copy:

 virtual PayOff* clone() const = 0; 

and then defined in each inherited class:

 PayOff* PayOffCall::clone() const { return new PayOffCall(*this); } 

The return of the new caught me as something that might not be appropriate in C ++ 11. So, how to handle this with C ++ 11 correctly?

+6
source share
2 answers

The solution that he advises is to create a virtual copy constructor in the PayOffDoubleDigital base class [...]

First of all, clone() not a copy constructor. The copy constructor for class X is a special member function without a return type, which usually has a signature:

 X(X const&) 

And may have a signature:

 X(X&) 

The clone() function is just a regular (virtual) function, and its specific value is recognized by you - the user - as something that creates clones of your object, but not by a compiler that has no idea what clone() does.

The return of new caught me as something that might not be appropriate in C ++ 11

It is true that using new not idiomatic in C ++ 11. In fact, in C ++ 11 you should (almost) never use new unless you are performing really low-level memory management (which you should avoid if you really not necessary) - and in C ++ 14 you can delete "almost". Unfortunately, this is probably an exceptional case when new is required.

I say this because I think that returning unique_ptr sounds like a suitable thing here (the option object must contain its own PayOff object, and it must remain alive as long as the option object is alive), and in C ++ 11 there is no function std::make_unique() (it will be there in C ++ 14):

 std::unique_ptr<PayOff> PayOffCall::clone() const { return std::unique_ptr<PayOff>(new PayOffCall(*this)); } 

Having VanillaOption (or its base class), hold unique_ptr , not a raw pointer, would be unnecessary for the delete of the PayOff object returned by clone() . In turn, without delete this object, there is no need to determine the destructor provided by the user and there is no need to take care of Rule of Three , Rule of Five or something else.

Whenever you can, follow R. Martinho Fernandes and go to the Rule of Zero .

+11
source

How often when working with property, the cleanest solution is to return a smart pointer: it guarantees the safety of exceptions (without the risk of memory leaks) and makes it clear who owns the objects.

Whether you use unique_ptr or shared_ptr is entirely up to you.

0
source

Source: https://habr.com/ru/post/946019/


All Articles