2014-10-15 17 views
7

Entrambi clang 3.5.0 e g ++ 4.9.0compile the following code fine (con -std=c++11 -Wall -Wextra -pedantic-errors) e le uscite del programma true:È valido il cast da A * a B * tramite dynamic_cast quando A e B non hanno un antenato comune?

#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

C'è una ragione particolare per cui sospetti che il comportamento che vedi possa essere sbagliato? (È una domanda valida in entrambi i casi, ma farebbe la differenza su cosa una buona risposta dovrebbe concentrarsi.) – hvd

+0

@hvd Ero quasi sicuro che non fosse possibile. Non so perché. :) – Constructor

+0

@hvd Intendo che ho pensato che l'output del programma dovrebbe essere 'false', non che l'uso di' dynamic_cast' potrebbe non essere valido in alcuni casi, ovviamente. – Constructor

risposta

7

Sì, secondo §5.2.7 [expr.dynamic.cast], per dynamic_cast<T>(v) (enfasi mia):

Se C è il tipo di classe a cui punti T o fa riferimento, la fase di esecuzione verifica logicamente come segue:

- Se, nell'oggetto più derivato puntato (riferito) a da v, v punti (si riferisce) a una base di base pubblica subobject di un oggetto C e se solo un oggetto di tipo C deriva dal subobject puntato (riferito) a da v i punti di risultato (si riferisce) a quell'oggetto C.

- Altrimenti, se V punti (riferisce) a una classe base pubblica sottoggetto dell'oggetto massima derivazione, e la tipo dell'oggetto massima derivazione ha una classe di base, di tipo C, cioè inequivocabile e pubblico, i punti di risultato (si riferisce) al sottooggetto C dell'oggetto più derivato.

- In caso contrario, la verifica del tempo di esecuzione non riesce.

Nel suo caso, v si riferisce ad un oggetto più derivata che è un'istanza del C, ma il tipo statico di v è un puntatore alla classe base pubblica A. La classe base C menzionata nell'offerta è B.

+0

Rilevante anche per qualcuno che potrebbe semplicemente chiederselo: 11.2.2 - 'In assenza di un identificatore di accesso per una classe base, si assume il pubblico quando la classe derivata è definita con la struct della chiave di classe e si assume il privato quando la classe è definita con la classe chiave di classe. –

+0

@MarcoA., immagino che sarebbe bello notare, sì. Grazie. – chris

+0

@ MarcoA. In che modo la tua citazione si riferisce alla domanda o alla risposta? – Constructor

8

Sì. Questo è talvolta noto come cross-casting e avrà esito positivo se sono entrambi sotto-oggetti di base dello stesso oggetto derivato, come sono qui.

dynamic_cast è necessario, poiché la conversione richiede le informazioni di runtime che entrambi fanno parte di un oggetto C. Per eseguire il cast statico, devi prima convertire esplicitamente in C*.

+1

Grazie. * Cross-casting * è un nuovo termine per me. – Constructor