Domanda

Stavo leggendo le FAQ C ++ 0x di Stroustrup e mi sono bloccato con questo codice. Considera il seguente codice

struct A
{
    void f(double)
    {
        std::cout << "in double" << std::endl;
    }
};

struct B : A
{
    void f(int)
    {
        std::cout << "in int" << std::endl;
    }
};


int main()
{
    A a; a.f(10.10);  // as expected, A.f will get called
    B b; b.f(10.10);  // This calls b.f and we lose the .10 here
    return 0;
}

La mia comprensione era quando un tipo viene ereditato, tutti i membri protetti e pubblici saranno accessibili dalla classe derivata. Ma secondo questo esempio, sembra che mi sbagli. Mi aspettavo che b.f chiamasse le classi di base f . Ho ottenuto il risultato atteso cambiando la classe derivata come

struct B : A
{
    using A::f;
    void f(int)
    {
        std::cout << "in int" << std::endl;
    }
};

Domande

  1. Perché non funzionava nel primo codice?
  2. Quale sezione dello standard C ++ descrive tutte queste regole di ambito?
È stato utile?

Soluzione

Il primo codice funziona come c ++ è progettato per funzionare.

La risoluzione di sovraccarico segue un insieme di regole molto complicate. Dalla bibbia c ++ di Stroustrup 15.2.2 "[A] le ambiguità tra funzioni di classi di base diverse non vengono risolte in base ai tipi di argomento."

Continua spiegando l'uso di " usando " come hai descritto.

Questa è stata una decisione di progettazione nella lingua.

Tendo a seguire il libro di Stroustrup piuttosto che lo standard, ma sono sicuro che sia lì.

[Modifica]

Eccolo (dallo standard):

Capitolo 13

Quando vengono specificate due o più dichiarazioni diverse per un singolo nome nello stesso ambito, si dice che quel nome sia sovraccarico.

E poi:

13.2 Corrispondenza delle dichiarazioni

1 Le dichiarazioni di due funzioni con lo stesso nome si riferiscono alla stessa funzione se si trovano nello stesso ambito e hanno dichiarazioni di parametri equivalenti (13.1). Un membro di funzione di una classe derivata non è nello stesso ambito di un membro di funzione di lo stesso nome in una classe base.

Altri suggerimenti

È perché A :: f è " nascosto " piuttosto che "sovraccarico" o "sovrascritto". Fare riferimento:

http://www.parashift.com /c++-faq-lite/strange-inheritance.html#faq-23.9

Cerca risoluzione sovraccarico . Una domanda simile, ma non identica .

In C ++, non c'è sovraccarico tra gli ambiti, nell'ambito delle classi derivate non fanno eccezione. (Secondo il linguaggio di programmazione C ++)

Per ulteriori informazioni, consulta http: //www.research. att.com/~bs/bs_faq2.html#overloadderived

Nel primo caso, il metodo della classe base 'f' è nascosto dal metodo della classe derivata. In C ++ non c'è sovraccarico tra gli ambiti; ecco perché non viene chiamato. Lo standard C ++ spiega tutte le regole di ricerca dei nomi dei membri nella sezione 10.2 Ricerca dei nomi dei membri [class.member.lookup] . HTH

La prima versione del codice dovrebbe davvero chiamare B :: f. Si ridefinisce il simbolo "f" in struct "B", in modo da nascondere il simbolo originale "f" da struct "A". Non è un sovraccarico, come potrebbe sembrare.

Ogni volta che il compilatore incontra b.f (), cerca in " B " struct per un simbolo "f". È presente lì, quindi il compilatore decide di chiamare B :: f (int), convertendo double in int. Non vede la necessità di scansionare la classe genitore per una funzione più adatta ...

Tuttavia, quando aggiungi " usando A :: f " è una direttiva explict per il compilatore di scansionare una classe genitrice per il simbolo " f " ;. Ora, la classe B ha due funzioni sovraccaricate: per int e per double.

Credo anche che tu possa scrivere b.A :: f () senza usare " usando " direttiva nell'esempio originale ...

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top