[英]Polymorphic copy-constructor with type conversion
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 and (hopefully) understand the idea behind it.
我已经阅读了有关多态复制构造函数的文章,并且(希望如此)了解其背后的想法。 Yet, I still don't know if this pattern applies to my case and, if so, how to implement it.
但是,我仍然不知道此模式是否适用于我的情况,如果适用,如何实施。 I think it's best if I show what I need on an example.
我认为最好在一个例子中说明我的需要。
There is a Base
class and two child classes, Child1
and Child2
. 有一个
Base
类和两个子类, Child1
和Child2
。 I need to create an object of type Child2
basing on Child1
, ie. 我需要创建类型的对象
Child2
立足Child1
,即。 most of all, I need to copy the object p_int
is pointing to from Child1
to Child2
. 最重要的是,我需要复制的对象
p_int
指向从Child1
到Child2
。 I've written a simple program to illustrate it: 我编写了一个简单的程序来说明它:
#include <iostream>
using namespace std;
class Base {
public:
Base() { p_int = new int; *p_int = 0; }
~Base() { delete p_int; }
virtual Base* clone() const = 0;
void setpInt(int val) { *p_int = val; }
void setInt(int val) { a = val; }
virtual void print() {
cout << "Base: ";
cout << (long)p_int << ":" << *p_int << " " << a << endl;
}
protected:
int* p_int;
int a;
};
class Child1 : public Base {
public:
Child1() {};
Child1(const Child1& child) {
p_int = new int (*child.p_int);
a = child.a + 1;
}
Base* clone() const { return new Child1(*this); }
void print() {
cout << "Child1: ";
cout << (long)p_int << ":" << *p_int << " " << a << endl;
}
};
class Child2 : public Base {
public:
Child2() {};
Child2(const Child2& child) {
p_int = new int (*child.p_int);
a = child.a + 1;
}
Base* clone() const { return new Child2(*this); }
void print() {
cout << "Child2: ";
cout << (long)p_int << ":" << *p_int << " " << a << endl;
}
};
int main() {
Child1* c1 = new Child1();
Child2* c2;
c1->setpInt(4);
c1->print();
c2 = (Child2*)c1->clone();
c2->print();
}
Unfortunately, the outcome is as below, ie. 不幸的是,结果如下。 there is no type conversion:
没有类型转换:
Child1: 162611224:4 0
Child1: 162611272:4 1
What exactly do I need to implement, to be able to achieve what I need? 我究竟需要实现什么才能实现我所需要的? I'm starting to think there is a type-conversion mechanism I need to implement rather than a polymorphic copy-constructor, but I'm confused already.
我开始认为我需要实现一种类型转换机制,而不是多态的复制构造函数,但是我已经很困惑了。
Simplest solution would probably be to implement a Child2
constructor taking a Child1&
as parameter. 最简单的解决方案可能是实现以
Child2
Child1&
作为参数的Child2
构造函数。 Then you could simply call: 然后,您可以简单地调用:
Child2* c2 = new Child2(*c1);
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: 如果您有几个Child类,并且需要从其中任何一个创建Child2,则可以执行以下操作:
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);
c2 = (Child2*)c1->clone();
Here is a serious bug, and the c-style cast hides the bug. 这是一个严重的错误,C样式强制转换隐藏了该错误。
If you use C++-style cast, then it will not hide the bug, and you will know it. 如果使用C ++样式的强制转换,它将不会隐藏该错误,并且您将知道它。 In this case, the C++-style cast is :
dynamic_cast
. 在这种情况下,C ++样式的转换为:
dynamic_cast
。 Use it to discover the bug yourself. 用它自己发现错误。
As it is clear from the code that c1-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*
. 从代码中可以清楚地看出,
c1-clone()
创建了一个c1
的克隆,其类型为Child1*
, clone()
返回了Base*
类型的指针(从Child1 Child1*
向上转换后),您正在尝试将其向下Child2*
为Child2*
。 The cast should fail if you use proper cast : dynamic_cast
. 如果使用正确的
dynamic_cast
将失败: dynamic_cast
。
The clone() patterns allows you to create a valid copy/clone of the object of a child class having just the base reference, eg in your case it allows you to do the following: clone()模式允许您创建仅具有基本引用的子类对象的有效副本/克隆,例如,在您的情况下,它允许您执行以下操作:
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, eg: 您可能需要一个“复制构造函数”,它允许您从基类进行复制,例如:
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
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.