2012-03-31 4 views
1

Ich weiß über das Grundkonzept der virtuellen Funktion und Laufzeitanruf. Aber ich versuchte einig Stück Code ausgeführt wird, die mirKann jemand dieses Verhalten für die virtuelle Funktion erklären?

verwirrte
class A { 
    public: 
    A& operator=(char) { 
     cout << "A& A::operator=(char)" << endl; 
     return *this; 
    } 
    virtual A& operator=(const A&) { 
     cout << "A& A::operator=(const A&)" << endl; 
     return *this; 
    } 
    }; 

    class B : public A { 
    public: 
     B& operator=(char) { 
     cout << "B& B::operator=(char)" << endl; 
     return *this; 
     } 

     virtual B& operator=(const B&) { 
     cout << "B& B::operator=(const B&)" << endl; 
     return *this; 
     } 
    }; 

    int main() { 
    B b1; 
    B b2; 
    A* ap1 = &b1; 
    A* ap2 = &b1; 
    *ap1 = 'z'; 
    *ap2 = b2; 
    } 

Das Ausführen dieses Programms geben Sie mir die folgende Ausgabe: -

A& A::operator=(char) //expected output 
    A& A::operator=(const A&) //Why this Output? in case of *ap2 = b2; 

b2 ein Objekt von B Typ, aber noch geht es in virtuellen A& operator=(const A&) und nicht virtuell B& operator=(const B&). Warum ist das so ?

Antwort

3

Weil virtual B& operator=(const B&) nicht übersteuert virtual A& operator=(const A&); Die Argumente sind anders.

+0

Chalesworth ist es so, dass ein Zeigertyp Angelegenheiten während des Funktionsaufrufs und nicht die Art von Objekt ist dieser Zeiger, auf den zeigt, was bei virtueller Funktion tatsächlich passiert? Weil hier ap2 ein Zeigertyp von A ist, aber auf ein Objekt vom Typ B zeigt? Ich irre mich irgendwo? – Invictus

+1

@Ritesh: In der Zeile '* ap2 = b2' ist der Kompilierzeittyp von' * ap2' 'A'. Der Compiler kann also nur (virtuelle) Elementfunktionen berücksichtigen, die in der Schnittstelle vorhanden sind, die "A" darstellt. –

2

Damit eine abgeleitete Klassenfunktion die Base-Klassenfunktion überschreiben kann, muss die abgeleitete Klassenfunktion genau denselben Funktionsprototyp haben (Ausnahme: kovariante Rückgabetypen sind zulässig).

Der = Operator in abgeleiteten Klasse B hier nicht über gleiche Funktion Prototyp wie = in Basisklasse A, und daher ist es nicht die Basisklasse = außer Kraft setzen.

Der einzige verfügbare Operator = ist derjenige, der aufgerufen wird.

2

Damit eine Funktion als Überschreibung betrachtet werden kann, muss die Signatur exakt mit der Version in der Basisklasse übereinstimmen (der Rückgabetyp kann kovariant sein, wenn ein Zeiger oder eine Referenz zurückgegeben wird). Das heißt, Sie müssten

B& B::operator= (A const&) 

definieren, um die Version von der Basisklasse zu überschreiben. Beachten Sie, dass es für Eingabeparameter in überschreibenden Funktionen nicht sinnvoll ist, kovariant zu sein, da Sie nicht garantieren können, dass die Basisklassenversion mit einem abgeleiteten Objekt in einem Kontext aufgerufen wird, der nur die Basisklasse verwendet. Wenn Parameter zu einer überschreibenden Funktion kontravariant sein könnten, unterstützt C++ dies nicht.

2

Hier in der abgeleiteten Klasse nimmt die Funktion B, während in der Basisklasse die Annahme von A. So, im Grunde ist es nicht überschrieben, da die Funktion Argumente sind unterschiedlich.

Beachten Sie auch, dass der Rückgabetyp im Falle einer Außerkraftsetzung anders sein kann, da in Ihrem Fall die Referenz von A in der Basis und die Referenz von B in abgeleitet sind. virtuelle Basis & func (konst Basis &) virtuellen Abgeleitet & func (konst Basis &) Dies gilt Form des überwiegenden