我继承了一个管理RGB图像的项目,其主要组件是数据类型RGBPixel
的可变大小数组(简化版本如下)。它包含许多基本上是接口的方法 - 例如,循环所有像素并调用类RGBPixel
的某个方法的方法Operate
。
我现在需要处理具有不同类型像素的图像(我们称它们为 NewPixel
和 NewImage
)。接口类型方法与RGBImage
相同,但并非所有方法都是像素级的接口(例如在图像类型之间转换或从磁盘读取)。
我显然不想将我的代码加倍。我觉得我需要模板类和基类的组合(RGBImage
和NewImage
都将继承,但我不知道如何做到这一点(我已经绞尽脑汁并阅读网络几天了)。
class RGBImage {
public:
RGBImage::RGBImage(int w, int h) {
_width = w;
_height = h;
_pixels = new RGBPixel[w*h];
}
RGBImage::~RGBImage() { _pixels = NULL; }
void RGBImage::Operate(int val) {
for (int i = 0; i < _width*_height; i++)
_pixels[i].Operate(val);
}
void RGBImage::RGBSpecific() {
bla bla bla
}
private:
int _width, _height;
RGBPixel* _pixels;
};
您可以从提取所有与像素无关的内容开始,并创建一个抽象基类。
class AbstractImage {
public:
AbstractImage(int w, int h) : _width(w), _height(h) { }
virtual ~AbstractImage() = 0;
virtual void Operate(int val) = 0;
protected:
int _width, _height;
}
然后创建一个基模板类,实现适用于各种像素的所有函数。
template<typename Pixel>
class TemplateImage : public AbstractImage {
public:
TemplateImage (int w, int h) : AbstractImage(w, h), _pixels(w*h) { }
~TemplateImage () {};
void Operate(int val) {
for (int i = 0; i < _width*_height; i++)
_pixels[i].Operate(val);
}
protected:
std::vector<Pixel> _pixels; //Changed raw pointer to vector to avoid memory management
}
最后,声明一个名为 Image 的模板类
template<typename Pixel>
class Image;
让它像这样。稍后,您将针对您的像素类型对其进行专门化。
template<>
class Image<RGBPixel> : TemplateImage<RGBPixel> {
public:
Image(int w, int h) : TemplateImage(w, h) { }
void RGBSpecific() {
bla bla bla
}
}
template<>
class Image<NewPixel> : TemplateImage<NewPixel > {
public:
Image(int w, int h) : TemplateImage(w, h) { }
void NewPixelSpecific() {
bla bla bla
}
}
您将只能实例化Image<RGBPixel>
和Image<NewPixel>
。他们有其特定的操作。您可以将AbstractImage
用于适用于任何类型的图像的功能。
可以使用一组虚函数实现抽象像素类,稍后会重载这些函数。图像类使用抽象类的指针。您可以轻松交换像素的种类。这将导致最少的代码量增加,并且无需模板即可工作。但当然还有很多其他方法。一些伪代码:
AbstractPixel {
public:
virtual void Operate(float);
virtual void foo();
// ..
}
class RGBPixel : public AbstractPixel {
//void Operate(float); // Maybe, maybe not
void RGB_function();
}
class CMYPixel : public AbstractPixel {
//void Operate(float); // Maybe, maybe not
void CMY_function();
}
class RGBImage {
public:
RGBImage::RGBImage(int w, int h) {
_width = w;
_height = h;
_pixels = new RGBPixel[w*h];
}
RGBImage::~RGBImage() { _pixels = NULL; }
void RGBImage::Operate(int val) {
for (int i = 0; i < _width*_height; i++)
_pixels[i]->Operate(val);
}
void RGBImage::RGBSpecific() {
((RGBPixel*)_pixels[i])->RGB_function();
}
private:
int _width, _height;
AbstractPixel* _pixels;
};
您可以将 RGBImage 类设置为临时类,并使用模板方法专用化。像这样:主.cpp
#include <iostream>
#include "Image.h"
class RGBPixel
{
public:
void Operate(int val) {};
};
class NewPixel
{
public:
void Operate(int val) {};
};
int main()
{
CImage<RGBPixel> image_RGBPixel = new CImage<RGBPixel>(100,100);
CImage<NewPixel> image_NewPixel = new CImage<NewPixel>(100,100);
image_NewPixel.PixelSpecific(); //calls void CImage<RGBPixel>::PixelSpecific()
image_NewPixel.PixelSpecific(); //calls void CImage<NewPixel>::PixelSpecific()
return 0;
}
图片.h
#ifndef RGBIMAGE_H_
#define RGBIMAGE_H_
template <class T>
class CImage
{
public:
CImage(int w, int h);
~CImage();
void Operate(int val);
void PixelSpecific();
private:
int _width, _height;
T* _pixels;
};
#endif /* RGBIMAGE_H_ */
图片.cpp
#include "RGBImage.h"
class RGBPixel;
class NewPixel;
template <class T>
CImage<T>::CImage(int w, int h)
{
_width = w;
_height = h;
_pixels = new T[w*h];
}
template <class T>
CImage<T>::~CImage()
{
if(_pixels)
{
delete[] _pixels;
_pixels = 0;
}
}
template <class T>
void CImage<T>::Operate(int val)
{
for (int i = 0; i < _width*_height; i++)
_pixels[i].Operate(val);
}
template <class T>
void CImage<T>::PixelSpecific()
{
//general implementation
}
void CImage<RGBPixel>::PixelSpecific()
{
//RGBPixel specific implementation of PixelSpecific
}
void CImage<NewPixel>::PixelSpecific()
{
//NewPixel specific implementation of PixelSpecific
}