c++ casting virtual-inheritance static-cast diamond-problem

c++ - Abatido en una jerarquía de diamantes



casting virtual-inheritance (2)

¿Por qué static_cast no puede descender desde una base virtual?

struct A {}; struct B : public virtual A {}; struct C : public virtual A {}; struct D : public B, public C {}; int main() { D d; A& a = d; D* p = static_cast<D*>(&a); //error }

g ++ 4.5 dice:

error: cannot convert from base ‘A’ to derived type ‘D’ via virtual base ‘A’

La solución es usar dynamic_cast ? pero por qué. ¿Qué es lo racional?

editar
Muy buenas respuestas a continuación. Sin embargo, no hay respuestas que detallan exactamente cómo los subobjetos y vtables terminan siendo ordenados. El siguiente artículo da algunos buenos ejemplos para gcc:
http://www.phpcompiler.org/articles/virtualinheritance.html#Downcasting


Debido a que si el objeto era en realidad de tipo E (derivado de D), la ubicación de A subobjeto A relación con el subobjeto D podría ser diferente que si el objeto fuera realmente D

En realidad, ya sucede si considera la conversión de A a C. Cuando asigna C, tiene que contener una instancia de A y vive en algún desplazamiento específico. Pero cuando asigna D, el subobjeto C se refiere a la instancia de A que vino con B, por lo que su compensación es diferente.


La respuesta obvia es: porque la norma lo dice. La motivación detrás de esto en la norma es que static_cast debe ser casi trivial, como máximo, una simple suma o resta de una constante al puntero. Donde está el downcast a una base virtual requeriría un código más complicado: quizás incluso con una entrada adicional en el vtable en algún lugar. (Requiere algo más que constantes, ya que la posición de D respecto a A puede cambiar si hay una derivación adicional). La conversión es obviamente factible, ya que cuando se llama una función virtual en un A* , la función se implementa en D , el compilador debe hacerlo, pero la sobrecarga adicional se consideró inadecuada para static_cast . (Presumiblemente, la única razón para usar static_cast en estos casos es la optimización, ya que dynamic_cast suele ser la solución preferida. Por lo tanto, cuando static_cast probablemente sea tan costoso como dynamic_cast todos modos, ¿por qué?)