Respuesta corta: en C++, las matrices de valores nunca son polimórficas, incluso si su contenido es, y no puede ser tratado de esta manera. Es decir, no puede tratar un derived ad[N]
como si fuera un base ab[N]
.
Respuesta larga: La razón de esto está profundamente enterrada en la aritmética del puntero de C. Si tiene un int* pi
y lo incrementa ++pi
, no se incrementará simplemente a la siguiente dirección de memoria. Si lo hiciera, no apuntaría al siguiente int
ya que esto no comienza en la siguiente dirección. Entonces, en su lugar, se agregan sizeof(int)
bytes al puntero. (Un ejemplo concreto podría ayudar: en arquitecturas con 8bit char
tipos - char
siendo, por definición, lo que C y C++ consideran el tamaño de byte de la arquitectura - y 32bit int
tipos, int
tiene el tamaño de 4 bytes. Por lo tanto, ++pi
agregará 4 a la dirección de punteros, de modo que apunte al siguiente int
). La misma aritmética se aplica a todas las demás operaciones del puntero. Así, por ejemplo, con int* pi2=pi+1
, pi2
señalarán sizeof(int)
bytes detrás pi
, aunque pi2-pi
rendirá 1.
Así, suponiendo que entiende el último párrafo, vamos a volver a las matrices. Si tiene una matriz derived ad[N]
, la dirección de ad[1]
es sizeof(derived)
bytes mayor que la dirección de ad[0]
.(Eso sin tener en cuenta la alineación para no complicar aún más el problema). Sin embargo, si tiene un base* pb
apuntando a ad[0]
, al aumentarlo, se pondrá el sizeof(base)
detrás de la dirección del primer elemento, que si (como es el caso su ejemplo) sizeof(base) < sizeof(derived)
, es no la dirección de ad[1]
, pero en algún lugar en el medio de ad[0]
.
La única cosa que puede hacer para tratar el contenido matriz como si se tratara de todas las clases de base, es iterar sobre la matriz mediante un derived*
y lanzar este puntero a base*
dentro el bucle:
derived d[5];
derived* begin = d;
const derived* end = d + sizeof(d)/sizeof(d[0]); // points one beyond the last element
while(begin != end)
{
base* pb = begin;
cout<< pb->_bval;
++begin;
}
(Tenga en cuenta que también he cambiado su código para usar los iteradores idiomáticos de inicio/fin de C++)
Gracias por ser preciso. –