Ein Basisklassenzeiger kann auf ein abgeleitetes Klassenobjekt zeigen. Warum gilt das Gegenteil nicht?

Lesezeit: 6 Minuten

Ein Basisklassenzeiger kann auf ein abgeleitetes Klassenobjekt zeigen. Warum gilt das Umgekehrte ohne Casting nicht? Logischerweise hätte eine Basisklasse nicht genügend Informationen der abgeleiteten Klasse, aber eine abgeleitete Klasse sollte auch die Informationen der Basisklasse haben. Hier fehlen mir ein paar Basics.

Ein Basisklassenzeiger kann auf ein abgeleitetes Klassenobjekt zeigen Warum gilt
jk.

Wenn ich Ihnen sage, dass ich einen Hund habe, können Sie davon ausgehen, dass ich ein Haustier habe.

Wenn ich Ihnen sage, dass ich ein Haustier habe, wissen Sie nicht, ob dieses Tier ein Hund ist, es könnte eine Katze oder vielleicht sogar eine Giraffe sein. Ohne einige zusätzliche Informationen zu kennen, können Sie nicht davon ausgehen, dass ich einen Hund habe.

ebenso ist ein abgeleitetes Objekt ein Basisklassenobjekt (da es sich um eine Unterklasse handelt), sodass ein Basisklassenzeiger darauf zeigen kann. Ein Basisklassenobjekt ist jedoch kein abgeleitetes Klassenobjekt, sodass es keinem abgeleiteten Klassenzeiger zugewiesen werden kann.

(Das Knarren, das Sie jetzt hören werden, ist die Analogie, die sich ausdehnt)

Angenommen, Sie wollen mir jetzt ein Geschenk für mein Haustier kaufen.

Im ersten Szenario weißt du, dass es ein Hund ist, du kannst mir eine Leine kaufen, alle sind glücklich.

Im zweiten Szenario habe ich dir nicht gesagt, was mein Haustier ist, also wenn du mir sowieso ein Geschenk kaufen willst, musst du Informationen wissen, die ich dir nicht gesagt habe (oder nur raten), du kaufst mir eine Leine, wenn es so ist Es stellt sich heraus, dass ich wirklich einen Hund hatte, alle sind glücklich.

Wenn ich jedoch tatsächlich eine Katze hatte, wissen wir jetzt, dass Sie eine schlechte Annahme getroffen haben (Cast) und eine unglückliche Katze an der Leine haben (Laufzeitfehler).

ClassCastException Kat

  • +1: Beste Antwort bisher, IMHO. Eine einfache Analogie, die das Problem intuitiv veranschaulicht.

    – Oliver Charlesworth

    8. Februar 11 um 19:43 Uhr

  • “Für jedes Problem gibt es eine Lösung, die einfach, sauber und falsch ist.” — HL Mencken. Intuitive Antworten fallen oft in diese Kategorie, insbesondere OO, das in „realen“ Begriffen beschrieben wird. Manchmal zeigt ein Basisklassenzeiger auf ein Objekt eines abgeleiteten Klassentyps, und deshalb (wie die Frage zeigt) können Sie umwandeln.

    – Fred Nurk

    8. Februar 11 um 20:05 Uhr


  • @Fred: Die Antwort ist nicht falsch; Es ist niemals gültig, auf eine Basisklasse zu zeigen Objekt mit einem Zeiger auf abgeleitet. Wie Sie jedoch sagen, ist es manchmal gültig, eine Basisklasse zu casten Zeiger zu einem Zeiger-auf-abgeleitet.

    – Oliver Charlesworth

    8. Februar 11 um 20:37 Uhr

  • Ein Hund ist ein Tier, aber ein Tier ist nicht unbedingt ein Hund, es könnte eine Giraffe sein. Was sagt diese Analogie aus? Wenn Tier als Basisklasse betrachtet wird und Hund/Giraffe die abgeleiteten Klassen sind. Da Hund/Giraffe tatsächlich Tiere sind, sollte die untergeordnete Klasse in der Lage sein, auf die Basisklasse zu zeigen? Sollte das nicht so sein?

    – Zuzu

    9. Februar 11 um 11:32 Uhr


  • Ja, wenn Sie casten, sagen Sie dem Compiler ausdrücklich, dass er die Klappe halten soll, da Sie zusätzliche Informationen haben, die dies nicht tut. Ich denke, ich kann die Tiermetapher erweitern, um die Zeiger und das Gießen ein wenig hinzuzufügen – ertrage es mit mir

    – jk.

    9. Februar 11 um 13:34 Uhr

Wir haben zwei Objekte.

class A {
   int a;
};

class B : A {
   int b;
};

Ordnen Sie eine Instanz von zu B. Wir können damit entweder eine Schnittstelle herstellen A* oder ein B*.

Ordnen Sie eine Instanz von zu A. Wenn wir es auf a werfen würden B*falls für das Mitglied Platz zugeteilt ist b?

  • Dies! Dies hat mir geholfen, meine Zweifel auszuräumen, WARUM es TECHNISCH nicht erlaubt ist. Danke.

    – Sumaiya A

    10. April 21 um 10:22 Uhr

  • @BillLynch B b1; A *pa; Objekt von B und ptr von Objekt A deklarieren, Jetzt müssen wir Gießen es so pa=(A*)&b1; oder wir können direkt verwenden pa=&b1; ?

    – Abhishek Mähne

    10. Mai 21 um 7:02 Uhr


Äh, weil die Basisklasse keine abgeleitete Klasse ist.

