Kovarianter Rückgabetyp und Typkonvertierung

Lesezeit: 3 Minuten

Kovarianter Ruckgabetyp und Typkonvertierung
Vorlage Junge

s->duplicate() gibt ein Objekt vom Typ . zurück Box*, aber ich erhalte einen Fehler beim Initialisieren mit Box*. Es sieht so aus, als ob es zurück in umgewandelt wird Shape*. Welchen Sinn haben kovariante Rückgabetypen, wenn sie zurück in den Basisklassenzeiger konvertiert werden?:

struct Shape
{
    virtual Shape* duplicate()
    {
        return new Shape;
    }
};

struct Box : Shape
{
    virtual Box* duplicate()
    {
        return new Box;
    }
};

int main()
{
    Shape* s = new Box;
    Box*   b = s->duplicate();
}

Fehler:

main.cpp:22:12: error: cannot initialize a variable of type 'Box *' with an rvalue of type 'Shape *'
    Box*   b = s->duplicate();
           ^   ~~~~~~~~~~~~~~
1 error generated.

Kovarianter Ruckgabetyp und Typkonvertierung
Leichtigkeitsrennen im Orbit

Obwohl Box::duplicate ist zur Laufzeit aufgerufen werden (über virtuellen Dispatch), und obwohl Box::duplicate tut überschreiben Shape::duplicate (kovariant) und obwohl Box::duplicate tut zurück a Box*, du bekommst immer noch ein Shape* Zeiger, weil du anrufst duplicate() durch ein Shape* Zeiger, und Shape* ist der Rückgabetyp von Shape::duplicate(), und der Compiler sieht nur Sie aufrufen Shape::duplicate, nicht Box::duplicate.

C++ ist nicht in der Lage, Typen dynamisch auszuwählen, daher ist dies das Beste, was es tun kann. Deine Box* wird automatisch in a . umgewandelt Shape* auf dem weg aus Box::duplicate. Wie Barry sagte, “muss es immer noch zur Kompilierzeit kompiliert werden, und zur Kompilierzeit wissen wir nur, dass es a . zurückgibt Shape*“.

Dann, um es zu einem zu machen Box* Auch hier müssen Sie es explizit umwandeln (mit static_cast oder dynamic_cast), da keine implizite Abwärtskonvertierung existiert.

[C++11: 10.3/7]: Der Rückgabetyp einer überschreibenden Funktion ist entweder identisch mit dem Rückgabetyp der überschriebenen Funktion oder kovariant mit den Klassen der Funktionen. [..]

[C++11: 10.3/8]: Wenn der Rückgabetyp von D::f unterscheidet sich von der Rückgabeart von B::f, der Klassentyp im Rückgabetyp von D::f muss zum Zeitpunkt der Erklärung vollständig sein D::f oder soll der Klassentyp sein D. Wenn die überschreibende Funktion als letzte Überschreibung der überschriebenen Funktion aufgerufen wird, wird ihr Ergebnis in den von der (statisch ausgewählten) überschriebenen Funktion zurückgegebenen Typ konvertiert (5.2.2). [..]

Im Standardtext folgt ein entsprechendes Beispiel.

  • Sie hätten wirklich kein kürzeres Beispiel finden können, um diesen Abschnitt zu veranschaulichen?

    – Barry

    12. Mai ’15 um 18:01

  • @Barry: Überrascht? 😛

    – Leichtigkeitsrennen im Orbit

    12. Mai ’15 um 21:33

  • @Kad: Nicht sicher, was Sie sagen wollen. Wollten Sie eine Frage zu dieser Codezeile stellen? Das ist ungültig, da es sich um eine versuchte implizite Basis-zu-derived-Konvertierung handelt, die nicht zulässig ist (und dies habe ich tatsächlich in der Antwort gesagt). Versuchen Shape* s = new Box(); stattdessen.

    – Leichtigkeitsrennen im Orbit

    19. April ’18 um 13:58


Der Punkt ist nicht, dies zu tun:

Box*   b = s->duplicate();

Das kann offensichtlich nicht funktionieren, da Shape::duplicate() gibt a . zurück Shape*. Der Punkt ist vielmehr, a . zu akzeptieren Box* wenn du anrufst duplicate() auf einen Box direkt:

Box* old = new Box;
Box* b = old->duplicate(); // OK! We know it's a Box

  • Da der Versand zur Laufzeit erfolgt, warum wird der Rückgabetyp nicht von Box::duplicate()?

    – Vorlagenjunge

    25. Januar ’15 um 3:30


  • @templateboy Weil es zur Kompilierzeit immer noch kompiliert werden muss, und zur Kompilierzeit wissen wir nur, dass es a zurückgibt Shape*.

    – Barry

    25. Januar ’15 um 3:30

  • Die Lösung ist nicht sehr allgemein. Was ist, wenn ich nicht weiß was? duplicate() kehrt zurück?

    – Vorlagenjunge

    25. Januar ’15 bei 3:39

  • @templateboy Sie wissen, dass es zurückkehrt Shape*. Und wenn du das weißt Box::duplicate() gibt a . zurück Box*, dann können Sie diese Informationen verwenden? Ich verstehe nicht, worauf du hinaus willst.

    – Barry

    25. Januar ’15 bei 3:44

  • Ich verstehe jetzt. Danke.

    – Vorlagenjunge

    25. Januar ’15 um 3:45

.

460790cookie-checkKovarianter Rückgabetyp und Typkonvertierung

This website is using cookies to improve the user-friendliness. You agree by using the website further.

Privacy policy