处理模板创建的更好方法
A better way to handle template creation?
试图找到一个更好的设计!
考虑我们有一个模板图像类,它继承自模板矩阵库(在本例中为Eigen,但它可以是任何东西)
template <typename T>
class Image : public Eigen::Matrix <T, Eigen::Dynamic, Eigen::Dynamic, Eigen::RowMajor>
现在想想我们想要编写一个函数来处理从文件中读取图像的情况。当然,图像可以是不同类型的,即未经处理的char、uint16_t、float,甚至具有不同的通道,如灰度、RGB甚至RGBA。
所以我们当然可以使用模板类来轻松处理这个问题。如
Image<RGB<unisgned char>> or Image<RGBA<float>>
当人们知道图像的类型时,这很简单,比如单色8位
Image<unisgned char> image = ReadImage(const char* const filename);
甚至可能是
Image<unisgned char> image;
bool b = ReadImage(const char* const filename, Image<unisgned char>& image)
然而,当读取图像文件时,在读取图像之前,我们永远不知道类型。例如,Tiff和png都支持8bit和16bit,Tiff甚至支持float。在这种情况下,不可能使用上述任何功能。然而,我们可以使用temmplateFactory类来解决这个问题。
为此,我们首先需要引入BaseImage类
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>
然后我们可以在工厂类中传递无符号的char*、float*等,并让它处理创建
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;
};
在任何一种情况下,我的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> ...
或者这个:
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> ...
后者消除了动态内存。。。但是如果没有动态内存,就不可能有调整大小的功能。我会使用动态记忆。
当然,您需要继承不同的文件格式,因为它们读取图像的方式不同。
--
好的。这个怎么样?这里的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 */);
- 初始化具有非默认构造函数的std::数组项的更好方法
- Protobuf中重复字段的问题.使用重复字段进行序列化/反序列化的更好方法是什么?
- 编写按初始值循环的循环的更好方法是什么
- 用 c++ 为游戏制作"bullet"的更好方法?
- 在CMakeLists中包含目录的更好方法.txt
- 将QDomDocument数据用作文本的更好方法
- C++ - 创建具有相同字符的特定大小的以 null 结尾的 c 样式字符串的更好方法
- 在 sqlite3 中批量插入的更好方法C++
- 设计许多单例代码结构的更好方法
- 使用继承的类模板避免公共成员不可见和源代码膨胀/重复的更好方法
- 在初始化列表中初始化数组的更好方法
- 将对象从一个 std::d eque 移动到另一个的更好方法
- 请告诉我在巴泽尔拥有多平台工作空间的更好方法
- 构造具有大量数据的对象的更好方法(C++)
- 从2D矢量中找出最小尺寸的向量元素的更好方法
- 在C++中创建不可变对象的更好方法
- 在构造函数中组织初始值设定项列表的更好方法
- std::copy with return values - 防止"expression: string iterators incompatible"的更好方法?
- 删除数组成员的更好方法是什么?
- 在C 中操作数据的更好方法是什么