gpt4 book ai didi

c++ - 多重继承 : unexpected result after cast from void * to 2nd base class

转载 作者:可可西里 更新时间:2023-11-01 17:04:57 30 4
gpt4 key购买 nike

我的程序需要使用 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

如您所见,“Decorated (per void*)”结果是完全错误的。它也应该是第一行中的 30,30。

无论我在 shape_cast() 中使用什么转换方法,我总是会为装饰部分获得相同的意外结果。这些 void * 完全有问题。

根据我对 C++ 的理解,这应该可以正常工作。有没有机会让它与 void* 一起工作?这可能是 gcc 中的错误吗?

谢谢

最佳答案

重复十次 - 这是您可以安全地使用 reinterpret_cast 做的唯一事情指针是 reinterpret_cast它回到它来自的相同指针类型。这同样适用于转换为 void* : 您必须转换回原始类型。

因此,如果您转换 DecoratedSquare*void* ,您必须将其转换回 DecoratedSquare* .不是Decorated* , 不是 Square* , 不是 Shape* .其中一些可能在您的机器上工作,但这是好运和特定于实现的行为的结合。它通常适用于单继承,因为没有明显的理由以停止其工作的方式实现对象指针,但这并不能保证,而且它通常不能用于多重继承。

您说您的代码通过 void* 访问“任意类型,包括原始类型”。这没有任何问题——大概接收数据的人都知道将其视为 DecoratedSquare*。而不是,比如说,int* .

如果谁收到就只知道把它当作一个基类,比如Decorated* , 然后将其转换为 void* 的人应该static_cast它首先到基类,然后到 void* :

void *decorated_vp = static_cast<Decorated*>(ds);

现在当你施放 decorated_vp返回Decorated* , 你会得到 static_cast<Decorated*>(ds) 的结果,这就是您所需要的。

关于c++ - 多重继承 : unexpected result after cast from void * to 2nd base class,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2379427/

30 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com