0

I have a (partally implemented) class hierarchy where

template<typename T> {
    class data { 
        data ( string s ) {}; // loads from file
        ...
    }
    class image: public data <T> { 
        image ( string s ) {}; // loads from file
        ...
    }
    class jpgimage : public image<T> {
        jpgimage ( string s ) {}; // loads from file 
        ...
    }
    // other image types
}

Now in the rest of my code I would like to be able to abstract from whether something is a jpeg image or even an image, so I would like to work with data. But at the same time I would like to pass commands specific to jpeg images to those functions.

So if I call data<int> img("lena.jpg"); which turns out to be an image, even a jpeg image, I would like the data constructor to call the image constructor, which in turn calls the jpgimage constructor.

There is no way I can get it to work, and people warn about slicing, virtual constructors, etc. But is this such a strange way to set it up?

Patrick
  • 1,717
  • 7
  • 21
  • 28
alle_meije
  • 2,424
  • 1
  • 19
  • 40
  • this is not C++. You must make each class a `template` – Walter Oct 15 '13 at 21:22
  • 1
    What you want is a `Data Factory`. You pass the factory the name of the file. It works out which type of object to create and returns it. – Martin York Oct 15 '13 at 23:34
  • Chapter 8 of [Modern C++ Design](http://www.amazon.com/Modern-Design-Generic-Programming-Patterns/dp/0201704315) by Alexandrescu discusses the Factory pattern. – TemplateRex Oct 18 '13 at 21:30

3 Answers3

1

Inheritance is to be used for is a relationships. So, an image<T> is a data<T>, but not the other way around! It makes no sense to call a method specific to image<T> for a data<T> object, which after all may not be an image<T>. The fact that you want to do that shows that your code design is flawed. Rethink your code design.

Walter
  • 44,150
  • 20
  • 113
  • 196
  • Point taken. I wanted to code it so that for example, I can load `image im1("lena.jpg");` and `image im2("lena.png");` (with a different constructor, for PNG images) and then use them as objects of the same class. So a jpeg image *is* an image and a png image *is* an image, but I want to only use the fact that they're both images after loading them. In this case, coding the different I/O options as methods rather than different classes is then better, including the filetype-specific parts such as headers etc. -- that was what I thought different classes would be best for. – alle_meije Oct 15 '13 at 22:14
  • I know exactly where you were coming from. But best to think about this for yourself! – Walter Oct 15 '13 at 22:27
1

To implement that you would need data to be owner of implementation, not base class:

template<typename T> 
class base_data {
    base_data ( string s ) {} // loads from file
    // ...  
};

template<typename T> 
class image: public base_data <T> { 
    image ( string s ) {} // loads from file
    ... 
};

template<typename T> 
class jpgimage : public image<T> {
    jpgimage ( string s ) {} // loads from file 
    // ...
    // other image types
};

template<typename T> 
class data {
    data ( string s ) {
        if(is_jpeg( s )) impl = new jpeg_data<T>( s );
        // ...
    } // loads from file
    // ...
    private:
        base_data<T> *impl;
};

Now in constructor you can create proper type of implementation and so on.

Patrick
  • 1,717
  • 7
  • 21
  • 28
Slava
  • 43,454
  • 1
  • 47
  • 90
0

I'd say it's a bad design. You don't need to work with generic data classes just to guess whether you work with images, if you know for sure that you do. Use the image or jpgimage class where you need it, and make everything else work with a generic data class.

Avidan Borisov
  • 3,235
  • 4
  • 24
  • 27
  • I made the code more concise, because ideally I want something that works with different forms of numerical data, could be images, surfaces, signals, etc. I think the `image` and `jpgimage` class should really be methods of data only. – alle_meije Oct 15 '13 at 22:20