简体   繁体   English

具有类型转换的多态复制构造函数

[英]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类和两个子类, Child1Child2 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指向从Child1Child2 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. 我开始认为我需要实现一种类型转换机制,而不是多态的复制构造函数,但是我已经很困惑了。

EDIT: Asked a follow up here 编辑: 这里要求跟进

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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM