我的程序需要使用 void* 在动态调用情况下传输数据或对象,以便它可以引用任意类型的数据,甚至是原始类型的数据。但是,我最近发现,在具有多个基类的类的情况下,向下转换这些 void* 的过程会失败,甚至在对这些向下转换的指针调用方法后使我的程序崩溃,即使内存地址似乎是正确的。崩溃发生在访问“vtable”期间。
所以我创建了一个小测试用例,环境是 Mac OS X 上的 gcc 4.2:
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;
}
产生以下输出:
Decorated (direct)30,30
Shape 30,30
Square 30,30
Decorated (per void*) 73952,73952
DecoratedSquare 30,30
如您所见,“装饰(每个 void*)”结果是完全错误的。它也应该是 30,30,就像第一行一样。
无论我在 shape_cast() 中使用什么铸造方法,我总是会为 Decorated 部分获得相同的意外结果。这些 void *.
根据我对 C++ 的理解,这应该是可行的。有没有机会让它与 void* 一起工作?这可能是 gcc 中的错误吗?
谢谢