假设我有两个不同的类,它们以相同的内部方式表示2D坐标数据,如下所示:
class LibA_Vertex{
public:
// ... constructors and various methods, operator overloads
float x, y
};
class LibB_Vertex{
public:
// ... same usage and internal data as LibA, but with different methods
float x, y
};
void foobar(){
LibA_Vertex * verticesA = new LibA_Vertex[1000];
verticesA[50].y = 9;
LibB_Vertex * verticesB = reinterpret_cast<LibB_Vertex*>( vertexA );
print(verticesB[50].y); // should output a "9"
};
鉴于两个类相同并且上面的函数,我可以可靠地指望这个指针转换在每种情况下按预期工作吗?
(背景,我需要一种简单的方法来交换两个具有相同Vertex类的独立库之间的顶点数组,我想避免不必要地复制数组。)
答案 0 :(得分:13)
C ++ 11添加了一个名为 layout-compatible 的概念,适用于此处。
如果两个标准布局结构(第9条)类型具有相同数量的非静态数据成员和相应的非静态数据成员,则它们是布局兼容 (按照声明顺序)具有布局兼容类型(3.9)。
,其中
标准布局类是一个类:
- 没有非标准布局类(或此类类型的数组)或引用类型的非静态数据成员,
- 没有虚函数(10.3),没有虚基类(10.1),
- 对所有非静态数据成员具有相同的访问控制(第11条),
- 没有非标准布局基类
- 在大多数派生类中没有非静态数据成员,并且最多只有一个具有非静态数据成员的基类,或者没有包含非静态数据成员的基类,并且
- 没有与第一个非静态数据成员相同类型的基类。
标准布局结构是使用 class-key
struct
或标准布局类 > class-keyclass
。标准布局联合是使用 class-key
union
定义的标准布局类。
最后
指向cv-qualified和cv-nonqualified version(3.9.3)的布局兼容的指针 类型应具有相同的值表示和对齐要求(3.11)。
保证reinterpret_cast
可以将指向一种类型的指针转换为指向任何布局兼容类型的指针。
答案 1 :(得分:1)
我会把这个转换包装在一个类中(这样如果你需要更改平台或其他东西,它至少会在一个地方进行本地化)但是是的,它应该是可能的。
您还希望使用reinterpret_cast
,而不是static_cast
。
答案 2 :(得分:1)
理论上这是一种未定义的行为。但是,它可能适用于某些系统/平台。
我建议您尝试将 2个类合并为1.即
class Lib_Vertex{
// data (which is exactly same for both classes)
public:
// methods for LibA_Vertex
// methods for LibB_Vertex
};
将方法添加到class
不会影响其大小。您可能需要稍微改变一下设计,但这是值得的。
答案 3 :(得分:0)
从技术上讲,这是未定义的行为。实际上,如果使用相同的编译器来编译这两个类,如果字段以相同的顺序声明,具有相同的类型和相同的访问级别,它们在内存中将具有相同的布局。