C++ 处理模板创建的更好方法?

C++ 处理模板创建的更好方法?,c++,templates,design-patterns,c++11,C++,Templates,Design Patterns,C++11,试图找出一个更好的设计 假设我们有一个从模板矩阵库继承的模板图像类(在本例中是Eigen,但它可以是任何东西) 无论哪种情况,我的BaseImage类都必须公开我需要从矩阵库中使用的所有功能,这有点违背了继承的目的 问题是,如果有一个比这里更好的设计,它会变得相当麻烦如果我能在注释中显示代码,我会将其作为注释发布。。。对我来说,这似乎很明显,你可能已经想到了。为什么这不是你要找的 class Image { public: Image (int bytesPerPixelIn = 1) {

试图找出一个更好的设计

假设我们有一个从模板矩阵库继承的模板图像类(在本例中是Eigen,但它可以是任何东西)

无论哪种情况,我的BaseImage类都必须公开我需要从矩阵库中使用的所有功能,这有点违背了继承的目的


问题是,如果有一个比这里更好的设计,它会变得相当麻烦

如果我能在注释中显示代码,我会将其作为注释发布。。。对我来说,这似乎很明显,你可能已经想到了。为什么这不是你要找的

class Image
{
public:
  Image (int bytesPerPixelIn = 1) { data_ = NULL; bytesPerPixel=bytesPerPixelIn;};

  void readImage (int width, int height);
private:
  int       bytesPerPixel_;
  void*     data_;
};

void Image::read (int width, int height, ...)
{
   data_ = new unsigned char [width*height*pixelSize(imageType_)];
   //...
}

//And you can inherit from this if need be to add special functions 
//like interleaving in BMP files
编辑:好的,我明白了。这样会更好吗

template <typename PixelType>
class Image
{
public:
  Image () { data_ = NULL; };

  virtual void allocateImage (int width, int height)
  {
    data_ = new PixelType [width*height]; 
  }
  virtual void readImage (int width, int height) = 0;
private:
  PixelType*     data_;
};

template <typename PixelType>
class ImageTIFF: public Image <PixelType> ...
模板
阶级形象
{
公众:
Image(){data_u=NULL;};
虚拟空分配图像(整数宽度、整数高度)
{
数据=新的像素类型[宽度*高度];
}
虚空读取图像(整数宽度、整数高度)=0;
私人:
像素类型*数据;
};
模板
类ImageTIFF:公共映像。。。
或者这个:

template <typename PixelType, int WIDTH, int HEIGHT>
class Image
{
public:
  Image () { }

  virtual void readImage () = 0;
private:
  PixelType*     data_ [WIDTH][HEIGHT];
};

template <typename PixelType, int WIDTH, int HEIGHT>
class ImageTIFF: public Image <PixelType, WIDTH, HEIGHT> ...
模板
阶级形象
{
公众:
图像(){}
虚拟void readImage()=0;
私人:
PixelType*数据_uz[宽度][高度];
};
模板
类ImageTIFF:公共映像。。。
后者消除了动态内存。。。但如果没有动态内存,就无法实现调整大小功能。我会使用动态记忆

当然,不同的文件格式需要继承,因为它们读取图像的方式不同

--

嗯。这个怎么样?这里的BaseImage类似于Java“接口”,将确保派生类具有所需的函数

class BaseImage 
{
public:
  virtual void allocateImage (int width, int height) = 0;
  virtual void readImage     (int width, int height) = 0;
};

template <typename PixelType>
class Image: public BaseImage ... /* and so on */

BaseImage* myTIFFImage = readTIFFImage (/* whatever goes here */);
classbaseimage
{
公众:
虚空分配图像(整数宽度、整数高度)=0;
虚空读取图像(整数宽度、整数高度)=0;
};
模板
类映像:公共BaseImage…/*等等*/
BaseImage*myTIFFImage=readTIFFImage(/*此处的内容*/);

为什么要在此处使用模板?我宁愿在单个类
Image
中使用一个简单的联合(或)。另外,您能否显示“类型为
float
”的图像示例?你的意思是点将由一种颜色的浮点值来表示吗?@Nelxiost这会非常慢
float
用于单色图像。要仅从矩阵库访问这些字段,您可以在
BaseImage
类中定义尽可能多的字段,或者使用
friend
s将字段仅显示到您需要的位置。为什么要使用矩阵作为图像?虽然两者都是二维组织的数据,但其中一个基本上是线性变换,而另一个。。。事实并非如此。另一种方法是只使用一个原始缓冲区(在读取图像标题之前,我不知道它的类型)。原始缓冲区可以很好地包装在一个类周围,以隐藏void*(或unsanged char*)的丑陋,我必须有某种类型来区分它。然后我想我可以使用type_traits并在以后的阶段创建我的图像模板(如果需要的话)。这是我的另一个想法,但我不喜欢两阶段结构。不是真正通用的,也不是类型安全的。您必须为图像可以保存的每种类型编写代码。当然,动态内存选项更好,但我想主要的问题是,从readTiffImage(const char*)函数返回什么?Tiff可以保存各种类型,唯一的解决方案是创建一个可以返回的基类,这也是我的想法。唯一的区别是我们如何构造基类,我依赖于Eigen对其进行优化。因为您需要readTIFFImage返回一个不指定任何内容的类,包括像素类型,这听起来像是一个指定某些所需函数的基类,特别是readImage,但没有其他内容。我把代码放在上面,看起来像是一个解决方案;看看你怎么想。
class BaseImage
{
public:
    inline BaseImage() {};
    virtual inline ~BaseImage() {};

    virtual inline int Width() const = 0;
    virtual inline int Height() const = 0;
    virtual inline int Depth() const = 0;
    etc...
};

template <typename T>
class Image : public BaseImage, public Eigen::Matrix <T, Eigen::Dynamic, Eigen::Dynamic, Eigen::RowMajor>
class ImageFactory
{
  typename <T>
  static BaseImage* createImage(const T* const src, const int& width, const int& height, const int& depth)
  {
    if (depth == 1)
    {
      return new Image<T>();
    }
    else if (depth == 3)
    {
      return new Image<RGB<T>>();
    }
    etc...
  }
}
class Image2
{
public:
    Image2(const char* const path)
    {
        // where ReadImage and external function that will call ImageFactory
        pBaseImage = ReadImage(path);
    }
    ~Image2();

private:
    BaseImage* pBaseImage;
};
class Image
{
public:
  Image (int bytesPerPixelIn = 1) { data_ = NULL; bytesPerPixel=bytesPerPixelIn;};

  void readImage (int width, int height);
private:
  int       bytesPerPixel_;
  void*     data_;
};

void Image::read (int width, int height, ...)
{
   data_ = new unsigned char [width*height*pixelSize(imageType_)];
   //...
}

//And you can inherit from this if need be to add special functions 
//like interleaving in BMP files
template <typename PixelType>
class Image
{
public:
  Image () { data_ = NULL; };

  virtual void allocateImage (int width, int height)
  {
    data_ = new PixelType [width*height]; 
  }
  virtual void readImage (int width, int height) = 0;
private:
  PixelType*     data_;
};

template <typename PixelType>
class ImageTIFF: public Image <PixelType> ...
template <typename PixelType, int WIDTH, int HEIGHT>
class Image
{
public:
  Image () { }

  virtual void readImage () = 0;
private:
  PixelType*     data_ [WIDTH][HEIGHT];
};

template <typename PixelType, int WIDTH, int HEIGHT>
class ImageTIFF: public Image <PixelType, WIDTH, HEIGHT> ...
class BaseImage 
{
public:
  virtual void allocateImage (int width, int height) = 0;
  virtual void readImage     (int width, int height) = 0;
};

template <typename PixelType>
class Image: public BaseImage ... /* and so on */

BaseImage* myTIFFImage = readTIFFImage (/* whatever goes here */);