My program should use void * to transfer data or objects into a dynamic call situation so that it can refer to data of arbitrary types, even primitive types. However, I recently discovered that the process of dropping these void * in the case of classes with several base classes fails and even my program crashes after calling methods on these hidden pointers, even if the memory addresses seem correct. A crash occurs while accessing "vtable".
So, I created a small test case, the environment is gcc 4.2 on 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; }
outputs the following result:
Decorated (direct)30,30 Shape 30,30 Square 30,30 Decorated (per void*) 73952,73952 DecoratedSquare 30,30
As you can see, the result "Awarded (for void *)" is completely erroneous. It should also be 30.30, as in the first line.
Whatever casting method I use in shape_cast (), I always get the same unexpected results for the Decorated part. Something is completely wrong with these void *.
From my understanding of C ++, this should be really working. Is there a chance to make this work with void *? Could this be a bug in gcc?
thanks
c ++ gcc casting multiple-inheritance void-pointers
Andrรฉ pareis
source share