Newsgroup: it.comp.lang.c++
Titolo: problemino (credo) sulle funzioni virtuali

Ciao a tutti,
supponiamo di avere la famosa classe shape a cui appartengono cilindro,
piano e sfera.
Queste shape sono disposte nello spazio e quindi la classe base avra' una
traslazione
e una rotazione rispetto a un sistema di riferimento comune. Supponiamo ora
di voler
calcolare la distanza tra 2 shape generiche. Come faccio? Se scrivo una
funzione
virtuale in shape e la particolarizzo in ognuna di esse, dovro' comunque, al
loro interno,
effettuare un switch/case per capire la seconda shape di che tipo e'. O
sbaglio?
Chiaramente non vorrei fare switch/case.
Grazie in anticipo.
--
Tiberio Grasso
e-mail: 
gras...@tecnomare.it

Chiaramente non vorrei fare switch/case.
Potresti ricorrere ad una tecnica nota come double dispatching che consente
un polimorfismo su due argomenti anche se forse avresti poi qualche problema
in fase di manutenzione (aggiungendo una nuova classe dovresti aggiungere nuove
cose anche nelle precedenti classi).
Potresti provare con il pattern visitor che in qualche modo e` legato al multiple
dispatching, pero` cosi` su due piedi non saprei dirti se fa al tuo caso anche perche`
non lo ricordo bene.
Alternativamente potresti cercare di calcolare dall'esterno la distanza...
potresti pensare di disporre di un metodo tramite cui avere i punti di cui calcolare
la distanza, operazione che a questo punto potresti eseguire con una normale funzione.
Paolo
------------------------------------------------------------------
  Paolo Marotta
  Computer Science, University of Pisa
  home:   
http://www.cli.di.unipi.it/~marotta
  G: Per concludere, possiamo chiedervi di commentare
     l'attuale panorama informatico?
  I: /* l'attuale panorama informatico */
------------------------------------------------------------------

 Chiaramente non vorrei fare switch/case.
Intanto dovresti stabilire cosa significa 'distanza tra due shape'.
Mettiamo sia la distanza tra i due centri. Allora in ogni derivata ci
sarebbe un metodo che restituisce le coordinate di questo centro. E
nella classe base avresti invece un metodo che calcola la distanza tra
la shape corrente ed un'altra shape utilizzando l'informazione
restituita dal metodo di cui sopra. Forse questa stessa tecnica potrebbe
essere utilizzata anche nel caso che il calcolo della distanza sia più
complesso (come temo).
EMG

Ciao,
volevo precisare che la distanza tra 2 shape e' la distanza
minima tra i due oggetti (quindi tra 2 loro punti che non conosco a priori),
E' chiaro quindo che il calcolo della distanza dipende dagli oggetti
stessi.
Grazie e ciao.



Il problema e' assai complesso e non lo puoi risolvere, come hai gia'
capito, con una semplice funzione virtuale. Il problema sta nel fatto che il
sistema di calcolo e' differente a seconda delle combinazioni di shape a
confronto.
Si potrebbe arrivare alla soluzione per approssimazioni successive. Mi
spiego meglio.
Mettiamo il tipo
    struct TPoint {
        double x, y, z;
    };
Ogni tua shape dovrebbe avere 2 funzioni virtuali:
  virtual double CalcPtDistance(const TPoint& srcPt, TPoint& resPt);
  virtual TPoint GetStartDstPoint();
La prima mi pare ovvia: calcola la distanza minima di un punto da una shape.
In resPt deve essere restituito il punto dello shape in cui la distanza
minima viene calcolata.
La seconda restituisce, per ogni shape, il punti di partenza per il calcolo
approssimativo. Potrebbe essere il centro della shape (o il baricentro).
L'algoritmo di calcolo della distanza fra 2 shape potrebbe essere cosi'
definito:
#define shape_dst_epsilon 0.0001
double TGenericShape::CalcMinDistance(TGenericShape* otherShape)
{
    TGenericShape *shape1 = this,
                                 *shape2 = otherShape;
    TPoint s1Pt = shape1->GetStartDstPoint();
    TPoint s2Pt;
    double minDist = "valore molto grande";
    do {
        double prevDist = minDist;
        minDist = shape2->CalcPtDistance(s1Pt, s2Pt);
        //Inverte le shapes e i punti
        Swap(shape1, shape2);
        Swap(s1Pt, s2Pt);
    } while( fabs(minDist - prevDist) > shape_dst_epsilon);
    return (minDist);
}
Se le cose sono fatte bene e l'epsilon e' scelto con coerenza (vedi tu a
seconda delle tue unita') l'algoritmo in questione dovrebbe stabilizzarsi
dopo poche iterazioni.
Puoi anche aggiungere un controllo con un numero massimo di iterazioni per
evitare blocchi.
Ciao,
Stefano

calcolare la distanza tra 2 shape generiche. Come faccio? Se scrivo una
Beh, puoi utilizzare le info della sola classe di base, considerando solo la
traslazione. Avendo due generiche shape hai anche le loro due posizioni
(riferite all'origine), Da quelle calcolare la distanza tra due punti nello
spazio non dovrebbe essere un problema.
Senza switch - case di sorta (sapere di che tipo sia la shape non ha
importanza), ti basta una funzione membro della classe di base che ti
fornisca le coordinate. Non hai bisogno di virtualizzare questa funzione, in
quanto la posizione di un oggetto non dipende dalla forma dell'oggetto
stesso. (Ovviamente mi riferisco alla posizione dei centri di massa degli
oggetti).
---
Bye, Fox.