2015-02-11 18 views
25

Date un'occhiata al seguente codice:dichiarazione using in classe derivata non nasconde stessa funzione derivata dalla classe base

struct A { 
public: 
    virtual void f(){std::cout << "in A";}; 
}; 

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

struct C : B{ 
    using A::f; 
    void test(){f();} 
}; 


int main() 
{ 
    C c; 
    c.f(); // calls B::f, the final overrider 
    c.C::f(); // calls A::f because of the using-declaration 
    c.test(); //calls B::f 
    return 0; 
} 

Per la mia comprensione, il B::f() in C dovrebbe nascondere il A::f() che viene portato a C usando-declaration; se sì, allora perché c.C::f() chiama ancora A::f()?

If c.C::f() chiamate A::f(), che dovrebbe significare che nell'ambito di C, f() occorre riferiscono sempre A::f(), questa è la funzione della dichiarazione using. Quindi, perché nel C::test(), la chiamata a f() viene ancora valutata su B::f()?

risposta

29

Bella domanda, un caso complicato di ricerca del nome.

In sostanza, quando il nome f viene cercato nel campo di applicazione del C, è sempre trova A::f a causa della dichiarazione using. Quindi tutte le chiamate c.f(), c.C::f() e f() in C::test() risolvono il nome f in A::f.

Avanti arriva la spedizione virtuale. Se una funzione virtuale viene chiamata da un nome non qualificato, si verifica una spedizione dinamica e viene chiamato lo overrider finale. Questo copre c.f() e la chiamata f() in C::test(), poiché questi non sono qualificati.

La chiamata c.C::f() utilizza un nome qualificato per f, che sopprime l'invio dinamico e la funzione a cui il nome risolto viene chiamato direttamente. Poiché tale funzione è A::f (grazie alla dichiarazione di utilizzo), A::f viene chiamato non virtualmente. Le norme pertinenti seguono (C citando ++ 14 def progetto N4140, sottolineatura mia):

§10.3/15

qualificazione esplicita con l'operatore di portata (5.1) sopprime il meccanismo di chiamata virtuale.

§5.2.2/1

... Se la funzione selezionata non è virtuale, o se il id-espressione nell'espressione accesso membro della classe è un id qualificato, viene chiamata tale funzione. In caso contrario, viene chiamato il suo overrider finale (10.3) nel tipo dinamico dell'espressione dell'oggetto; tale chiamata è denominata chiamata di funzione virtuale .

+0

@LiuNick Aggiunto. – Angew

+0

solo così professionale! Grazie! –

+0

@LiuNick Il modo Stack Overflow di dire "grazie" è di [accettare la risposta che ha risolto il problema] (http://stackoverflow.com/help/someone-answers) (al massimo una risposta accettata per domanda).Questo contrassegna la domanda come risolta e fornisce sia al rispondente che a te una certa reputazione. – Angew

Problemi correlati