Wenn Sie einen gültigen Zeiger auf einen Typ haben, sagen Sie, dass das Objekt, auf das gezeigt wird, bestimmte Daten an bestimmten Stellen haben wird, damit wir es finden können. Wenn Sie einen Zeiger auf ein abgeleitetes Objekt haben, dann garantieren Sie, dass das Objekt, auf das gezeigt wird, alle Datenelemente von Derived enthält – aber wenn Sie auf eine Basis zeigen, dann hat es das tatsächlich nicht und es passieren schlechte Dinge.

Bei Derived ist jedoch garantiert, dass sich alle Base-Datenelemente an denselben Speicherorten befinden. Aus diesem Grund kann ein Zeiger auf Base tatsächlich auf Derived zeigen.

  • Es wird nicht garantiert, dass alle abgeleiteten Klassen alle Base-Datenelemente an denselben Speicherorten haben.

    – Fred Nurk

    8. Februar 11 um 20:07 Uhr

  • In Bezug auf den fraglichen Zeiger glaube ich, dass sie es sind.

    – Welpe

    8. Februar 11 um 20:18 Uhr

  • @Bo: Das macht Dinge wie Casting und Funktionsaufrufe nur komplexer. Grundsätzlich funktioniert die zeigerbasierte Vererbung nur auf der Grundlage, dass, wenn ich einen Zeiger auf Base habe, die vtable- und Member-Variablen dort existieren, wo sie in einer regulären Instanz von Base existieren würden.

    – Welpe

    9. Februar 11 um 0:58 Uhr

Ein Basisklassenzeiger kann auf ein abgeleitetes Klassenobjekt zeigen Warum gilt
Jonathan Holz

Weil eine abgeleitete Klasse alles enthält, was in der Basisklasse enthalten ist. Aber eine Basisklasse enthält nicht alles, was in der abgeleiteten Klasse enthalten ist.

Die Typumwandlung einer Basisklasse in eine abgeleitete Klasse wird nicht empfohlen: Was passiert, wenn Sie versuchen, auf Elemente zuzugreifen, die nicht Teil der Basisklasse sind?

Dies gilt, weil ein Tiger ein Tier ist:

    Animal * pAnimal = new Tiger();

Das ist nicht gültig, weil es nicht stimmt, dass das Objekt ein Pfeilgiftfrosch ist.

    PoisonDartFrog * pPoisonDartFrog = new GenericFrog();

  • @DeadMG: Du hast mich mitten in der Bearbeitung erwischt. Ich denke, ein Beispiel hilft, das Konzept zu vermitteln.

    – Andi Thomas

    8. Februar 11 um 19:13 Uhr

  • Würden die beiden Abwähler von heute, drei Jahre später, etwas dazu sagen, was sie an dieser Antwort für fehlerhaft halten?

    – Andi Thomas

    11. November 14 um 20:17 Uhr

  • …es ist nicht Notwendig stimmt, dass das Objekt ein Pfeilgiftfrosch ist …

    – Aryaman

    19. Juli 18 um 19:33 Uhr

  • @Aryaman – Es ist sicherlich nicht wahr, mit der vernünftigen Annahme, dass niemand GenericFrog als Unterklasse von PoisonDartFrog definiert hat.

    – Andi Thomas

    19. Juli 18 um 20:09 Uhr

  • @AbhishekMane – Es ist ein generischer Frosch – eine Oberklasse von Fröschen – keine bestimmte Unterklasse von Fröschen wie PoisonDartFrog.

    – Andi Thomas

    10. Mai 21 um 13:29 Uhr

1643961611 413 Ein Basisklassenzeiger kann auf ein abgeleitetes Klassenobjekt zeigen Warum gilt
fredoverflow

Da C++ eine statisch typisierte Sprache ist und das Zulassen impliziter Base-to-Derived-Konvertierungen das Typsystem beschädigen würde. Bjarne Stroustrup wollte keine „Nachricht nicht verstanden“-Laufzeitfehler.

  • @DeadMG: Du hast mich mitten in der Bearbeitung erwischt. Ich denke, ein Beispiel hilft, das Konzept zu vermitteln.

    – Andi Thomas

    8. Februar 11 um 19:13 Uhr

  • Würden die beiden Abwähler von heute, drei Jahre später, etwas dazu sagen, was sie an dieser Antwort für fehlerhaft halten?

    – Andi Thomas

    11. November 14 um 20:17 Uhr

  • …es ist nicht Notwendig stimmt, dass das Objekt ein Pfeilgiftfrosch ist …

    – Aryaman

    19. Juli 18 um 19:33 Uhr

  • @Aryaman – Es ist sicherlich nicht wahr, mit der vernünftigen Annahme, dass niemand GenericFrog als Unterklasse von PoisonDartFrog definiert hat.

    – Andi Thomas

    19. Juli 18 um 20:09 Uhr

  • @AbhishekMane – Es ist ein generischer Frosch – eine Oberklasse von Fröschen – keine bestimmte Unterklasse von Fröschen wie PoisonDartFrog.

    – Andi Thomas

    10. Mai 21 um 13:29 Uhr

1643961611 480 Ein Basisklassenzeiger kann auf ein abgeleitetes Klassenobjekt zeigen Warum gilt
JungJohn

class Base
{
public:
    int a;
}

class Derived : public Base
{
public:
    float b;
}

Base * pBase = new Base();
pBase->a = 7; // setting the value of a in the base

// make a pDerived that points to the SAME DATA as pBase
Derived * pDerived = pBase;
pDerived->a = 5; // this would be okay, base has a public member 'a'
pDerived->b = 0.2f; // error pBase has no data member b and pDerived
                    // points to the SAME DATA as pBase

.

766530cookie-checkEin Basisklassenzeiger kann auf ein abgeleitetes Klassenobjekt zeigen. Warum gilt das Gegenteil nicht?

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

Privacy policy