Реализация метода Clone () в базовом классе - PullRequest
0 голосов
/ 19 мая 2009

Вот реализация 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 ]

3 голосов
/ 19 мая 2009

В простом старом 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 снова.

0 голосов
/ 19 мая 2009

Хм, я думаю, вы можете использовать здесь шаблон Factory. I.e.:

MyClass Clone(){
    return MyClassFactory.createInstance(this.getClass(), this.member1, this.member2, ...);
}

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

0 голосов
/ 19 мая 2009

Я бы предложил вместо этого использовать конструкторы копирования (поскольку производные классы могут также вызывать конструктор копирования базовой реализации) - также удобно, поскольку это будет привычной территорией для программистов на C ++.

Возможно, вам удастся создать один метод Clone, который использует отражение для вызова самого конструктора копирования в этом случае.

Возможно, также стоит отметить, что Джеффри Рихтер сказал в книге Руководства по проектированию платформы: «Интерфейс ICloneable является примером очень простой абстракции с контрактом, которая никогда не была явно задокументирована. Некоторые типы реализуют метод Clone этого интерфейса, так что он выполняет поверхностное копирование объекта, в то время как некоторые реализации выполняют глубокое копирование, потому что метод этого интерфейса Clone никогда не был полностью задокументирован, при использовании объекта с типом, который реализует ICloneable, вы никогда не знаете, что вы собираемся получить. Это делает интерфейс бесполезным"(выделено мной)

0 голосов
/ 19 мая 2009

Не в C ++, о котором я знаю. Как вы говорите, вам нужно создать объект разного класса в каждой реализации Clone ().

...