I have base class like this:
class Base{
public:
virtual Base *createNew(){
auto newItem = new Base();
setNew(newItem);
return newItem;
};
void setNew(Base *item){
item->value = value;
};
private:
int value;
};
A number of derived classes are shown below, each of which has a createNew
interface that returns a derived object.
class Derive1 : public Base{
Derive1 *createNew(){
auto newItem = new Derive1();
setNew(newItem);
return newItem;
};
void setNew(Derive1 *item){
Base::setNew(item);
item->value1 = value1;
};
private:
int value1;
};
class Derive2 : public Base{
Derive2 *createNew(){
auto newItem = new Derive2();
setNew(newItem);
return newItem;
};
void setNew(Derive2 *item){
Base::setNew(item);
item->value2 = value2;
};
private:
int value2;
};
class Derive3 : public Base{
Derive3 *createNew(){
auto newItem = new Derive3();
setNew(newItem);
return newItem;
};
void setNew(Derive3 *item){
Base::setNew(item);
item->value3 = value3;
};
private:
int value3;
};
int main(int argc, char *argv[])
{
std::list<Base *> list;
list.push_back(new Derive1);
list.push_back(new Derive2);
list.push_back(new Derive3);
list.push_back(new Derive2);
list.push_back(new Derive1);
std::list<Base *> listNew;
for(auto item : list)
{
listNew.push_back(item->createNew());
}
...
//ignore the memory leak.
}
Is there any easy way to not write every createNew
in the derived class, because they are similar, the only difference is the type. Do templates help?
CodePudding user response:
Supposedly you want to use the Curiously Recurring Template Pattern (CRTP) for this. Here is an example where we introduce template class BaseT
that inherits from Base
. Note how each derived class inherits from BaseT
passing itself as template parameter.
class Base {
public:
virtual Base* createNew() = 0;
virtual ~Base() {}
};
template <typename T>
class BaseT : public Base {
public:
Base* createNew() override {
return createDerived();
}
T* createDerived() {
auto newItem = new T();
setNew(newItem);
return newItem;
};
void setNew(T* item){
item->value = value;
setNewDerived(item);
};
virtual void setNewDerived(T* item) {}
virtual ~BaseT() {}
private:
int value;
};
class Derive1 : public BaseT<Derive1> {
public:
void setNewDerived(Derive1* item) override {
item->value1 = value1;
}
private:
int value1;
};
class Derive2 : public BaseT<Derive2> {
public:
void setNewDerived(Derive2 *item) override {
item->value2 = value2;
}
private:
int value2;
};
class Derive3 : public BaseT<Derive3> {
public:
void setNewDerived(Derive3 *item) override {
item->value3 = value3;
};
private:
int value3;
};
Is this what you are trying to do?