Реализация метода Clone() в базовом классе
Вот Clone()
реализация для моего класса:
MyClass^ Clone(){
return gcnew MyClass(this->member1, this->member2);
}
Теперь у меня есть около 10 классов, полученных из MyClass
, Реализация одинакова в каждом случае. В связи с тем, что мне нужно позвонить gcnew
с фактическим именем класса в каждом случае, я должен создать 10 почти идентичных реализаций Clone()
,
Есть ли способ написать один Clone()
метод в базовом классе, который будет обслуживать все 10 производных классов?
Изменить: Есть ли способ вызвать конструктор класса через один из его объектов? Таким образом, будет вызываться фактический конструктор производного класса. Что-то вроде:
MyClass ^obj2 = obj1->Class->Construct(arg1, arg2);
Я делаю это на C++/CLI, но ответы от других языков приветствуются.
4 ответа
В простом старом C++ вы можете сделать это с полиморфизмом во время компиляции (любопытно повторяющийся шаблон). Предполагая, что ваши производные классы являются копируемыми, вы можете просто написать:
class Base
{
public:
virtual Base* Clone() const = 0;
//etc.
};
template <typename Derived>
class BaseHelper: public Base
{
//other base code here
//This is a covariant return type, allowed in standard C++
Derived * Clone() const
{
return new Derived(static_cast<Derived *>(*this));
}
};
Тогда используйте это как:
class MyClass: public BaseHelper<MyClass>
{
//MyClass automatically gets a Clone method with the right signature
};
Обратите внимание, что вы не можете снова получить класс из класса и заставить его работать без сбоев - вам нужно "спроектировать" опцию для получения производного класса с помощью шаблонов промежуточных классов или начать переписывать Clone
снова.
Вместо этого я бы предложил использовать конструкторы копирования (так как производные классы могут также вызывать конструктор копирования базовой реализации) - также удобно, так как это будет привычной территорией для программистов на C++.
Возможно, вам удастся создать один метод Clone, который использует отражение для вызова самого конструктора копирования в этом случае.
Возможно, также стоит отметить, что Джеффри Рихтер сказал в книге "Руководства по разработке инфраструктуры": "Интерфейс ICloneable - это пример очень простой абстракции с контрактом, который никогда не был явно задокументирован. Некоторые типы реализуют этот интерфейс. Clone
метод, так что он выполняет поверхностную копию объекта, в то время как некоторые реализации выполняют глубокую копию. Потому что этот интерфейс Clone
метод должен был никогда полностью не документироваться, когда используется объект с типом, который реализует ICloneable
Никогда не знаешь, что получишь. Это делает интерфейс бесполезным" (выделено мое)
Не в C++, о котором я знаю. Как вы говорите, вам нужно создать объект другого класса в каждой реализации Clone().
Хм, я думаю, вы можете использовать здесь шаблон Factory. То есть:
MyClass Clone(){
return MyClassFactory.createInstance(this.getClass(), this.member1, this.member2, ...);
}
На фабрике вам нужно будет создать экземпляр подкласса на основе переданного типа класса. Так что, вероятно, он имеет те же недостатки, что и ваш подход.