Cast one derrived class to another without changing base class

左心房为你撑大大i 提交于 2019-12-12 15:53:18

问题


I have several child classes all having same parent. Each child class can be constructed using some data that is contained in parent object. I would like to cast one child to be another child using info contained in base object (without modifying base object).

Currently it is implemented as illustrated in following example:

#include <iostream>

using namespace std;

class Data {};
class base
{
public:
    base()  {}
    base(Data input) : data(input)  {}
    virtual ~base() {   cout << "Deleting :" << this->name() << endl;   }
    template<class T> static base* CastToDerrived(base* object)
    {
        T* output = new T(object->data);
        delete object;
        return output;
    }
    virtual const char* name()  {return "base";}
    Data data;
};

class derrived1 : public base
{
public:
    derrived1() {}

    derrived1(Data input): base(input){}
    ~derrived1(){cout << "Deleting :" << this->name() << endl;}
    const char* name(){return "derrived1";}
};

class derrived2 : public base
{
public:
    derrived2(){}
    derrived2(Data input): base(input){}
    ~derrived2(){cout << "Deleting :\t" << this->name() << endl;}
    const char* name(){return "derrived2";}
};

int main(int argc, char *argv[])
{
    base* object = new derrived1();
    cout << "Created :\t"<<object->name()<<endl;
    object = base::CastToDerrived<derrived2>(object);
    cout << "Casted to :\t"<<object->name()<<endl;
}

Which outputs:

Created :   derrived1
Deleting :derrived1
Deleting :base
Casted to : derrived2

However, this requires base class to be destroyed and created again, which I would like to avoid - I would like to destroy derrived1, use base to construct derrived2, but keep the base class intact. What is the best way to do that?

(There are several derived classes, base class provides common interface for all, some derived class will be added later without modifying the base).


回答1:


you can't destroy the derived class an keep the base class because it's the same instance. we can demonstrate this using the folowing code

#include <iostream>

using namespace std;

class Data {};
class base
{
public:
    base()
    {
        printf("base pointer = %08X\n", this);
    }
};

class derrived1 : public base
{
public:
    derrived1()
    {
        printf("derrived1 pointer = %08X\n", this);
    }
};

int main(int argc, char *argv[])
{
    base* object = new derrived1();
    delete object;
    return 0;
}

the output will show that base an derived1 is the same pointer on the other hand you use some tricky code to achieve what you want. the idea is to use a pointer to Data class instead of a variable. your code will become then as folowing

#include <iostream>

using namespace std;

class Data {};
class base
{
public:
    base(){data = new Data}
    base(Data* input) : data(input)  {}
    virtual ~base() {   cout << "Deleting :" << this->name() << endl;   }
    template<class T> static base* CastToDerrived(base* object)
    {
        T* output = new T(object->data);
        delete object; 
        return output;
    }
    virtual const char* name()  {return "base";}
    Data* data;
};

class derrived1 : public base
{
public:
    derrived1() {}

    derrived1(Data* input): base(input){}
    ~derrived1(){cout << "Deleting :" << this->name() << endl;}
    const char* name(){return "derrived1";}
};

class derrived2 : public base
{
public:
    derrived2(){}
    derrived2(Data* input): base(input){}
    ~derrived2(){cout << "Deleting :\t" << this->name() << endl;}
    const char* name(){return "derrived2";}
};

int main(int argc, char *argv[])
{
    base* object = new derrived1();
    cout << "Created :\t"<<object->name()<<endl;
    object = base::CastToDerrived<derrived2>(object);
    cout << "Casted to :\t"<<object->name()<<endl;
}

i wish this will help.



来源:https://stackoverflow.com/questions/15843549/cast-one-derrived-class-to-another-without-changing-base-class

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!