Ich versuche, den abgeleiteten Typ eines Objekts über eine virtuelle Funktion der Basisklasse zu erhalten. Ich habe das geschrieben, was nicht kompiliert:
%Vor% ... gibt mir eine Fehlermeldung, dass: Ich kann derived&
nicht von base
initialisieren. Da get_this
virtuell ist, warum gibt pd->get_this()
eine base&
anstelle von derived&
zurück? Vielen Dank im Voraus!
BEARBEITEN:
Danke an alle für ihre nützlichen Antworten und Entschuldigungen für meine verspätete Antwort. Ich hätte im ursprünglichen Beitrag angeben sollen, dass ich auch an einer Lösung für mein Problem interessiert bin, anstatt nur herauszufinden, warum das obige nicht kompiliert. Mein Hauptproblem ist, dass fn
für die Klasse derived
eindeutig ist und nicht über die Basisklasse aufgerufen werden kann. Die Verwendung von Casts löst zwar das Problem, aber ich hasse es, Code mit anderen Konstrukten zu schreiben, nur um den richtigen Typ zu erhalten (auch Scott Meyers rät von Umsetzungen :)). Die Antworten scheinen darauf hinzudeuten, dass Gussstücke der richtige Weg sind, was in gewisser Weise zumindest beruhigend ist, dass ich keine "elegantere" Lösung für mein Problem vernachlässige. Nochmals vielen Dank!
C ++ kovariante Rückgabetypen werden nur funktionieren, solange Sie den abgeleiteten Typ bereits kennen. Um eine Basisklasse auf eine möglicherweise abgeleitete Klasse zu reduzieren, verwenden Sie einfach dynamic_cast<derived>(base_ref)
, um festzustellen, ob base_ref mit dem tatsächlich abgeleiteten Typ übereinstimmt:
Oder alternativ:
%Vor% gekennzeichnete Fragen c ++ unterstützt kovariante Rückgabetypen für abgeleitete Klassen, Aber wie die anderen Antworten beschreiben, können Sie es nicht durch Aufruf der Basisklasse ( pd->get_this()
) hier erreichen.
Sie könnten auch statischen Polymorphismus in Betracht ziehen, um die Typkompatibilität zum Zeitpunkt der Kompilierung zu überprüfen, wenn Sie
Der statische Typ von pd
ist base *
. Wenn der Compiler nach der Memberfunktion get_this()
sucht, findet er nur base::get_this()
. Der Rückgabetyp von base::get_this()
ist base&
, der nicht in derived&
konvertiert werden kann. Daher der Fehler.
Ich möchte die Antwort von Novelocrat mit Verweis auf Abschnitt 10.3, Absatz 8 der Arbeitsentwurf C ++ - Standard (klicken Sie hier) , der erklärt, in welchem Fall der statische Typ des zurückgegebenen Zeigers Abgeleitete * im Gegensatz zu Basis * ist. Wenn Sie get_this()
über einen Zeiger auf die dervied-Klasse aufgerufen hätten, hätten Sie den richtigen Typ ohne Compilerfehler erhalten.
Hier ist ein Zitat aus dem Standard mit einem Beispiel (auch aus dem Standard):
%Vor%Wenn sich der Rückgabetyp von D :: f vom Rückgabetyp von B :: f unterscheidet, wird der Klassenart im Rückgabetyp von D :: f soll an dieser Stelle vollständig sein der Deklaration von D :: f oder soll der Klassentyp D sein Übersteuerungsfunktion wird als der endgültige Überrißer des Übersteuerten bezeichnet Funktion wird das Ergebnis in den Typ konvertiert, der von (statisch gewählte) überschriebene Funktion (5.2.2). [Beispiel:
C ++ unterstützt den kovarianten Rückgabetyp.
Was es bedeutet, dass, wenn Sie get_this()
auf einem derived
Objekt durch einen base
Zeiger aufrufen, es die Implementierung von abgeleitet wird, die aufgerufen wird.
Das bedeutet jedoch nicht, dass Sie base::get_this
aufrufen, wenn Sie derived&
angeben. Der Rückgabetyp von base::get_this
ist base&
. Wenn Sie ein Objekt derived
erhalten möchten, müssen Sie get_this
über einen derived
-Zeiger aufrufen (oder Ihr base&
auf ein derived&
reduzieren). Beachten Sie, dass die Rückgabetyp-Kovarianz in Java, C ++, D ... funktioniert.
Ich habe eine einfache Lösung gefunden, aber wenn es möglich ist, würde ich die Herren bewerten:
%Vor%Auf diese Weise können Sie die Methode 'int getType ()' einer abgeleiteten Klasse aufrufen. Da der Typ im Konstruktor festgelegt ist, besteht kein Risiko von Fehlverhalten. Um die Benutzerfreundlichkeit zu verbessern, habe ich vordefinierte "Typen" erstellt.
Ich benutze, aber ich weiß nicht, ob MacGyvery ist!