gpt4 book ai didi

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

转载 作者:塔克拉玛干 更新时间:2023-11-02 23:45:39 26 4
gpt4 key购买 nike

试图为此找出更好的设计!

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

template <typename T>
class Image : public Eigen::Matrix <T, Eigen::Dynamic, Eigen::Dynamic, Eigen::RowMajor>

现在想想我们要编写一个函数来处理从文件中读取图像的情况。当然图像可以是不同的类型,即 unisnged char、uint16_t、float,甚至可以有不同的 channel ,如灰度、RGB 甚至 RGBA。

所以我们当然可以使用模板类来轻松处理这个问题。如

Image<RGB<unisgned char>> or Image<RGBA<float>>

当知道图像的类型时就很简单了,比如单色 8bit

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 都支持 8 位和 16 位,而 tiff 甚至支持 float 。在这种情况下,不可能使用上述任何功能。但是,我们可以使用模板工厂类来解决这个问题。

为此我们首先需要引入一个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>

然后我们可以在工厂类中传递 unsigned 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“接口(interface)”,将确保派生类具有它们需要的功能。

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 */);

关于c++ - 处理模板创建的更好方法?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25990030/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com