自定义结构体类型转换

3

我有两个结构体,定义了给定坐标系中的一个点和向量。

struct point3D
{
  float x;
  float y;
  float z;
};
struct vector3D
{
  float x;
  float y;
  float z;
};

它们被定义为两个不同的结构体的原因是因为有其他函数将点(point3D)与向量(vector3D)区分对待,尽管它们具有相同类型的成员变量。

我想知道是否有一种方法可以将它们中的一个强制转换为另一个,例如:

point3D variable1;
vector3D variable2;
variable2=(vector3D)variable1;

您可以定义一个转换运算符:https://en.cppreference.com/w/cpp/language/cast_operator - UnholySheep
1
也许更合理的做法是像 point - originpoint.as_vector_from_origin() 这样做,而不是直接转换。 - chris
1
也许你可以从vector3D派生出point3D,因为一个点是一个位置向量。 - Karsten Koop
你正在使用OpenCV吗? - Joseph D.
我喜欢像汇编程序员一样思考,并将C和C++视为可移植的汇编语言。有时候,禁用别名优化并强制将一个结构体指针转换为兼容指针是很好的选择。 - Erik Alapää
显示剩余2条评论
2个回答

3

你可以做到这一点

struct vector3D
{
  float x;
  float y;
  float z;
};

struct point3D
{
  float x;
  float y;
  float z;
  explicit operator vector3D() {
    return {x, y, z};
  }
};

为什么要使用 explicit?(只是为了我的学习)。谢谢。 - Paul Sanders
@PaulSanders 显式声明是因为 OP 给出的示例不需要隐式转换,而隐式转换应该避免。 - Tyker
好的,但是也许他的例子应该是variable2 = variable1; - Paul Sanders
@PaulSanders 也许本来应该有,但是我还是加上了显式的。 - Tyker
2
@PaulSanders,如果拥有两个不同的类的整个目的是确保您不混合和匹配它们的语义,那么在它们之间进行隐式转换有点违背了初衷。 - chris
@chris 是的,但是我之前确实说过“你为什么要这样做呢?”- 但是从来没有得到回应。我认为这个问题相当混乱。 - Paul Sanders

0

我会把刀子给你,虽然我相信你不是个外科医生。Karsten在评论中建议从向量派生点。如果这样不好,请继续作弊:适当的转换运算符是reinterpret_cast

point3D variable1; 
vector3D variable2;
variable2=reinterpret_cast<vector3D&>(variable1);

但那是C ++。如果您需要C样式转换,则指针转换是正确的方法:

variable2=*(vector3D*)(void*)&variable1;

以上两种解决方案都不被鼓励。如果我是你,我会考虑重新设计。


在C语言中你不能这样做,因为它违反了严格别名规则,请参见C11标准-§6.5表达式(p6,7) - David C. Rankin
@DavidC.Rankin 不太相关。在任何两个对象指针之间进行类型转换一直是有效的 C 代码。片段中的 void 指针转换是我使用的一种过度设计。 - Red.Wave
不是为了争论,但在 C 语言中,当您尝试通过 vector3D 指针(而不是 char)访问 point3D 类型的对象时,这违反了严格别名规则。 *"对于访问其存储值的对象的有效类型是对象的声明类型..."*。现在你可以争辩说每个都是与有效类型兼容的类型,但上面的 C 示例只是将 point3D 强制转换为 vector3D。正确的方法是使用类型之间的 union - David C. Rankin
同意。这是不使用它的一个原因。但类型转换在广泛使用,甚至在标准API中也是如此(例如sockaddr_in等)。而且强制转换和联合之间没有区别:除了char / void之外的任何类型游戏都不能保证,尽管在常见情况下正确处理。在缺乏别名的情况下(示例代码不存储指针,只读取指针),没有实际问题。但答案中的“作弊”一词暗示了类型游戏周围的微妙和危险。 - Red.Wave
@Red.Wave:识别一个类型的左值或指针是从另一个指针或左值派生而来的情况,这是一个实现质量问题,标准并不试图要求编译器具有足够的质量适用于任何特定目的。另一方面,我认为标准的作者们并没有期望高质量的编译器将“别名”这个术语解释为包括严格嵌套使用派生和使用指针和左值的情况,因为没有像样的编译器应该会遇到这种问题。 - supercat

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接