Erhalten abgeleiteten Typ über Basisklasse virtuelle Funktion
Ich versuche dem abgeleiteten Typ eines Objekts über eine Basisklasse virtuelle Funktion. Ich habe dies geschrieben, die nicht kompilieren:
struct base {
virtual base& get_this() {
return *this;
}
};
struct derived : base {
virtual derived& get_this() override {
return *this;
}
void fn();
};
int main () {
base* pd = new derived();
derived& x = pd->get_this(); /*ERROR*/
x.fn();
return 0;
}
... geben mir eine Fehlermeldung: ich kann nicht initialisiert werden ein derived&
aus einer base
. Da get_this
ist virtuell, warum pd->get_this()
Gegenzug eine base&
statt einer derived&
? Vielen Dank im Voraus!
EDIT:
Danke an alle für Ihre hilfreichen Antworten und Entschuldigung für meine späte Antwort. Sollte ich angegeben habe in dem ursprünglichen Beitrag, ich bin auch daran interessiert, eine Lösung für mein problem eher, als nur herauszufinden, warum die oben genannten nicht kompilieren. Mein Hauptproblem ist, dass fn
ist einzigartig in der derived
Klasse und kann nicht aufgerufen werden, über die Basis-Klasse. Mithilfe wirft sicher löst das problem, aber ich hasse das schreiben von code mit if -, else-Konstrukte, nur um die richtige Art (auch Scott Meyers abraten wirft :)) . Die Antworten scheinen darauf hinzudeuten, dass die casts sind der Weg zu gehen, die in einer Art und Weise ist zumindest beruhigend, dass ich nicht vernachlässigen, eine "elegante" Lösung zu meinem problem. Nochmals vielen Dank!
- Gelöscht meine Antwort, aber ich glaube immer noch, die OP wird es besser mit einem einfachen
dynamic_cast
wird eine gute Lösung für den Anwendungsfall beschrieben. Niemand erwähnte dies in die Antworten, und die Art und Weise Kovarianz unterstützt in C++ löst nicht die OP das primäre problem. - Gut, ja, man könnte (sollte) gerade entfernt oder verändert der umstrittene Satz, der rest ist spot-on und eine gute Antwort. Jetzt haben Sie weggeworfen, das Kind mit dem Bade aus.
- Gab noch eins (ohne die wählerisch Worte). Zumindest hast du Recht: downvote-rate war weniger als Ruf gewinnen an diesem Punkt. Aber ich bin immer nervös auf downvotes, und die Erfahrung zeigt, dass Sie nie zurückgenommen werden, auf entsprechend bearbeitet Antworten.
Du musst angemeldet sein, um einen Kommentar abzugeben.
C++ kovariante Rückgabetypen Unterstützung funktioniert nur, so lange Sie wissen bereits, den abgeleiteten Typ. Zu niedergeschlagen einer Basisklasse auf eine mögliche abgeleitete Klasse, verwenden Sie einfach
dynamic_cast<derived>(base_ref)
um festzustellen, ob base_ref entspricht der tatsächlichen abgeleiteten Typ:Alternativ:
c++ unterstützt die kovariante Rückgabetypen für abgeleitete Klassen, aber wie die anderen Antworten beschreiben, Sie können es nicht über den Aufruf der Basisklasse (
pd->get_this()
) hier.Könnte Sie auch interessieren statische Polymorphie überprüfen der Konformität zur compile-Zeit, wenn Sie nicht verwenden können,RTTI, exception-handling oder wollen, fest Typ-Bindung (ohne vtable-overhead).
Der statische Typ von
pd
istbase *
. Also, wenn der compiler sucht die member-Funktionget_this()
findet es nurbase::get_this()
. Der Rückgabetypbase::get_this()
istbase&
, die nicht konvertierbar ist zuderived&
. Daher der Fehler.Ich hinzufügen möchte, Novelocrat Antwort verweisen Sie auf Abschnitt 10.3, Absatz 8 des working draft C++ - standard (klicken Sie hier) die erklärt, in welchem Fall die zurückgegebene Zeiger der statische Typ Abgeleitet ist* im Gegensatz zu Base*. Grundsätzlich, wenn Sie genannt haben würde
get_this()
durch einen Zeiger auf die Klasse abgeleitet ist, dann würden Sie bekommen haben und der richtige Typ mit keine compiler-Fehler.Hier ist ein Zitat aus der standard, zusammen mit einem Beispiel (auch aus dem standard):
dynamic_cast
. Das ist, warum ich erwähnt habe statische Polymorphie, die das bessere design Wahl in den meisten Fällen IMHO. Aber es braucht mehr Anstrengungen, um es richtig zu machen.C++ unterstützt covariant return-Typ.
Was es bedeutet ist, dass, wenn Sie nennen
get_this()
auf einederived
Objekt durch einebase
pointer es ist die Umsetzung abgeleitet, genannt wird.Allerdings bedeutet dies nicht, dass der Aufruf
base::get_this
wird Ihnen einederived&
. Der Rückgabetypbase::get_this
istbase&
. wenn Sie wollen, um einenderived
Objekt, das Sie haben, zu nennenget_this
durch einederived
Zeiger (oder niedergeschlagen Ihrbase&
zu einemderived&
). Beachten Sie, dass dies ist, wie return-type-Kovarianz-arbeiten in Java, C++, D...base
Hinweis, es könnte jede Art hinter sich, wie konnte Sie wissen, was sollte der Typ derx
... ?Fand ich eine einfache Lösung, aber wenn möglich, würde ich den Meister zu bewerten:
Diese Weise können Sie rufen Sie die Methode "int getType ()" von einer der abgeleiteten Klassen. Als der Typ auf der Konstruktor, gibt es kein Risiko des Fehlverhaltens.
Zur Verbesserung der usability, ich habe eine vordefinierte 'Typen'.
Ich bin mit, aber ich weiß nicht, ob MacGyvery!
type
fehlt, ist ein Typ-Bezeichner. Sie konnte nicht einmal instanziieren eine Instanz derderived1
in deinem Beispiel.