2014-10-15 9 views
7

Sowohl Klirren 3.5.0 und g ++ 4.9.0compile the following code fine (mit -std=c++11 -Wall -Wextra -pedantic-errors) und das Programm Ausgänge true:Kann man von A * nach B * über dynamic_cast umwandeln, wenn A und B keinen gemeinsamen Vorfahren haben?

#include <iostream> 

struct A 
{ 
    virtual ~A() = default; 
}; 

struct B 
{ 
    virtual ~B() = default; 
}; 

struct C : A, B 
{ 
    virtual ~C() = default; 
}; 

int main() 
{ 
    C c; 
    A* ap = &c; 
    B* bp = dynamic_cast<B*>(ap); 

    std::cout << std::boolalpha << (bp != nullptr) << std::endl; 
} 
+1

Gibt es einen bestimmten Grund, warum Sie vermuten, dass das angezeigte Verhalten falsch ist? (Es ist eine gültige Frage, aber es würde einen Unterschied machen, worauf sich eine gute Antwort konzentrieren sollte.) – hvd

+0

@hvd Ich war mir fast sicher, dass es nicht möglich war. Ich weiß nicht warum. :) – Constructor

+0

@hvd Ich meine, ich nahm an, dass die Ausgabe des Programms "falsch" sein sollte, nicht, dass die Verwendung von 'dynamic_cast' in einigen Fällen natürlich ungültig sein kann. – Constructor

Antwort

7

, gemäß §5.2.7 [expr.dynamic.cast], für dynamic_cast<T>(v) (Hervorhebung von mir):

Wenn C der Klassentyp, auf die T Punkte oder bezieht, ist die Laufzeit check logisch wie folgt ausgeführt:

- Wenn in dem abgeleiteten Objekt, auf das von v verwiesen wird, verweist V auf eine öffentliche Basisklasse Unterobjekt eines C-Objekts, und wenn nur ein Objekt vom Typ C wird aus dem Unterobjekt abgeleitet, auf das die Ergebnispunkte (referenziert) auf dieses C-Objekt zeigen.

- Andernfalls, wenn v Punkte (bezieht) auf eine öffentliche Basisklasse Subobjekt des meisten abgeleitetes Objekt und dem Typ des meisten abgeleitetes Objekt eine Basisklasse hat, vom Typ C, das eindeutig und öffentlich ist, Das Ergebnis verweist auf das Unterobjekt C des am weitesten abgeleiteten Objekts.

- Andernfalls schlägt die Laufzeitprüfung fehl.

In Ihrem Fall bezieht sich auf ein v meist abgeleitete Objekt, das eine Instanz der C ist, aber die statische Art der v ist ein Zeiger auf die öffentliche Basisklasse A. Die im Angebot genannte C Basisklasse ist Ihre B.

+0

Auch relevant für jemanden, der sich vielleicht gerade darüber Gedanken macht: 11.2.2 - 'In Abwesenheit eines Zugriffsspezifizierers für eine Basisklasse wird public angenommen, wenn die abgeleitete Klasse mit der Klassenschlüssel-Struktur definiert ist und private wann angenommen wird Die Klasse ist mit der Klasse-Schlüssel-Klasse definiert. –

+0

@MarcoA., Ich denke, das wäre gut zu beachten, ja. Vielen Dank. – chris

+0

@MarcoA. Wie bezieht sich Ihr Angebot auf die Frage oder Antwort? – Constructor

8

Ja. Das wird manchmal als Crosscasting bezeichnet und wird erfolgreich sein, wenn sie beide Basisunterobjekte desselben abgeleiteten Objekts sind, wie sie hier sind.

dynamic_cast ist erforderlich, da die Konvertierung die Laufzeitinformationen benötigt, die beide Teil eines C Objekts sind. Um statisch zu wirken, müssten Sie zuerst explizit zu C* konvertieren. Ja

+1

Danke. * Crosscasting * ist ein neuer Begriff für mich. – Constructor