Pergunta

Aqui está uma implementação Clone() para minha classe:

    MyClass^ Clone(){
        return gcnew MyClass(this->member1, this->member2);
    }

Agora eu tenho cerca de 10 classes derivadas de MyClass. A implementação é o mesmo em cada caso. Devido ao fato de que eu preciso gcnew chamada com o nome real da classe em cada caso, eu sou obrigado a criar 10 implementações quase idênticas de Clone().

Existe uma maneira de escrever um método Clone() único na classe base que servirá todas as 10 classes derivadas?

Editar: Existe uma maneira de chamar o construtor de uma classe através de um de seus objetos? De uma forma que irá chamar o construtor real classe derivada. Algo como:

MyClass ^obj2 = obj1->Class->Construct(arg1, arg2);

Estou fazendo isso em C ++ / CLI, mas respostas de outros idiomas são bem-vindos.

Foi útil?

Solução

Na planície antiga C ++, você pode fazer isso com o polimorfismo em tempo de compilação (o padrão modelo curiosamente recorrente). Assumindo as suas classes derivadas são copiável, você pode apenas escrever:


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));
    }
};

Em seguida, usá-lo como:


class MyClass: public BaseHelper<MyClass>
{
    //MyClass automatically gets a Clone method with the right signature
};

Note que você não pode derivar de uma classe novamente e tê-lo funcionar perfeitamente -. Você tem que "design no" a opção para derivar novamente por templates as classes intermediárias, ou iniciar Clone-escrevendo re novamente

Outras dicas

Não em C ++ que eu estou ciente. Como você disse, você precisa criar um objeto de uma classe diferente em cada implementação de Clone ().

Hm, acho que você pode usar o padrão de fábrica aqui. Ou seja:.

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

Na fábrica, você teria que criar instância da subclasse com base no tipo de classe passou. Então, provavelmente, ele tem as mesmas desvantagens como a sua abordagem.

Gostaria de sugerir o uso de construtores de cópia em vez (como as classes derivadas pode chamar construtor de cópia da implementação base também) - também acessível, pois será um território familiar para programadores C ++.

Você pode ser capaz de criar um único método Clone que usa reflexão para chamar o construtor de cópia de si mesmo neste caso.

Possivelmente importante notar também que Jeffrey Richter diz no livro Framework Design Guidelines, "A interface ICloneable é um exemplo de uma abstração muito simples, com um contrato que nunca foi documentado explicitamente. Alguns tipos de implementar o método Clone deste interface para que ele executa uma cópia superficial do objeto, enquanto que algumas implementações executar uma cópia profunda. Porque o que método Clone desta interface deve fazer nunca mais foi totalmente documentado, ao usar um objeto com um tipo que implementa ICloneable, você nunca sabe o que você vai conseguir. Isso faz com que a interface inútil "(grifo meu)

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top