Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to avoid clone() boilerplate code for polymorphic objects in c++

If I want to clone a polymorphic object in C++ (i.e. an instance of a class A which is derived from some other class B), the easiest way seems to give B a virtual clone member function, that has to be overridden by A and looks like this

A* clone(){
    return new A(*this);
}

My problem is, that I find this unnecessary boilerplate code, as this is almost always needed, if one wants to use run-time polymorphic features of C++. How can it be circumvented?

Thanks

Why I need this:

My use case can be abstracted to the following example: I have a class Integral, which evaluates the integral of some function. Do do this, they have a member which is a pointer to the class MathFunction. This abstract class contains a pure virtual function evaluate which takes one argument. I I wanted to implement the power function I would create a class PowFunction : class MathFunction. This class would have a member exponent and the function evaluate would look like this:

double evaluate(x){
    return pow(x,exponent);
}

As stated the member MathFunction of class Integral has to be polymorhpic, which requires it to be a pointer. To answer the questions of the commenters with another question. Why wouldn't I want to be able to make copies of MathFunction objects?

I really want the Integral to "own" its MathFunction, meaning, that it can alter the parameters (like exponent) without changing the MathFunction of any other Integral object. This means every Integral needs to have its own copy. This requires a clone() function for MathFunctions, doesn't it?

One alternative i thought of: If several Integral objects can share the same MathFunction via a pointer to the same address, I could create copies of Integral objects without the need to copy the MathFunction. But in this case I would have to make all the properties const or somehow readonly, which is not very elegant either. Also, which Integral object should handle delete the MathFunction object?

Why you need this:

Are you seriously saying, that as soon as you work with polymorphic objects you don't ever need a copy operation? What makes polymorphic object different from other objects in this respect?

Using this argumentation, you could also throw the copy constructor and copy assignment operator out of the C++ standard!

like image 590
Johannes Gerer Avatar asked Dec 16 '22 13:12

Johannes Gerer


2 Answers

Reduce the need to clone polymorphic objects. Really, I rarely find the need for this in my own code, and the comments on the question suggest that I'm hardly alone in the opinion that if you find yourself cloning everything, you're probably designing it wrong.

Of course, never to be unhelpful, you could indeed use the Curiously Recurring Template Pattern.

template<typename T> struct Clone {
    virtual T* clone() { return new T(static_cast<const T&>(*this)); }
};
like image 128
Puppy Avatar answered Jan 11 '23 23:01

Puppy


I handled this issue with a macro... it's ugly, but it works to avoid inconsistencies.

/** An interface that can be inherited by any class that wants to provide a Clone()
  * method that will return a copy of itself.
  */
class ICloneable
{
public:
   ICloneable() {}
   virtual ~ICloneable() {}

   virtual ICloneable * Clone() const = 0;
};
#define DECLARE_STANDARD_CLONE_METHOD(class_name) virtual ICloneable * Clone() const {new class_name(*this);}

[...]
public MyCloneableClass : public ICloneable
{
public:
   MyCloneableClass() {}

   DECLARE_STANDARD_CLONE_METHOD(MyCloneableClass);
};
like image 42
Jeremy Friesner Avatar answered Jan 12 '23 00:01

Jeremy Friesner