假设我有两个来自两个不同库的相同成员的类:
namespace A {
struct Point3D {
float x,y,z;
};
}
namespace B {
struct Point3D {
float x,y,z;
};
}
当我尝试交叉投射时,它起作用了:
A::Point3D pa = {3,4,5};
B::Point3D* pb = (B::Point3D*)&pa;
cout << pb->x << " " << pb->y << " " << pb->z << endl;
在哪种情况下这可以保证有效?总是?请注意,编辑外部库以添加对齐编译指示或类似的东西是非常不受欢迎的。我在Ubuntu 8.10上使用g ++ 4.3.2。
答案 0 :(得分:2)
如果您使用的结构只是数据而且没有使用继承,我认为它应该始终有效。
只要它们是POD就应该没问题。 http://en.wikipedia.org/wiki/Plain_old_data_structures
根据标准(1.8.5)
“除非它是一个位域(9.6),否则大多数派生的对象应具有非零大小并且应占用一个或多个字节 存储。基类子对象可以具有零大小。 POD的一个对象5) 类型(3.9)应占用连续的字节 存储“。
如果它们占用连续的存储字节并且它们是具有不同名称的相同结构,则转换应该成功
答案 1 :(得分:2)
如果两个POD结构以相同的成员序列开头,则标准保证您可以通过联合自由访问它们。您可以将A :: Point3D存储在并集中,然后从B :: Point3D成员读取,只要您只触及属于初始公共序列的成员即可。 (所以如果一个struct包含int,int,int,float,另一个包含int,int,int,int,那么你只能访问三个第一个int。)
因此,这似乎是您的代码应该起作用的一种保证方式。 这也意味着演员应该工作,但我不确定这是否在标准中明确说明。
当然,所有这些都假定两个结构都使用相同的编译器进行编译,以确保相同的ABI。
答案 2 :(得分:0)
这一行应该是:
B::Point3D* pb = (B::Point3D*)&pa;
请注意&
。我认为你所做的是两个指针之间的reinterpret_cast
。实际上,无论两个指针的类型如何,您都可以将任何指针类型重新解释为另一个指针类型。但这不安全,而且不便携。
例如,
int x = 5;
double* y = reinterpret_cast<double*>(&x);
你只是采用C风格,所以第二行实际上等于:
double* z = (double*)&x;
我只是讨厌C-Style,因为你无法从一个角度来看出演员的目的:)
这是什么情况 保证工作?
这不是类型之间的真实投射。例如,
int i = 5;
float* f = reinterpret_cast<float*>(&i);
现在f
指向i
指向的同一个地方。所以,没有进行任何转换。当您取消引用f
时,您将获得具有整数i
的相同二进制表示的浮点数。我的机器上有四个字节。
答案 3 :(得分:0)
以下是非常安全的:
namespace A {
struct Point3D {
float x,y,z;
};
}
namespace B {
typedef A::Point3D Point3D;
}
int main() {
A::Point3D a;
B::Point3D* b = &a;
return 0;
}
答案 4 :(得分:-2)
我确切地知道它不起作用:
可能是其他人......