Visualizzazione dei risultati da 1 a 4 su 4
  1. #1
    Utente di HTML.it L'avatar di felpone
    Registrato dal
    Jun 2010
    Messaggi
    182

    [c++]spiegazione scelta metodo

    Salve, ho questo codice che produce il seguente output:set1,set2,set2,set2.
    Forse non ho ben capito il this ma non mi spiego perchè il terzo output sia set2 invece che set1.


    codice:
    #include <iostream>
    class B;
    class A
    {
    public:
        virtual A* set(A* a) = 0;
    };
    
    class B : public A
    {
    public:
        virtual A* set(B* b)
        {
            std::cout << "set1 has been called" << std::endl;
            b = this;
            return b;
        }
    
        virtual B* set(A* a)
        {
            std::cout << "set2 has been called" << std::endl;
            a = this;
            return this;
        }
    };
    
    int main(int argc, char *argv[])
    {
        B *b = new B();
        A *a = b->set(b);
        a = b->set(a);
        a = a->set(b);
        a = a->set(a);
        return 0;
    }

  2. #2
    Set restituisce l'argomento che gli è stato passato, per cui dopo la seconda set a è impostato a b, per cui a effettivamente punta ad un oggetto di tipo B; dato quindi che set è virtual, ne viene chiamata la versione di B.
    Amaro C++, il gusto pieno dell'undefined behavior.

  3. #3
    Utente di HTML.it L'avatar di felpone
    Registrato dal
    Jun 2010
    Messaggi
    182
    Scusa ma i this a cosa si riferiscono?poi mi viene detto che dopo la prima set si ritorna tipo a,come è possibile?

  4. #4
    Ah no aspetta, ho letto male (complice il fatto che il codice non era indentato ); la questione è ben più ingarbugliata.

    Vediamo passo per passo:
    B *b = new B();
    crea un nuovo oggetto di tipo B e ne assegna un puntatore a b

    A *a = b->set(b);
    chiama il primo overload di set (quello che riceve un B*); questo stampa a video "set1 has been called" e restituisce this (b = this; return b; di fatto è come scrivere return this); ricorda che this è un puntatore all'oggetto su cui è stato richiamato il metodo corrente, in questo caso quindi b.
    Ora, b è un B*, che però può essere convertito implicitamente in un A* dato che B eredita da A. Quindi, dopo la prima set a è uguale a b (ma con "tipo statico" diverso).

    a = b->set(a);
    Chiama il secondo overload di set (dato che il "tipo statico" di a è A*, ed è il "tipo statico" ad essere usato per risolvere gli overload); questo stampa a video "set2 has been called" e restituisce this; stesso discorso di prima per la conversione. a è ancora uguale a b.

    a = a->set(b);
    a = a->set(a);
    Qui la questione è più sottile; in entrambi i casi viene richiamata la set su a, ma, poiché il tipo statico di a è A*, viene visto solo l'overload dichiarato in A, ovvero quello che riceve un A*. Dato che il tipo dinamico di a è B*, viene quindi richiamato il secondo overload (set2).

    Mi spiego meglio; come detto sopra, al momento della risoluzione degli overload viene considerato solo il "tipo statico" (dato che gli overload vengono risolti al momento della compilazione non c'è alternativa). A* ha un solo overload per set, ovvero quello che riceve un A*, per cui è questo che viene chiamato.
    Ora, a in realtà punta ad un B e set è virtual, per cui verrà richiamata la "versione" di B della funzione virtuale in questione. Questa è set2, dato che, delle due, è quella che riceve A*, ed è lei che ridefinisce il metodo dichiarato in A.

    Fatto curioso: la set2 ridefinisce la set della classe base, ma ha un tipo restituito differente: questo è consentito dalla cosiddetta "covarianza" dei metodi virtuali: se il metodo virtuale nella classe base restituisce un T* (o un T&) (dove T è un tipo), i metodi che lo ridefiniscono nelle classi derivate possono sempre avere tipo U* (o un U&) se U è una classe derivata da T.
    Amaro C++, il gusto pieno dell'undefined behavior.

Permessi di invio

  • Non puoi inserire discussioni
  • Non puoi inserire repliche
  • Non puoi inserire allegati
  • Non puoi modificare i tuoi messaggi
  •  
Powered by vBulletin® Version 4.2.1
Copyright © 2024 vBulletin Solutions, Inc. All rights reserved.