C ++引用基类的子类指针属性

时间:2014-02-13 14:51:43

标签: c++ templates inheritance

我继承了一个管理RGB图像的类的项目,其主要组件是数据类型RGBPixel的可变大小数组(简化版本如下)。它包含许多基本上是接口的方法 - 例如方法Operate循环遍历所有像素并调用类RGBPixel的某个方法。

我现在需要处理具有不同类型像素的图像(让我们称之为NewPixelNewImage)。接口类型方法与RGBImage相同,但并非所有方法都是像素级别的接口(例如,在图像类型之间进行转换或从磁盘读取)。

我显然不想加倍我的代码。我觉得我需要的东西是模板类和基类的组合(RGBImageNewImage都将继承,但我还没有弄清楚如何去做(I几天来我一直在捣乱我的大脑并阅读网络。)

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;
};

3 个答案:

答案 0 :(得分:2)

您可以从提取所有与像素无关的内容开始,并创建一个抽象基类。

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用于适用于任何类型图像的功能。

答案 1 :(得分:0)

可以使用一组虚函数实现抽象像素类,稍后会重载。您的图像类使用抽象类的指针。你可以轻松交换那种Pixel。这将导致最少量的代码增加,并且无需模板即可工作。但当然还有很多其他方法。一些伪代码:

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;
};

答案 2 :(得分:-1)

您可以将RGB Image类设为模板类,并使用模板方法专门化。 像这样的东西: main.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;
}

image.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_ */

Image.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
}