2012-07-09 109 views
0

这就是我的意思是铸造POD对象,使用的static_cast

class V3 
{ 
public: 
float x,y,z; 
}; 

class V3_ 
{ 
public: 
float x,y,z; 
}; 

V3_ vec1; 
V3 vec2 = static_cast<V3_>(vec1); 

我应该怎么做,使在编译时该模具的工作?

谢谢。

编辑:

似乎有什么我想要做一些误解。 我可以写一个操作符到转换,但我希望它在编译时完成。

这里是两个允许static_cast的Vector3实现。我不知道它是如何工作的,但它确实有效。

http://www.ogre3d.org/docs/api/html/OgreVector3_8h_source.html

http://harry-3d-engine.googlecode.com/svn/trunk/NxOgreVec3.h

我能做到这一点投

void DynamicBody::SetLinearMomentum(const Vector3& vel) 
{ 
body->setLinearMomentum(static_cast<NxOgre::Vec3>(vel)); 
} 

我想我如何能做到这一点的解释。

编辑:

经进一步调查,我发现它实际上是如何做到这一点, 它调用

template<class user_xyz_vector_type> 
inline user_xyz_vector_type as() const { ... } 

不是一个实际的static_cast,但编译器接受它作为一个。 我真的很希望将pod转换为彼此是一件实际的事情。

回答

4

此演员阵容在任何时候都无法使用。你不能完全不相关,也不能相互转换类型。

我不知道你正在尝试做的,所以我不知道是什么工作的“工作”,在这种情况下意味着,但在原始内存级别的转换可以通过reinterpret_cast

V3 vec2 = reinterpret_cast<V3_&>(vec1); 
进行

但这是一个丑陋的黑客,不能保证工作,因为,再次,你的类型是无关的。有了同样的程度(甚至更好)的成功,你可以简单地将一个对象memcpy变成另一个对象。

+3

'memcpy'更好,甚至。如果'V3'和'V3_'具有相同的布局,并且通常对于给定的编译器来说是相同的,那么它就可以保证工作,没有理由将它们放在不同的位置。使用'reinterpret_cast',你可以控制优化器是否利用严格的别名规则:你可以很容易地得到在-O1下工作的代码,并在'-O3'上失败,这取决于vec1何时何地'被初始化。然后reinterpret_cast – 2012-07-09 18:58:42

+0

。 – mikbal 2012-07-09 19:32:14

+0

@mikbal:'reinterpret_cast'可能很容易因为Steve Jessop的评论中描述的原因而失败。 – AnT 2012-07-09 19:54:51

0
V3_ vec1; 
V3 vec2 = *(V3*)&vec1; 

编辑:仍然,你知道这可能不是一件好事吗?

1

你可以尽量避免使用完全铸成:

V3 vec2 = {vec1.x, vec1.y, vec1.z}; 

或写转换功能:

V3 to_V3(V3_ const & v) 
{ 
    V3 v3 = {v.x, v.y, v.z}; 
    return v3; 
} 

,并用它作为:

V3 vec2 = to_V3(vec1); 
+0

理想(我在这里挑剔)会继续正常工作,或者在第四个数据成员添加到这两个类时停止编译。你的'to_V3'函数可以有一个或多个静态断言,足以确保'V3'没有任何额外的数据成员不明。 – 2012-07-10 09:57:38

+0

@SteveJessop:静态断言这两个类的大小,还是其他的东西? – Nawaz 2012-07-10 10:04:37

+0

我在想,班级大小是相同的,(对于这个例子),你复制的字段大小的总和等于班级大小。如果一个类中有填充,并且有人添加了一个适合填充内容的新数据成员,那么您将永远不会通过查看大小来检测它。所以我的建议在所有情况下都不是完美的,但它不应该对由多个浮体组成的结构产生任何误报。 – 2012-07-10 10:25:30

1

的类型是不相关的,因此,你需要reinterpret_cast

V3_ vec1; 
V3 vec2 = reinterpret_cast<V3_&>(vec1); 
0

static_castV3V3_使用public:V3类的声明。 class V3 : public V3_。这样你可以转换对象。如果你想要多态性,并且你意识到你在做什么,就使用虚拟解构器。

+1

如果您要更改'V3'的定义,那么您可能只需'typedef V3_ V3;';-) – 2012-07-09 19:00:12

+0

如果V3_的功能和类型与V3不同,则不适用。这很可能是一个子类的类型转换,如'class A:public B'' class B'' void B :: function(){A * p =((A *)this); }而不是对象typedef – 2012-07-09 19:14:18