Domanda

Ecco un'implementazione Clone() per la mia classe:

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

Ora ho circa 10 classi derivate da MyClass. L'attuazione è la stessa in ogni caso. A causa del fatto che ho bisogno di chiamare gcnew con il nome di classe effettiva in ogni caso, sono tenuto a creare 10 implementazioni quasi identiche di Clone().

C'è un modo per scrivere un metodo Clone() sola nella classe base che servirà tutti i 10 classi derivate?

Modifica C'è un modo per invocare il costruttore di una classe tramite uno dei suoi oggetti? In un modo che richiamerà il costruttore attuale classe derivata. Qualcosa di simile:

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

Lo sto facendo in C ++ / CLI, ma le risposte da altre lingue sono i benvenuti.

È stato utile?

Soluzione

In pianura vecchio C ++, è possibile farlo con il polimorfismo in fase di compilazione (il modello modello curiosamente ricorrenti). Assumendo che il classi derivate sono copiabile, si può semplicemente scrivere:


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

Quindi utilizzare le cose come:


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

Si noti che non è possibile derivare da una classe di nuovo e farlo funzionare senza soluzione di continuità -. Dovete "design" la possibilità di ricavare nuovamente templating classi intermedie, o iniziare di nuovo ri-scrittura Clone

Altri suggerimenti

Non in C ++ che io sappia. Come dici tu, è necessario creare un oggetto di una classe diversa in ogni implementazione di clone ().

Hm, penso che si può utilizzare pattern Factory qui. Cioè:.

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

In fabbrica, si dovrà creare un'istanza di sottoclasse in base al tipo di classe passato. Quindi probabilmente ha gli stessi svantaggi come il vostro approccio.

Io suggerirei di usare costruttori di copia, invece (come classi derivate possono chiamare costruttore di copia della implementazione di base pure) - anche a portata di mano, in quanto sarà un territorio familiare per i programmatori C ++.

Potreste essere in grado di creare un unico metodo Clone che utilizza la reflection per chiamare il costruttore di copia su se stesso in questo caso.

Forse anche la pena notare che Jeffrey Richter ha detto nel libro orientamenti quadro di progettazione, "L'interfaccia ICloneable è un esempio di una semplice astrazione con un contratto che non è mai stato documentato in modo esplicito. Alcuni tipi di implementare il metodo Clone di questa interfaccia in modo che esso esegue una copia dell'oggetto, mentre alcune implementazioni eseguire una copia profonda. Perché ciò che il metodo Clone di questa interfaccia dovrebbe fare non è mai stato pienamente documentato, quando si utilizza un oggetto con un tipo che implementa ICloneable, non si sa mai quello che si vuole ottenere. Questo rende l'interfaccia inutile "(sottolineatura mia)

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top