Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/128.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/haskell/9.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/powerbi/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ C++;代数数据类型的等价物?_C++_Haskell_Algebraic Data Types - Fatal编程技术网

C++ C++;代数数据类型的等价物?

C++ C++;代数数据类型的等价物?,c++,haskell,algebraic-data-types,C++,Haskell,Algebraic Data Types,假设我有一个Haskell代码: 数据刚体=刚体矢量3矢量3浮动形状--位置、速度、质量和形状 数据形状=浮球-半径 |凸多边形[三角形] < C++中最好的表达方式是什么? struct Rigid_body { glm::vec3 position; glm::vec3 velocity; float mass; *???* shape; }; 我要问的是,当结构可以是两种类型中的一种时,如何在结构内部表示形状。您需要创建一个基类shape。从这里,您可以

假设我有一个Haskell代码:

数据刚体=刚体矢量3矢量3浮动形状--位置、速度、质量和形状
数据形状=浮球-半径
|凸多边形[三角形]
< C++中最好的表达方式是什么?

struct Rigid_body {
    glm::vec3 position;
    glm::vec3 velocity;
    float mass;
    *???* shape;
};

我要问的是,当结构可以是两种类型中的一种时,如何在结构内部表示形状。

您需要创建一个基类
shape
。从这里,您可以创建实际的形状类,
Ball
ConvexPolygon
。您需要确保
Ball
ConvexPolygon
是基类的子类

class Shape {
    // Whatever commonalities you have between the two shapes, could be none.
};

class Ball: public Shape {
    // Whatever you need in your Ball class
};

class ConvexPolygon: public Shape {
    // Whatever you need in your ConvexPolygon class
};
现在,你可以做一个这样的广义对象

struct Rigid_body {
    glm::vec3 position;
    glm::vec3 velocity;
    float mass;
    Shape *shape;
};

当您实际初始化
shape
变量时,可以使用
Ball
ConvexPolygon
类初始化它。你可以继续按你想要的形状制作很多形状。

< P>有不同的方法可以用来解决C++中的问题。 纯OO方法是定义一个接口
Shape
,并将两个不同的选项作为实现该接口的派生类型。然后,
刚体
将包含指向
形状
的指针,该形状将被设置为指向球或凸多边形。赞成:人们喜欢OO(不确定这是不是一个真正的赞成:)),它很容易扩展(你可以在以后添加更多的形状而不改变类型)。缺点:您应该为
形状定义一个合适的接口,它需要动态分配内存


抛开OO不谈,您可以使用
boost::variant
或类似的类型,这基本上是一个标记的联合,它将保存其中一个类型。Pro:没有动态分配,形状是对象的局部形状。Con:不是纯粹的OO(人们喜欢OO,你记得吗?),不容易扩展,不能一般使用< /p> < p>的形状。C++中的规范方式是Justin Wood回答中的基于继承的解决方案。通常,您赋予
形状
各种
形状

<>但是,C++也有<代码>联合< /COD>类型。您可以改为执行“标记的联合”:

您可以使用
标记
成员说明
形状
还是
正方形
或其他任何形状。您可以在
标签上
切换
成员等等

这样做的缺点是
形状
正方形
和其他形状的最大值大一个
int
;OCaml和诸如此类的东西中的对象没有这个问题


您使用哪种技术取决于您如何使用
形状。

要在这里引入另一种可能性,您还可以使用
boost::variant
,它将作为
std::variant
添加到C++17中的标准库中:

struct Ball { float radius; };
struct ConvexPolygon { Triangle t; }

using Shape = boost::variant<Ball, ConvexPolygon>;
struct Ball{float radius;};
结构凸多边形{三角形t;}
使用Shape=boost::variant;
这种方法的优点是:

  • 类型安全,与标记的联合不同
  • 可以保存复杂类型,而不是联合
  • 与OO不同,不需要跨所有“子”类型的统一接口
一些缺点:

  • 有时需要在访问变量时进行类型检查,以确认它是您希望的类型,这与OO不同
  • 要求您使用boost,或与C++17兼容;对于一些编译器或一些普遍支持OO和联合的组织来说,这可能很困难

问题是什么?如何引用尚未定义的其他类型
形状
?如何创建一个类型
Shape
,它实际上是一组其他类型中的一种?所有这些?你可能想考虑一个不同的编程范例,把Haskell直接翻译成C++是很可能不会成功的……我想最简单的方法是结构的结合,但是我宁愿尝试为Haskell编写一个解析器而不是C++中的任何程序。“变体“键入C++使用的任何范式。请参阅我的编辑。@ USER 313395:从尊重方面来说,先学习C++然后解决这个问题是更好的。不要试图将Haskell翻译成C++,而不需要事先知道C++的习语。你可能想让代码> RigIDyBooS/<代码>有一个<代码>形状>代码>而不是<代码>形状>代码>,这样你就可以避免切片。它已经被固定了。C++中的联合类型是有限的,在C++ 11中使用起来很难。如果union中的任何元素不是POD类型,则需要添加自己的构造函数、复制构造函数、赋值并手动管理对象的生存期。这就是
boost::variant
为您解决的问题。@DavidRodríguez dribeas:是的。我无法想象为什么一个
正方形
不是豆荚。好吧,在哈斯克尔代码中,它不是
正方形
,而是
凸多边形
,它可能具有可变数量的vertices@DavidRodríguez dribeas:我明白了。@Nathan:是的,你可以用一堆
dynamic_cast
s来代替。但是,我不知道如何对对象的动态类型进行
切换。我并不真正关心一般性地使用它。我不想强迫我的
刚体的创建者手动分配内存。我宁可为刚体做两个构造函数,也可以构造形状本身。@ USE313395: C++中的构造函数不是Haskell中的构造函数。内存分配是你最终要做的事情,如果你正在做C++,这不是一个可怕的负担,用户(你的C++的构造函数RigIDBOSS/CODE)可以采用<代码>形状>代码>。
struct Ball { float radius; };
struct ConvexPolygon { Triangle t; }

using Shape = boost::variant<Ball, ConvexPolygon>;