I need to copy-construct an object simultaneously changing it\'s type to another class being a member of the same class-hierarchy. I\'ve read about polymorphic copy-constructors
If you only have 2 child classes, then the easiest way is to create a conversion constructor:
class Child2: public Base
{
public:
Child2(Child1 const& child)
{
p_int = new int (*child.p_int);
a = child.a + 1;
}
};
c2 = new Child2(*c1);
If you have several Child classes, and you need to create a Child2 from any of them, then you could do something like this:
class Base
{
public:
void CopyFrom(Base* base)
{
p_int = new int (*base.p_int);
a = base.a + 1;
}
};
class ChildX: public Base
{
public:
static ChildX* CreateFrom(Base* base)
{
ChildX ch = new ChildX();
ch->CopyFrom(base);
return ch;
}
};
c2 = Child2::CreateFrom(c1);
The clone() patterns allows you to create a valid copy/clone of the object of a child class having just the base reference, e.g. in your case it allows you to do the following:
Base* basePtr = getBaseOrSomeDerivedObject();
Base* copy = basePtr.clone(); // Create a copy that is an object of an actual basePtr's type.
What you could need is a "copy-constructor" that allows you to copy from a base class, e.g.:
class Base {
public:
// [...]
Base(const Base& other) : a(other.a + 1)
{
p_int = new int(*(other.p_int));
}
// [...]
};
class Child2 : public Base {
public:
// [...]
Child2(const Base& base) : Base(base) {}
// [...]
};
int main() {
// [...]
c2 = new Child2(*c1);
c2->print();
}
Result:
Child1: 7275360:4 0
Child2: 7340936:4 1
c2 = (Child2*)c1->clone();
Here is a serious bug, and the c-style cast hides the bug.
If you use C++-style cast, then it will not hide the bug, and you will know it. In this case, the C++-style cast is : dynamic_cast
. Use it to discover the bug yourself.
As it is clear from the code thatc1-clone()
creates a clone of c1
whose type is Child1*
and clone()
returns a pointer of type Base*
(after upcasting from Child1*
), which you're trying to down-cast to Child2*
. The cast should fail if you use proper cast : dynamic_cast
.
Simplest solution would probably be to implement a Child2
constructor taking a Child1&
as parameter. Then you could simply call:
Child2* c2 = new Child2(*c1);