Copy Object - Keep Polymorphism

Copy object - keep polymorphism

Try this:

class Super
{
public:
Super();// regular ctor
Super(const Super& _rhs); // copy constructor
virtual Super* clone() const {return(new Super(*this));};
}; // eo class Super

class Special : public Super
{
public:
Special() : Super() {};
Special(const Special& _rhs) : Super(_rhs){};
virtual Special* clone() const {return(new Special(*this));};
}; // eo class Special

Note that we have implemented a clone() function that Special (and any other derivative of Super) overrides to create the correct copy.

e.g:

Super* s = new Super();
Super* s2 = s->clone(); // copy of s
Special* a = new Special();
Special* b = a->clone(); // copy of a

EDIT: As other commentator pointed out, *this, not this. That'll teach me to type quickly.

EDIT2: Another correction.

EDIT3: I really should not post so quickly when in the middle of work. Modified return-type of Special::clone() for covariant return-types.

Copying a Polymorphic object in C++

This is still how we do stuff in C++ for polymorphic classes, but you don't need to do the explicit copy of members if you create a copy constructor (possibly implicit or private) for your objects.

class Base
{
public:
virtual Base* Clone() = 0;
};

class Derivedn : public Base
{
public:
//This is OK, its called covariant return type.
Derivedn* Clone()
{
return new Derivedn(*this);
}
private:
Derivedn(const Derivedn&) : ... {}
};

Is it possible to clone a polymorphic object without manually adding overridden clone method into each derived class in C++?

You can use this generic CRTP code

template <class Derived, class Base>
struct Clonable : Base {
virtual Base* do_clone() {
return new Derived(*static_cast<Derived*>(this));
}
Derived* clone() { // not virtual
return static_cast<Derived*>(do_clone());
}

using Base::Base;
};

struct empty {};
struct A : Clonable<A, empty> {};
struct B : Clonable<B, A> {};

It can be generalised to smart pointers and multiple bases if desired.

C# polymorphism with cloning

have your Loot class implement ICloneable

public abstract class Loot : ICloneable
{
public virtual object Clone()
{
Type type = this.GetType();
Loot newLoot = (Loot) Activator.CreateInstance(type);
//do copying here
return newLoot;
}
}

C++ Copying vector of pointers with polymorphism

For A* ptr = &B(77);, B(77) is a temporary object which will be destroyed when the expression finished, and then ptr will become a dangled pointer.

For

A* CreateCopy()
{
A tmp = A(member); // tmp: member = 77, name = "Base"
return &tmp; // &tmp: member = 77, name = ""
}

tmp is a local variable which will be destroyed when out of the scope of the function, that means CreateCopy() will return a dangled pointer.

Is it possible to perform the copy without using the "new" operator? It seems like memory leaks are more likely to happen while using this operator.

You could use smart pointer to avoid manual memory management. Such as std::unique_ptr or std::shared_ptr.

Copy constructor in polymorphism in C#

You can use an overridden virtual Copy method instead of a copy constructor.

public class BaseClass
{
public BaseClass()
{
}

public virtual BaseClass ShallowCopy()
{
return new BaseClass();
}

public virtual string GetMSG()
{
return "Base";
}
}

public class DrivenClass : BaseClass
{
public string MSG { get; set; }

public DrivenClass(string msg)
{
MSG = msg;
}

public override BaseClass ShallowCopy() {
return new DrivenClass(this.MSG);
}

public override string GetMSG()
{
return MSG;
}
}

Then call it like this:

D = new DrivenClass("Driven");
B = D.ShallowCopy();

This will work because calling a virtual method always calls the actual overriden implementation in the subclass, even when called from the baseclass interface.

What is the purpose of copying an object in object oriented programming?

There are many situations where you might need to duplicate an object.

  • For convenience: When you create an object, you usually need to initialize it, either in the form of calling methods to set values, or in the form of passing parameters to the constructor. Sometimes, performing all this initialization might amount to a lot of work. If you want a new object B which only differs from another object A by a single value, then it may be easier to get a copy of A as B and change a single value of B, rather than to create B from scratch.

  • Because logic requires it: When a chess playing algorithm wants to make its next move, it may internally make many copies of the current board, modify each one of them with one of many possible moves that it may make, evaluate each one of the new boards using some heuristics, pick the best, and then use that as the new current board.

  • To be defensive: When a Person object is asked for its DateOfBirth, it may not necessarily return a reference to its own DateOfBirth, because someone might then alter the Date object, thus altering the Person's DateOfBirth. So, the Person object is likely to return a defensive copy of its DateOfBirth.

  • To take a snapshot: If I have a list of event observers to invoke, I might want to take a (shallow) snapshot copy of the list before starting to invoke the observers, because an observer may decide to unregister itself while I am processing the list, which will have disastrous consequences. (ConcurrentModificationException, look it up.)

How can I copy a templated instance with a virtual base class?

Traditionally, it's done by adding clone method to the Base:

struct Base {
virtual std::unique_ptr<Base> clone() const = 0;
virtual ~Base() = default;
};

CRTP can be used to automate overriding this method here:

template<class Child> struct Clonable: Base {
std::unique_ptr<Base> clone() const final {
auto &asChild = *static_cast<Child const *>(this);
return std::make_unique<Child>(asChild);
}
};

struct Foo: Clonable<Foo> {};

Deep Copy/Clone methods in a C# class hierarchy - Do I need a concrete implementation everywhere?

Could use an extension method and do incremental cloning

public static class DeepCopyExt
{
public static T DeepCopy<T>(this T item)
where T : ThingBase, new()
{
var newThing = new T();
item.CopyInto(newThing);
return newThing;
}
}

public abstract class ThingBase
{
public int A { get; set; }

public virtual void CopyInto(ThingBase target)
{
target.A = A;
}
}

public class ThingA : ThingBase
{
}

public class ThingB : ThingA
{
public int B { get; set; }

public override void CopyInto(ThingBase target)
{
var thingB = target as ThingB;

if(thingB == null)
{
throw new ArgumentException("target is not a ThingB");
}

thingB.B = B;
base.CopyInto(thingB);
}
}

class Program
{
static void Main(string[] args)
{
var b = new ThingB
{
A = 1,
B = 3
};

//c is ThingB
var c = b.DeepCopy();

var b1 = new ThingA
{
A = 1,
};

//c1 is ThingA
var c1 = b1.DeepCopy();

Debugger.Break();
}
}


Related Topics



Leave a reply



Submit