2015-02-11 9 views
25

einen Blick auf den folgenden Code haben:using-Deklaration in abgeleiteten Klasse nicht verstecken gleiche Funktion, die von der Basisklasse

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 mein Verständnis, das B::f() in C sollte die A::f() verstecken, die C gebracht wird durch Verwendung der Deklaration; Wenn ja, warum ruft c.C::f() immer noch A::f()?

Wenn c.C::f() Anrufe A::f(), dass die im Rahmen der C bedeuten sollte, sollte f() immer A::f() beziehen werden, ist dies die Funktion der using-Deklaration. Warum wird dann in der C::test() der Anruf an f() immer noch auf B::f() ausgewertet?

Antwort

29

Sehr nette Frage, ein komplizierter Fall von Namenssuche.

Grundsätzlich, wenn der Name f wird im Rahmen der C nachgeschlagen, es immer findet A::f aufgrund der Verwendung Deklaration. Also alle Anrufe c.f(), c.C::f() und f() in C::test(), lösen Sie den Namen f zu A::f.

Als nächstes kommt virtueller Versand. Wenn eine virtuelle Funktion mit einem unqualifizierten Namen aufgerufen wird, wird der dynamische Dispatch ausgeführt und der letzte Overrider aufgerufen. Dies deckt c.f() und den f() Aufruf in C::test() ab, da diese unqualifiziert sind.

Der Aufruf c.C::f() verwendet einen qualifizierten Namen für f, der dynamischen Versand unterdrückt und die Funktion, auf die der Name aufgelöst wird, direkt aufgerufen wird. Da diese Funktion A::f ist (dank der using-Deklaration), wird A::f als nicht virtuell bezeichnet. Die entsprechenden Regeln (unter Angabe C++ 14 endgültigen Entwurf N4140, Hervorhebung von mir):

§10.3/15

Explicit Qualifikation mit dem Bereichsoperator (5.1) unterdrückt die virtuellen Call-Mechanismus.

§5.2.2/1

... Wenn die ausgewählte Funktion nicht virtuell ist, oder wenn die ID-expression in dem Klassenmitglied Zugang Ausdruck ist ein qualifizierte-ID, Diese Funktion wird aufgerufen. Andernfalls wird sein final overrider (10.3) im dynamischen Typ des Objektausdrucks aufgerufen; Ein solcher Anruf wird als virtueller Funktionsaufruf bezeichnet.

+0

@LiuNick Hinzugefügt. – Angew

+0

nur so professionell! Vielen Dank! –

+0

@LiuNick Der Stack Overflow Weg zu sagen "Danke" ist zu [akzeptieren die Antwort, die das Problem gelöst] (http://stackoverflow.com/help/someone-answers) (höchstens eine akzeptierte Antwort pro Frage).Dies markiert die Frage als gelöst und gibt sowohl dem Antworter als auch Ihnen einen gewissen Ruf. – Angew

Verwandte Themen