amc
amc

Reputation: 349

C++ inheritance/template question

I have two classes, point and pixel:

class point {
    public:
        point(int x, int y) : x(x), y(y) { };
    private:
        int x, y;
}

template <class T>
class pixel : public point {
    public:
        pixel(int x, int y, T val) : point(x, y), val(val) { };
    private:
        T val;
}

Now here's my problem. I want to make a container class (let's call it coll) that has a private vector of points or pixels. If an instance of coll contains pixels, I want it to have a method toArray(), which converts its vector of pixels to an array of T representing the contents of the vector.

I was going to do this with inheritance: ie, I could make a base class coll that contains a vector of points and a derived class that contains the extra method, but then I seem to run into problems since pixel is a class template.

Does anyone have suggestions? Could I do this somehow by making coll a class template?

Upvotes: 5

Views: 514

Answers (3)

diverscuba23
diverscuba23

Reputation: 2185

Question: Do you mean for the private vector to contain both Points and Pixels at the same time, or just one or the other?

Question: If just one or the other, are you meaning to mix Pixels with different template parameters in the same private vector?

Assuming that it is just Point or Pixel in the private vector, and that the Pixels in the private vector all have the same template parameter, you could do something like this:

template < class T > class CollectionBase
{
   //common interface here
   protected:
   std::vector<T> coll_vec;
};

class PointCollection : public CollectionBase<Point>
{
   public:
   ...
};

template< class T> PixelCollection : public CollectionBase<Pixel<T> >
{
   public:
    Pixel<T>* toArray();

    ...

};

Upvotes: 3

Georg Fritzsche
Georg Fritzsche

Reputation: 98984

If collection treats points and pixels mostly the same and only contains one or the other, it makes sense to make it a template class.
Regarding to_array however, it might be simpler to make it a free function instead:

template<class T> struct collection {
    std::vector<point<T> > data_;
    // ...
};

template<class T>
void to_array(const collection<point<T> >& in, point<T>* out) {
    // ...
}

Note that you would have to provide a public interface for read-access to the data however or at least selectively grant to_array() access.

Upvotes: 1

user269597
user269597

Reputation:

If you want to check whether a point object is also a type of pixel<T>, then you can simply see if dynamic_cast returns NULL. In order to do this, point will need to be polymorphic, so add a virtual destructor to it.

Here's an example:

point x(0, 0);
pixel<int> y(0, 0, 0);
point *pX = &x;
point *pY = &y;
if(dynamic_cast<pixel<int> *> (pX) != NULL) {
    std::cout << "x is a pixel<int>.";
}
if(dynamic_cast<pixel<int> *> (pY) != NULL) {
    std::cout << "y is a pixel<int>.";
}

The output is as follows:

y is a pixel<int>.

You could use this code in your coll class to check whether each element of a vector<point *> is a point or a pixel. But in order to do so, you would need to know which specialisation of pixel is being stored (i.e. is it a pixel<int> or a pixel<float>?)

It may be simpler to make coll a class template instead.

Upvotes: 1

Related Questions