Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

C++11 virtual copy constructor

I'm reading C++ Design Patterns and Derivatives Pricing by Mark Joshi and implementing his code in C++11. Everything has gone pretty well until I hit chapter 4 where he discusses virtual copy constructors.

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

The problem here is that VanillaOption contains a reference to thePayOff. If that's the case and someone modifies thePayOff, the the behavior of theOption could be modified unwittingly. The solution he advises is to create a virtual copy constructor in PayOffDoubleDigital's base class, PayOff so that 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);
}

Returning new caught me as something that might be inappropriate in C++11. So what is the proper way of handling this using C++11?

like image 643
BDig Avatar asked May 28 '13 13:05

BDig


People also ask

Can a copy constructor be virtual?

The duplicate object being created with the help of Clone() virtual function which is also considered as virtual copy constructor.

Why virtual constructor is not possible in C++?

In C++, the constructor cannot be virtual, because when a constructor of a class is executed there is no virtual table in the memory, means no virtual pointer defined yet. So, the constructor should always be non-virtual.

What is clone () in C++?

In C++ copying the object means cloning. There is no any special cloning in the language. As the standard suggests, after copying you should have 2 identical copies of the same object.

What is a copy constructor can we call a virtual function from a constructor?

A copy constructor is a special type of constructor that is used to create an object that is an exact copy of the object that is passed. A virtual function is a member function that is declared in the parent class and is redefined ( overridden) in a child class that inherits the parent class.


2 Answers

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

First of all, clone() is not a copy-constructor. A copy constructor for class X is a special member function with no return type which usually has the signature:

X(X const&)

And may have the signature:

X(X&)

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

Returning new caught me as something that might be inappropriate in C++11

That's true, using new is not idiomatic in C++11. In fact, in C++11 you should (almost) never use new unless you are doing really low-level memory management (something you should avoid unless you really have to) - and in C++14, you can remove the "almost". Unfortunately, this is likely the exceptional case where new is needed.

I'm saying this because I believe returning a unique_ptr sounds like the appropriate thing to do here (the option object has to hold its own PayOff object, and that must stay alive just as long as the option object is alive), and there is no std::make_unique() function in C++11 (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 a unique_ptr rather than a raw pointer would make it unnecessary to delete the PayOff object returned by clone(). In turn, not having to delete that object means no need to define a user-provided destructor, and no need to take care about the Rule of Three, Rule of Five, or whatnot.

Whenever you can, follow R. Martinho's Fernandes's advice and go for the Rule of Zero.

like image 176
Andy Prowl Avatar answered Sep 30 '22 11:09

Andy Prowl


As often when dealing with ownership, the cleanest solution is to return a smart pointer: it both guarantees exception safety (no risk of memory leak) and makes it clear by whom the objects are owned.

Whether you'll want to use unique_ptr or shared_ptr depends entirely on you.

like image 32
syam Avatar answered Sep 30 '22 10:09

syam