2014-10-15 5 views
7

Zarówno dzyń 3.5.0 i g ++ 4.9.0compile the following code fine (z -std=c++11 -Wall -Wextra -pedantic-errors) i wyjścia programu true:Czy można rzutować z A * na B * przez dynamic_cast, gdy A i B nie mają wspólnego przodka?

#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

Czy istnieje szczególny powód, dla którego podejrzewasz, że obserwowane zachowanie może być nie tak? (Jest to uzasadnione pytanie w każdym przypadku, ale to by miało znaczenie, na czym powinna się skupić dobra odpowiedź.) – hvd

+0

@Hvd Byłem prawie pewien, że nie było to możliwe. Nie wiem dlaczego. :) – Constructor

+0

@hvd Mam na myśli założenie, że wynik programu powinien być "fałszywy", nie oznacza to oczywiście, że użycie 'dynamic_cast' może być nieważne w niektórych przypadkach. – Constructor

Odpowiedz

7

Tak, jak w §5.2.7 [expr.dynamic.cast] dla dynamic_cast<T>(v) (kopalni nacisk):

Jeśli C jest typ klasy, do której punkty T lub odnosi się wirowanie w czasie check logicznie wykonuje się w następujący sposób:

- Jeśli w najbardziej wyprowadzonym obiekcie wskazano (odniesione) do v, v punktów (odwołuje się) do publicznej klasy bazowej podobiekt obiektu C, a jeśli tylko jeden obiekt typu C pochodzi z podobiektu wskazywanego (nazywane) przez v punktów wynikowych (odniesienie) do tego obiektu C.

- przeciwnym razie, jeśli punkty v (obliczono) do klasy bazowej publicznej podobiektu przedmiotu najbardziej pochodnej, od typu obiektu najczęściej pochodzących posiada klasę zasady, typu C, który jest jednoznaczną i publicznych punkty wynikowe (odwołanie) do podobiektu C najbardziej wyprowadzonego obiektu.

- W przeciwnym razie sprawdzanie w czasie działania nie powiedzie się.

W twoim przypadku, v odnosi się do obiektu, który jest najbardziej pochodzącego instancją swoimi C, ale statyczny typ v jest wskaźnik do klasy bazowej publicznej A. Podstawową klasą C wspomnianą w ofercie jest Twoja B.

+0

Dotyczy również osoby, która może się po prostu zastanawiać: 11.2.2 - 'W przypadku braku specyfikatora dostępu dla klasy bazowej, zakłada się, że klasa publiczna jest zdefiniowana za pomocą struktury klasy klucza, a prywatna jest przyjmowana, gdy klasa jest zdefiniowana klasą klucza klasy. " –

+0

@MarcoA., myślę, że dobrze byłoby zauważyć, tak. Dziękuję Ci. – chris

+0

@MarcoA. Jak twój cytat odnosi się do pytania lub odpowiedzi? – Constructor

8

Tak. To jest czasami określane jako rzutowanie poprzeczne, i powiedzie się, jeśli oba są podstawowymi pod-obiektami tego samego obiektu pochodnego, tak jak są tutaj. Wymagane jest, aby konwersja wymagała informacji o czasie wykonywania, które są częścią obiektu . Aby statycznie rzutować, musisz najpierw jawnie przekonwertować na C*.

+1

Dziękuję. * Cross-casting * to dla mnie nowy termin. – Constructor

Powiązane problemy