2014-02-13 23 views
1

我繼承了一個管理RGB圖像的類的項目,其主要組件是數據類型爲RGBPixel(簡化版本在下面給出)的可變大小數組。它包含許多基本上是界面的方法 - 例如方法Operate,其循環所有像素並調用類別RGBPixel的某種方法。C++引用基類的子類指針屬性

我現在需要使用不同類型的像素處理圖像(我們稱它們爲NewPixelNewImage)。接口類型的方法與RGBImage相同,但不是所有的方法都是像素級的接口(例如在圖像類型之間轉換或從磁盤讀取)。

我顯然不想加倍我的代碼。我覺得我需要一個模板類和一個基類的組合(它們都會繼承,但我沒有線索如何去做這件事)(我一直在絞盡腦汁讀書網頁幾天了)。

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

回答

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 
} 

最後聲明瞭一個名爲圖片

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來實現適用於任何類型圖像的功能。

0

可以使用一組虛擬函數來實現一個抽象像素類,這些虛擬函數將在稍後重載。你的圖像類使用抽象類的指針。您可以輕鬆地交換像素的種類。這會導致代碼量增加很少,並且可以在沒有模板的情況下運行。但當然還有很多其他的方法。一些僞代碼:

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

你可以做RGBImage類tempalte類,並用模板法專業化。 事情是這樣的: 的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 
}