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é?)