钻石继承的解决方案,但它是否合适?

时间:2015-07-02 19:43:28

标签: c++ virtual-inheritance diamond-problem

除了我一直在做的其他各种事情,我也一直在做一个图像api。我遇到的一个问题是需要有一个包含图像尺寸的图像基类。从它将分支ImageIn和ImageOut,并从那些来ImageIO。这是我最初的解决方案;

class ImageBase{
public:
  point<int> Dim() const=0;
};

class ImageI : virtual public ImageBase{
public:
  virtual unsigned int get(int x, int y) const=0;
};

class ImageO : virtual public ImageBase{
public:
  virtual void set(int x, int y, unsigned int col)=0;
};

class ImageIO : public ImageI, public ImageO{
};

class Bitmap : public ImageIO{
  ...
};

当然,现在它们是两个vtable指针并且对每个图像实例都很暗淡,我认为给定一个像素数组的大小,它可能不值得担心,但是有一些令人不快的事情,所以我这个解决方案的目的;

class ImageIO{ // could also be called ImageBase
public:
  point<int> Dim() const=0;
  virtual unsigned int get(int x, int y) const=0;
  virtual void set(int x, int y, unsigned int col)=0;
};

class ImageI : public ImageIO{
public:
  point<int> Dim() const=0;
  virtual unsigned int get(int x, int y) const=0;
private:
  virtual void set(int x, int y, unsigned int col)=0;
};

class ImageO : public ImageIO{
public:
  point<int> Dim() const=0;
  virtual void set(int x, int y, unsigned int col)=0;
private:
  virtual unsigned int get(int x, int y) const=0;
};

class Bitmap : public ImageIO{
  ...
};

现在,因为ImageO和ImageI中的某些运算符是私有的,所以无法从该类型的指针访问它们,几乎完成了类的输入和输出版本的完成。但是有一个小问题,现在的转换语法有点复杂。

ImageI* myImgInput = static_cast<ImageI*>((ImageIO*)(&myReal));

我认为一些聪明的使用铸造功能可以使过程自动化,所以最后一个问题是,这有什么固有的缺陷吗?我已经用一个小的实现测试了它,并且它完全可以工作,但我不想完成api,然后必须重新开始。

修改

请注意,为了清楚起见,第二个示例中的ImageBase现在是ImageIO,第二个示例中的ImageI和ImageO 不应该应该从ImageIO中实际继承

1 个答案:

答案 0 :(得分:0)

如果基数具有数据成员

,则无效

使用以下尺寸

Imagaebase=4
ImageI=12 + 4 from Imagebase
ImageO=24 + 4 from Imagebase

在第一个示例中,Bitmap的大小为4 + 12 + 24(注意Imagebase只计算一次)= 40

在第二种情况下,Bitmap的大小为4

如果尺寸如此偏差,则无法进行投射

如果任何类中没有数据,则:

基地应为ImageIO并且其中包含所有功能

然后让ImageIImageO继承它以使不允许的函数成为私有函数。然后不需要铸造。

这将如下所示:

class ImageIO{
public:
  point<int> Dim() const=0;
  virtual unsigned int get(int x, int y) const=0;
  virtual void set(int x, int y, unsigned int col)=0;
};

class ImageI : virtual public ImageIO{
private:
  virtual void set(int x, int y, unsigned int col)
  {
        // Can't be called
  }
};

class ImageO : virtual public ImageIO{
private:
  virtual unsigned int get(int x, int y) const
  {
        // Can't be called
  }
};

class Bitmap : public ImageIO{
  ...
};