Я работаю над программой на C ++, но у меня возникают проблемы с множественным наследованием при использовании клонирования. Проблема (в упрощенном виде) заключается в следующем.
Я хочу иметь возможность клонировать все объекты, полученные из класса Base.
class Base{
public:
virtual Base* clone()const=0;
};
Я хочу определить два других класса, производных от Base, которые оба являются абстрактными, то есть я не могу определить функцию клона, но я должен объявить их некоторым образом (я хочу убедиться, что если я клонирую Derived *, я получу назад производные * а не базовые *, т.е. я хочу избежать кастинга в точке приложения)
class Derived1: public virtual Base{
public:
virtual Derived1* clone()const=0;
};
class Derived2: public virtual Base{
public:
virtual Derived2* clone()const=0;
};
Проблема возникает, когда я объявляю четвертый класс, который унаследован от Derived1 и Derived2:
class Derived3: public Derived1,public Derived2{
protected:
int b;
public:
Derived3():b(3){};
Derived3(Derived3 const& l_B) {b=l_B.b;};
virtual Derived3* clone()const{return new Derived3(*this);}
;
};
В этом случае я получу от компилятора Visual C ++ 2010 C2250: «Derived3»: неоднозначное наследование «Derived1 * Base :: clone (void) const». Если я объявляю clone () в Derived1 и Derived2 не чисто виртуальным, но без определения, ошибка остается той же:
class Base{
public:
virtual Base* clone()const=0;
};
class Derived1: public virtual Base{
public:
virtual Derived1* clone()const;
};class Derived2: public virtual Base{
public:
virtual Derived2* clone()const;
};
class Derived3: public Derived1,public Derived2{
protected:
int b;
public:
Derived3():b(3){};
Derived3(Derived3 const& l_B) {b=l_B.b;};
virtual Derived3* clone()const{return new Derived3(*this);}
;
};
Использование виртуального наследования в Derived3 также не поможет, и я не могу найти способ его решить, у меня просто заканчиваются идеи. Очень важно, чтобы все классы возвращали указатель одного типа, например Я хочу сделать позже:
Derived3 test;
Derived1* test2=&test;
Derived1* test3=test2->clone();
и я хочу избежать
Derived3 test;
Derived1* test2=&test;
Derived1* test3=dynamic_cast<Derived1*>(test2->clone());
Если у кого-то есть идея или решение, я буду признателен за это!
Идея состоит в том, чтобы иметь защищенный виртуальный метод clone_impl
в Base
и публичный не виртуальный clone
:
class Base
{
protected:
virtual Base* clone_impl() const = 0;
public:
Base* clone() const
{
return clone_impl();
}
};
и для каждый производный класс обеспечивают clone_impl
когда класс не абстрактный и не виртуальная оболочка clone
за все производные классы:
class DerivedX : ...
{
protected:
// only when not abstract:
virtual Base* clone_impl() const
{
return new DerivedX(*this);
}
public:
// in each derived class
DerivedX* clone() const
{
return static_cast<DerivedX*>(clone_impl());
}
};
Других решений пока нет …