Operatori di conversione

di il
5 risposte

Operatori di conversione

Parlando di classi, ho difficoltà comprendere come avviene la conversione mediante costruttore, ad es.
class complesso() {
   double re, im;
public:
   complesso(double re=0, double im=0);
   complesso operator+(complesso x, complesso y);
};
complesso::complesso(double r, double i) 
{ re=r; im=i; }
complesso operator+(complesso x)
{ 
   complesso z;
   z.re=re + x.re;
   z.im=im+y.im;
   return z;
}
Si presuppone che nella classe complesso non sia prevista la somma tra complesso e reale, quindi se avessi:
int main()
{
   complesso x, y(2, 5);
   x=y + 2.5;
   ...
}

Faccio "qualche" riflessione ad alta voce...
l'oggetto 'x' avrà i suoi due membri re e im inizializzati a zero,
A colpo d'occhio mi verrebbe da dire che il compilatore verifica che i 3 componenti della somma siano dello stesso tipo e nel caso farebbe una conversione implicita, ma forse nel nostro caso non è applicabile! Lo sarebbe se avessi avuto una somma del tipo
double= int + double, il secondo valore sarebbe oggetto di casting , giusto?
Ma qua come avviene l'interpretazione del 2.5 ? Dalla ridefinizione dell'operatore + si capisce che entrambi i termini sono di tipo class complesso? Come viene trattato?

5 Risposte

  • Re: Operatori di conversione

    double= int + double, il secondo valore sarebbe oggetto di casting , giusto?
    l'int è trasformato in double e poi sommato.
    Ma qua come avviene l'interpretazione del 2.5 ?
    In questo modo:
    
    int main()
    {
       complesso x, y(2, 5);
       x = y + 2.5; // equivale a  x=y + complesso(2.5);
       ...
    }
    
  • Re: Operatori di conversione

    [quote="shodan"]
    
    int main()
    {
       complesso x, y(2, 5);
       x = y + 2.5; // equivale a  x=y + complesso(2.5);
       ...
    }
    
    Quindi il compilatore tratta il 2o parametro della somma come una classe senza identificatore passandogli come argomento il 2.5 quindi utilizzato poi come parte reale essendo il primo membro della classe. Giusto?
    In questo processo interviene il costruttore.
  • Re: Operatori di conversione

    In linea di massima si. Quel che avviene davvero è che il compilatore cerca il metodo più adatto per fare la conversione. Trova che l'unico metodo è il costruttore, e solo perché il secondo parametro è di default (infatti se lo togli non compila, perché non sa che pesci pigliare), effettua la conversione etc. etc.
    Se il compilatore trovasse un metodo migliore (ad esempio
    
    complesso operator+(complesso x, double d)
    
    userebbe quest'ultimo.
  • Re: Operatori di conversione

    .
  • Re: Operatori di conversione

    int main() {
       complesso x, y(2, 5);
       x = y + 2.5; // equivale a  x=y + complesso(2.5);
       ...
    }
    Se non ricordo male (possibilissimo), il procedimento applicato è che prima l'oggetto y di classe complesso viene sommato al double 2.5 (somma per la quale deve esistere un operatore sovraccaricato), poi l'oggetto temporaneo restituito dall'operatore sovraccaricato viene assegnato all'oggetto x di classe complesso.
    #include <stdio.h>
    
    class complesso {
       double re, im;
    
    public:
       complesso(double re=0, double im=0);
    
       complesso operator+(const complesso &addendo_di_destra) const;
       complesso operator+(double addendo_di_destra) const;
    
       const char *Stringa();
    };
    
    complesso::complesso(double r, double i) {
        re=r; im=i;
        printf( "complesso: Funzione creatrice\n" ); // solo per un po' di info
    }
    
    complesso complesso::operator+(const complesso &addendo_di_destra) const {
       printf( "complesso: operatore + con complesso\n" ); // solo per un po' di info
       return complesso(re+addendo_di_destra.re,im+addendo_di_destra.im);
    }
    
    complesso complesso::operator+(double addendo_di_destra) const {
       printf( "complesso: operatore + con double\n" ); // solo per un po' di info
       return complesso(re+addendo_di_destra,im+addendo_di_destra);
    }
    
    const char *complesso::Stringa() { // giusto per poter avere un output visibile
        static char s[64];
        sprintf( s, "re: %lg\nim: %lg", re, im );
        return s;
    }
    
    int main() {
        complesso x, y(2, 5);
        x = y + 2.5;
        printf( "%s\n", x.Stringa() );
        return 0;
    }
    Questa roba dà un'uscita così:

    complesso: Funzione creatrice
    complesso: Funzione creatrice
    complesso: operatore + con double
    complesso: Funzione creatrice
    re: 4.5
    im: 7.5

    In effetti, la funzione creatrice viene invocata due volte per generare gli oggetti x e y.
    Poi viene eseguito y+2.5 nell'apposita funzione sovraccaricata.
    La funzione sovraccaricata crea un oggetto di classe complesso per usarlo come valore in uscita per il suo return (il che spiega la terza invocazione della funzione creatrice).
    A quel punto l'oggetto temporaneo creato e restituito viene assegnato all'oggetto x. Credo che non venga segnalata alcuna operazione perché l'oggetto x esiste già e non è stato definito un operatore di assegnamento sovraccaricato, per cui viene usato quello di default (quello che fa una copia bit-per-bit dell'oggetto da copiare in quello che riceve).

    Se ho scritto inesattezze, chi è più esperto mi corregga, così imparo anch'io.
Devi accedere o registrarti per scrivere nel forum
5 risposte