具有共享继承的C++中的多态性

use*_*527 8 c++ polymorphism

我正在研究实现GIS中使用的一套点类型,它们是2D(xy),3D(xyz或xym)或4D(xyzm).M坐标是度量坐标,其他坐标应该是显而易见的.不过,我似乎无法弄清楚如何使PointZM类股xy从成员Point类.这是我的代码:

#include <iostream>

class Point {
  public:
    double x, y;
    Point (double xNew, double yNew) : x(xNew), y(yNew) {};
};

class PointZ : public Point {
  public:
    double z;
    PointZ (double xNew, double yNew, double zNew) :
        Point(xNew, yNew), z(zNew) {};
};

class PointM : public Point {
  public:
    double m;
    PointM (double xNew, double yNew, double mNew) :
        Point(xNew, yNew), m(mNew) {};
};

class PointZM : public PointZ, public PointM {
  public:
      PointZM (double xNew, double yNew, double zNew, double mNew) :
          PointZ(xNew, yNew, zNew), PointM(xNew, yNew, mNew) {};
};

int main () {
    Point p (1, 2);
    PointZ pZ (1, 2, 3);
    PointM pM (1, 2, 4);
    PointZM pZM (1, 2, 3, 4);
    std::cout << "Point: " << sizeof(p) << std::endl;
    std::cout << "PointZ: " << sizeof(pZ) << std::endl;
    std::cout << "PointM: " << sizeof(pM) << std::endl;
    std::cout << "PointZM: " << sizeof(pZM) << std::endl;
}
Run Code Online (Sandbox Code Playgroud)

打印每个类的四个实例的大小:

Point: 16
PointZ: 24
PointM: 24
PointZM: 48
Run Code Online (Sandbox Code Playgroud)

我期待最后PointZM是32个字节,因为它应该有x,y,zm成员.如何获取两个继承的类PointZPointM共享其继承的Point成员?有两种方法可以获得两个类的联合吗?我是这个主题的C++新手.

简单的点几何形状对于为什么要对继承感到困扰的动机并不明显.然而,当进一步开发不同的几何类型时,如LineString(2D),LineStringZ(3D),LineStringM(3D)或LineStringZM(4D),length如果存在Z维,它们将具有不同的方法.只有存在Z维度时,长度方法才会有不同的计算方式,而且我不想加倍努力将其添加到类LineStringZLineStringZM类中.

n. *_* m. 5

有2D几何,3D几何和4D几何.3D几何体不是2D几何体的精细实例,它是一种完全不同的野兽.同样,4D几何不是3D几何的特殊情况.

公共继承旨在表达is-a关系.不同尺寸的几何形状之间没有这种关系.

非公共继承可用于代码共享,但不清楚在2D,3D和4D情况下可以共享哪些代码.

但是,所有这些几何都是通用N维几何的情况,N是参数.用类模板对它进行建模是很自然的.

   template <size_t N>
   class Point
   {
      std::array<double, N> coord;
      // ... rest of the code ...
   };
Run Code Online (Sandbox Code Playgroud)


Joh*_*nck 4

您问题的直接答案是使用虚拟继承。这将使 PointZM 仅包含一个点,而不是两个。您稍后可能会认为这不值得如此复杂,而只需分别实现 PointZ、PointM 和 PointZM,但这取决于您。

在我的系统上,虚拟继承为每个虚拟派生类型添加 8 个字节,而 PointZM 保持相同的大小,因为它包含的额外 Point 的 16 个字节被删除,但我们现在为虚拟基类存储了两个额外的指针。那么尺寸看起来像这样:

Point: 16
PointZ: 32
PointM: 32
PointZM: 48
Run Code Online (Sandbox Code Playgroud)