Il problema reale nasce dal voler rappresentare un punto geometrico, tenendo conto della possibilità che la sua posizione nello spazio possa essere espressa con diversi sistemi (coordinate cartesiane, polari, ecc), e con possibilità di passare da un sistema all'altro.
Io ho organizzato così:
classe astratta AbstractCoordinate da cui derivo i sistemi di coordinate (cartesiane2d, cartesian3D, polari,ecc), in cui implemento i metodi set, get, getType(mi da il tipo di coordinata), ecc.
Classe Point, che ha come dato membro mCoordinate di tipo AbstractCoordinate*.
La classe Point quindi richiama i metodi di mCoordinate per fare set, get.
La classe Point inoltre implementa il metodo pubblico convert(/*tipo di destinazione*/) che serve ad effettuare la conversione da un tipo di coordinate ad un altro.
codice:
class Point
{
public:
//costruttori vari
//distruttore
//metodi set, get, getType
//metodo per la conversione delle coordinate
void convert(AbstractCoordinateConverter::Converter convert_to);
/* convert_to e' il parametro che permette la scelta del nuovo tipo di coordinate*/
private:
AbstractCoordinate* mCoordinate;
}
Nella fattispecie il metodo convert di Point è fatto così
codice:
void convert(AbstractCoordinateConverter::Converter convert_to)
{
//creo l'oggetto converter
AbstractCoordinateConverter* converter = CoordinateConverterFactory::makeCoordinateConverter(convert_to);
//l'oggetto converter prende il dato membro e lo trasforma
converter->convert(mCoordinate);
//elimino l'oggetto converter
delete(converter);
}
il problema della conversione è quindi delegato a un oggetto temporaneo converter, in cui il metodo convert è così implementato
codice:
//metodo convertitore implementato in una delle classi converter
//prende come parametro un puntatore a un oggetto di tipo AbstractCoordinate*
virtual void convert(AbstractCoordinate* coordinate)
{
switch(coordinate->getType())//lo switch è fatto prendendo come parametro di scelta il tipo di AbstractCoordinate realmente passato
{
case AbstractCoordinate::Cartesian:
std::cout<<"\nE' gia' Cartesian\n";
break;
case AbstractCoordinate::Cartesian3D:
fromCartesian3D(coordinate);//è il metodo privato dell'oggetto converter che implementa la conversione a partire da una coordinata di tipo Cartesian3D
break;
case AbstractCoordinate::Polar:
fromPolar(coordinate);//è il metodo privato dell'oggetto converter che implementa la conversione a partire da una coordinata di tipo Polar
break;
}
}
riporto quindi l'implementazione del metodo fromCartesian3D(coordinate), l'altro è simile come concezione
codice:
void CoordinateConverterToCartesian::fromCartesian3D(AbstractCoordinate* coordinate)
{
//memorizzo in un vettore temporaneo i dati della coordinata di tipo 3D (x,y e z)
std::vector<double> array_to_convert(coordinate->get());
//elimino la z perche' in questo caso sto trasformando in cartesiano 2D, quindi solo x e y
array_to_convert.pop_back();
//cancello il coordinate esistente che è di tipo 3D
delete(coordinate);
coordinate=0;//questo è necessario o posso evitarlo
//creo un nuovo oggetto di tipo cartesiano 2D dandogli in input i valori delle coordinate gia' opportunamente trasfromati
coordinate = new CartesianCoordinate(array_to_convert);
}
avendo messo in ogni metodo da me creato una macro che stampa a video il nome della classe e il nome del metodo invocato, il progr si pianta quando è stato chiamato il costruttore del nuovo oggetto.
Grazie.