2011-01-10 30 views
10

Supongamos que me dan una biblioteca C++ llena de herencia. Me dan un Base* en una función cuando sé que en realidad apunta a un objeto Derived y Derived hereda Base. Pero no sé qué tipo de herencia es (público/protegido/privado). Tampoco sé si hay alguna función virtual en la jerarquía.static_cast vs dynamic_cast

Ante esta situación, sin mirar en el código fuente y/o documentación deBase y Derived, que echo debo usar? ¿O debería consultar primero el código/la documentación para asegurarme acerca del polimorfismo?

Antecedentes

estoy escribiendo changeEvent función de QMainWindow en Qt 4.7. La función changeEvent toma QEvent* que puedo convertir a otro tipo conociendo QEvent::type(). Me preguntaba si debería usar static_cast o dynamic_cast.

Gracias.

+3

Si alguna biblioteca que usa usa herencia 'protected', es hora de encontrar una mejor biblioteca escrita. –

+0

Esta pregunta podría ayudar: http://stackoverflow.com/questions/28002/regular-cast-vs-static-cast-vs-dynamic-cast –

+2

@Zac: Desearía poder rechazar los comentarios. ¿Cómo puede juzgar si la herencia protegida es la herramienta adecuada para el trabajo si no sabe lo que hace esa biblioteca? – Puppy

Respuesta

17

Utilice static_cast. Si sabe que su Base* apunta a Derived, entonces use static_cast. dynamic_cast es útil para cuando podría apunta a un derivado.

+1

Quizás lo sepa ahora. Pero él está usando una biblioteca y estoy seguro de que la biblioteca no garantiza que no cambien los detalles de implementación. La interfaz es Base *, por lo que es ** TODO ** lo que puede suponer. Por lo tanto, ** DEBE ** utilizar dynamic_cast <> para que pueda verificar que sus suposiciones contengan palabras posteriores. –

+0

@Martin: Ese es su problema, no el mío. Si él * sabe * que efectivamente apunta a un derivado, entonces la raíz de ese conocimiento está fuera de los límites de lo que posiblemente pueda responder. – Puppy

+2

El probelma es que él no puede saber. Su conocimiento se limita al tiempo espacio cordinates de esta instancia en particular. Por lo tanto, necesitamos enfatizar que el PO está equivocado en su suposición de que él sabe. Él sabe ahora, pero el conocimiento no es transferible al futuro. Por lo tanto, porque está equivocado, static_cast es la respuesta incorrecta (es la respuesta correcta si el OP fue correcto (pero no lo es)). El único momento en que puede suponer que la interfaz es Derivada es cuando devuelve un Derivado *; de lo contrario, puede devolver cualquier cosa derivada de Base * (es por eso que tenemos interfaces en el código). –

3

De MSDN -

En general se utilizan static_cast cuando se quiere convertir tipos de datos numéricos, como enumeraciones a enteros o enteros a los flotadores, y está seguro de los tipos de datos que intervienen en la conversión. Las conversiones de static_cast no son tan seguras como las conversiones de dynamic_cast, porque static_cast no verifica el tipo de tiempo de ejecución, mientras que dynamic_cast lo hace. Un dynamic_cast a un puntero ambiguo fallará, mientras que un static_cast se devolverá como si nada estuviera mal; esto puede ser peligroso Aunque las conversiones dynamic_cast son más seguras, dynamic_cast solo funciona en punteros o referencias, y la verificación de tipo en tiempo de ejecución es una sobrecarga.

Para obtener más información, echa un vistazo a este link

8

En caso de duda, se debe preferir dynamic_cast. Puede ser más lento, pero probablemente no notarás la diferencia de todos modos.

Si necesita velocidad, use el siguiente fragmento:

template <typename Derived, typename Base> 
Derived safe_static_cast(Base b) 
{ 
    assert((void*)dynamic_cast<Derived>(b) && "safe_static_cast failed!"); 
    return static_cast<Derived>(b); 
} 

O algo equivalente.

La idea es que, en las compilaciones de depuración, compruebe que es de hecho lo que pensaste que sería, y que crea versiones ... bueno, todo ya ha sido probado, ¿no es así?

+1

no es necesario '(void *)' emitir –

+0

@Gene: es ciertamente feo :) Estaba tratando de evitar la sobrecarga para el caso de referencia. –