Mi programa necesita hacer uso de void * para transportar datos u objetos en situación de invocación dinámica, para que pueda referenciar datos de tipos arbitrarios, incluso primitivos tipos. Sin embargo, recientemente descubrí que el proceso de anulación de estos espacios vacíos * en el caso de clases con múltiples clases base falla e incluso bloquea mi programa después de invocar métodos en estos punteros, incluso si las direcciones de memoria parecen ser correctas. El bloqueo ocurre durante el acceso a "vtable".herencia múltiple: resultado inesperado después del lanzamiento de void * a la segunda clase base
Así que he creado un pequeño caso de prueba, el medio ambiente es gcc 4.2 en Mac OS X:
class Shape {
public:
virtual int w() = 0;
virtual int h() = 0;
};
class Square : public Shape {
public:
int l;
int w() {return l;}
int h() {return l;}
};
class Decorated {
public:
int padding;
int w() {return 2*padding;}
int h() {return 2*padding;}
};
class DecoratedSquare : public Square, public Decorated {
public:
int w() {return Square::w() + Decorated::w();}
int h() {return Square::h() + Decorated::h();}
};
#include <iostream>
template <class T> T shape_cast(void *vp) {
// return dynamic_cast<T>(vp); // not possible, no pointer to class type
// return static_cast<T>(vp);
// return T(vp);
// return (T)vp;
return reinterpret_cast<T>(vp);
}
int main(int argc, char *argv[]) {
DecoratedSquare *ds = new DecoratedSquare;
ds->l = 20;
ds->padding = 5;
void *dsvp = ds;
std::cout << "Decorated (direct)" << ds->w() << "," << ds->h() << std::endl;
std::cout << "Shape " << shape_cast<Shape*>(dsvp)->w() << "," << shape_cast<Shape*>(dsvp)->h() << std::endl;
std::cout << "Square " << shape_cast<Square*>(dsvp)->w() << "," << shape_cast<Square*>(dsvp)->h() << std::endl;
std::cout << "Decorated (per void*) " << shape_cast<Decorated*>(dsvp)->w() << "," << shape_cast<Decorated*>(dsvp)->h() << std::endl;
std::cout << "DecoratedSquare " << shape_cast<DecoratedSquare*>(dsvp)->w() << "," << shape_cast<DecoratedSquare*>(dsvp)->h() << std::endl;
}
produce el siguiente resultado:
Decorated (direct)30,30
Shape 30,30
Square 30,30
Decorated (per void*) 73952,73952
DecoratedSquare 30,30
Como se puede ver, el "decorado (por nulo *) "el resultado es completamente incorrecto. También debería ser 30,30 como en la primera línea.
Cualquiera que sea el método de conversión que uso en shape_cast() siempre obtendré los mismos resultados inesperados para la parte decorada. Algo está completamente mal con este vacío *.
Desde mi comprensión de C++ esto debería estar realmente funcionando. ¿Hay alguna posibilidad de que esto funcione con el vacío *? ¿Puede ser esto un error en gcc?
Gracias
Solo puede usar reinterpret_cast para convertir a void * y luego volver al tipo original. Puedes __NOT__ lanzar al vacío * y luego a cualquier otra cosa. –
Sería mucho mejor utilizar el patrón de decorador que MI, pero eso no resolvería el problema de conversión de void *. – quamrana