Реализация метода 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, ...);
}

На фабрике вам нужно будет создать экземпляр подкласса на основе переданного типа класса. Так что, вероятно, он имеет те же недостатки, что и ваш подход.

Другие вопросы по тегам