问题
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