2009-09-28 60 views
10

Supponiamo che io ho il seguente (caso semplificato):costruttore di copia: una copia profonda di una classe astratta

class Color; 

class IColor 
{ 
public: 
    virtual Color getValue(const float u, const float v) const = 0; 
}; 

class Color : public IColor 
{ 
public: 
    float r,g,b; 
    Color(float ar, float ag, float ab) : r(ar), g(ag), b(ab) {} 
    Color getValue(const float u, const float v) const 
    { 
     return Color(r, g, b) 
    } 
} 

class Material 
{ 
private: 
    IColor* _color; 
public: 
    Material(); 
    Material(const Material& m); 
} 

Ora, c'è un modo per me di fare una copia completa del riassunto ICOLOR nella copia costruttore Materiale? Cioè, voglio che i valori di qualsiasi m._color possano essere (un colore, una trama) da copiare, non solo il puntatore a IColor.

risposta

7

È possibile aggiungere una funzione clone() all'interfaccia.

1

Dovrai aggiungere quel codice tu stesso al costruttore di copie Materiale. Quindi codice per liberare l'IColor assegnato nel distruttore.

Dovrai anche aggiungere un distruttore virtuale a IColor.

L'unico modo per eseguire automaticamente una copia profonda è quello di memorizzare un colore direttamente anziché un puntatore su un IColor.

+0

Perché archiviare un puntatore su IColor disabiliterà la copia profonda? –

+0

Poiché per impostazione predefinita verrà semplicemente copiato l'indirizzo del puntatore nell'indirizzo del puntatore copiato. Non copierà ciò che viene puntato e quindi regolerà nuovamente il puntatore. Luca ha il miglior suggerimento nel creare una funzione clone() chiamata dal costruttore di copie. –

0

Aggiunta di un metodo clone() per colore è probabilmente la cosa migliore, ma se non si dispone di tale opzione, un'altra soluzione potrebbe essere quella di usare dynamic_cast per lanciare ICOLOR * a * Colore. Quindi è possibile richiamare il costruttore della copia di colore.

+0

Ma non sai se è un colore o una trama, come puoi allora dynamic_cast? – Barth

+0

Se l'oggetto non è di tipo color, dynamic_cast (_color) restituirà null. (Il cast dinamico/rtti può rilevare quale sia il tipo effettivo fintanto che la classe ha almeno un metodo virtuale). Quindi quello che puoi fare è testare le possibilità. Non è divertente, e quasi sempre peggio di usare un metodo clone(), ma ci sono situazioni rare in cui devi fare qualcosa di simile. –

Problemi correlati