Designing a Volume Class

Discussion in 'C++' started by E G, Jan 22, 2004.

  1. E G

    E G Guest

    Hi!

    I am having problems in designing a class. First, I have a base class
    that allocates a 3D data set and allows some other mathematical
    operations with it, something like this:

    template <typename T> class BasicArray
    {
     
    E G, Jan 22, 2004
    #1
    1. Advertising

  2. In article <bupk61$hmv$>, E G wrote:
    > Hi!
    >
    > I am having problems in designing a class. First, I have a base class
    > that allocates a 3D data set and allows some other mathematical
    > operations with it,


    What mathematical operations do you need to do ? Think about this carefully,
    it's important.

    > template <typename T> class BasicArray
    > {
    > .
    > .
    > .
    > private:
    > T ***Array;


    Why use T*** and not a T* ? What are the advantages of this approach ? Have you
    read the FAQ for this forum ?

    > public:
    > T operator()(unsigned,unsigned,unsigned);


    Should be:

    T& operator()(unsigned,unsigned,unsigned);
    const T& operator() const(unsigned,unsigned,unsigned);

    > This class is not useful alone since I have to read the data from files.
    > The files may contain the information in an 3D array of any C basic type
    > (i.e., char, short, int, float, etcetera). This is the reason of
    > creating a template class. I decided to create a second class "Volume"
    > that handles the I/O and header information and uses BasicArray somehow.


    Here's the problem: you don't know what data type is stored in the file at
    compile time. So you need to handle this dynamically.

    For example:

    class FileReader;

    class DoubleReader : public FileReader
    {
    ....
    };

    ....

    Then the question is, do you always convert the data into a certain type of
    BasicArray (BasicArray<double> or BasicArray<int> or even BasicArray<char>
    depending on what you need to do with the data) or do you leave the data in
    the same format that it's stored on disk ?

    You need to think about how your classes are going to be used. Flexibility
    may seem like a good thing, but gratuitous flexibility is often actually
    just a nuisance. For example, having a "data set of any type" class could
    result in worse performance, and create all sorts of nasty problems down
    the road when you write your math ops.

    > Since the information of the basic type in which the information is
    > represented is stored in the file I cannot inherit Volume from
    > BasicArray.


    Templates and inheritance don't mix that well. If you really did want to
    handle this data polymorphically, you would need to derive BasicArray from
    some other class:

    class BaseArray
    {
    double operator() ( ..... );

    ....
    };

    class BasicArray<T> : public BaseArray
    {


    };

    But then you're going to have one hell of a time doing things like
    performing arithmatic ops on mixed types. For example, suppose you "add"
    a BasicArray<double> to a BasicArray<int>. What type should the result
    be ? You need a double dispatch. Also, if you are to make a variable return
    type, it needs to be a polymorphic BaseArray* pointer, not a value.

    But that's ugly. So now you need to wrap your BaseArray class in a handle.

    You should read a book that discusses handle classes if you haven't yet done
    so. Accelerated C++ would be a good start.

    Have I convinced you that using an "any-datatype" class for general use is
    probably not as good an idea as it may at first seem ?

    > I was thinking of creating the class Volume with a void *
    > pointer.


    No! That's a horrible way to do it.

    You would need

    class ArrayHandle
    {
    BaseArray* impl;
    public:
    ....

    };

    class BaseArray
    {

    ....
    };

    template <typename T> class BasicArray : public BaseArray
    {
    ...
    };

    Then you have to decide how the handle manages your array. Does it reference
    count ? Does it deep copy ? Etc.

    Then you need to think about how you handle mixed type arithmatic. For example,
    does it make sense for the sum of two BasicArray<short> objects to be a
    BasicArray<double> object ? You need to write "double dispatch" code which
    in itself is a terrible mess.

    Now the simplest solution would be to avoid the "any type" nonsense for
    anything more complicated than element access and file reading. This way,
    you only use "any type" for the limited and probablyt necessary task of
    being able to make small changes to large files without changing the data
    type of the whole file.

    For mathematical operations, the appropriate model will usually be to convert
    the on-disk data to an appropriate type. What an "appropriate type" is depends
    on what is being done with the data. char is appropriate for a binary mask.
    int is appropriate for discrete valued data, and for results of computations
    which preserve discreteness (e.g. spatial masking) floating point types are
    appropriate for storing the results of floating point computation on int data.

    The person using the code for a particular application is the right person
    to decide what type of Array is the appropriate one to use.

    Sometimes, there may not be a sensible conversion (for example, double->char).
    In this case, there should be some way to throw an exception or something,
    to tell the programmer using the class that the file open "failed" because
    the file was "unsuitable" for their intended use. Again, this must be handled
    at runtime since you don't know what will be in the file at compile time.

    Cheers,
    --
    Donovan Rebbechi
    http://pegasus.rutgers.edu/~elflord/
     
    Donovan Rebbechi, Jan 22, 2004
    #2
    1. Advertising

  3. E G

    red floyd Guest

    E G wrote:

    > Hi!
    >
    > I am having problems in designing a class. First, I have a base class
    > that allocates a 3D data set and allows some other mathematical
    > operations with it, something like this:
    >
    > template <typename T> class BasicArray
    > {
    > .
    > .
    > .
    > private:
    > T ***Array;
    > .
    > .
    > .
    > public:
    > T operator()(unsigned,unsigned,unsigned);
    > BasicArray<T> operator+(T op);
    > .
    > .
    > .
    > }
    >
    > This class is not useful alone since I have to read the data from files.
    > The files may contain the information in an 3D array of any C basic type
    > (i.e., char, short, int, float, etcetera). This is the reason of
    > creating a template class. I decided to create a second class "Volume"
    > that handles the I/O and header information and uses BasicArray somehow.
    > Since the information of the basic type in which the information is
    > represented is stored in the file I cannot inherit Volume from
    > BasicArray. I was thinking of creating the class Volume with a void *
    > pointer. This pointer would point to the appropiate instance of the
    > BasicArray<type>. However, I am not sure that this is the best approach.
    > Any ideas are greatly appreciated.
    >
    > Regards!
    >


    containment.

    template <typename T>
    class Volume {
    private:
    BasicArray<T> data;
    public:
    BasicArray<T>& get_array();
    const BasicArray<T>& get_array() const;
    // yada yada yada
    };
     
    red floyd, Jan 22, 2004
    #3
  4. In article <4_YPb.4687$>, red floyd wrote:
    > E G wrote:


    > containment.
    >
    > template <typename T>
    > class Volume {
    > private:
    > BasicArray<T> data;
    > public:
    > BasicArray<T>& get_array();
    > const BasicArray<T>& get_array() const;
    > // yada yada yada
    > };


    And how does this help ?

    --
    Donovan Rebbechi
    http://pegasus.rutgers.edu/~elflord/
     
    Donovan Rebbechi, Jan 23, 2004
    #4
  5. E G

    red floyd Guest

    Donovan Rebbechi wrote:
    > In article <4_YPb.4687$>, red floyd wrote:
    >
    >>E G wrote:

    >
    >
    >
    >>containment.
    >>
    >>template <typename T>
    >>class Volume {
    >>private:
    >> BasicArray<T> data;
    >>public:
    >> BasicArray<T>& get_array();
    >> const BasicArray<T>& get_array() const;
    >> // yada yada yada
    >>};

    >
    >
    > And how does this help ?
    >


    He wanted to know how he could use BasicArray<> with Volume, but said
    that he had problems with inheritance. It seems to me that containment
    is a much better solution.

    DISCLAIMER: I may have misread the OP.
     
    red floyd, Jan 23, 2004
    #5
  6. In article <q2_Pb.4715$>, red floyd wrote:
    > Donovan Rebbechi wrote:
    >> In article <4_YPb.4687$>, red floyd wrote:
    >>
    >>>E G wrote:

    >>
    >>
    >>
    >>>containment.
    >>>
    >>>template <typename T>
    >>>class Volume {
    >>>private:
    >>> BasicArray<T> data;
    >>>public:
    >>> BasicArray<T>& get_array();
    >>> const BasicArray<T>& get_array() const;
    >>> // yada yada yada
    >>>};

    >>
    >>
    >> And how does this help ?
    >>

    >
    > He wanted to know how he could use BasicArray<> with Volume, but said
    > that he had problems with inheritance. It seems to me that containment
    > is a much better solution.


    Your example is not a solution because it doesn't actually solve anything.

    The problems he was dealing with were associated with handling data (read via
    input files) whose type is not known at compile time. Your volume class doesn't
    address this (because your class still has a template parameter which must be
    presented at compile time), and in fact it, as you've presented it, your
    code doesn't really solve anything else either.

    Cheers,
    --
    Donovan Rebbechi
    http://pegasus.rutgers.edu/~elflord/
     
    Donovan Rebbechi, Jan 23, 2004
    #6
  7. E G

    Jumbo Guest

    "E G" <> wrote in message
    news:bupk61$hmv$...
    > Hi!
    >
    > I am having problems in designing a class. First, I have a base class
    > that allocates a 3D data set and allows some other mathematical
    > operations with it, something like this:
    >
    > template <typename T> class BasicArray
    > {
    > .
    > .
    > .
    > private:
    > T ***Array;
    > .
    > .
    > .
    > public:
    > T operator()(unsigned,unsigned,unsigned);
    > BasicArray<T> operator+(T op);
    > .
    > .
    > .
    > }
    >
    > This class is not useful alone since I have to read the data from files.
    > The files may contain the information in an 3D array of any C basic type
    > (i.e., char, short, int, float, etcetera). This is the reason of
    > creating a template class. I decided to create a second class "Volume"
    > that handles the I/O and header information and uses BasicArray somehow.
    > Since the information of the basic type in which the information is
    > represented is stored in the file I cannot inherit Volume from
    > BasicArray. I was thinking of creating the class Volume with a void *
    > pointer. This pointer would point to the appropiate instance of the
    > BasicArray<type>. However, I am not sure that this is the best approach.
    > Any ideas are greatly appreciated.
    >
    > Regards!
    >


    What you've got there looks good already. A custom array class specifically
    designed to suit your project.
    Stick some logic in your volume class i.e:
    if(type=="int")
    BasicArray<int> name;
    else if(type=="char")
    BasicArray<char> name;
    etc etc.

    Then your array is initialised with the correct type. What you might want to
    do is keep then seperate. One class for the business logic and one for the
    data. So design the array class so the volume class can communicate with the
    it easily.
    For example say your volume class had a function named getfiledata(8 bytes)
    then you make that function not only get the data but also fill the array
    with the data. Thus you need a good interface so make your array classes
    accessor methods suitable.

    The array class doens't need to be inherintely related to I don't think but
    I don't know enough about your project.
    You could always nest the array class inside the volume class too remember.
     
    Jumbo, Jan 23, 2004
    #7
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. E11
    Replies:
    1
    Views:
    4,944
    Thomas Weidenfeller
    Oct 12, 2005
  2. alexhong2001

    Questions of designing a class

    alexhong2001, Feb 18, 2004, in forum: C++
    Replies:
    3
    Views:
    409
    Cy Edmunds
    Feb 18, 2004
  3. Naren

    help in designing class

    Naren, May 25, 2004, in forum: C++
    Replies:
    1
    Views:
    317
    Victor Bazarov
    May 25, 2004
  4. Naren

    help in designing class

    Naren, May 26, 2004, in forum: C++
    Replies:
    1
    Views:
    333
    Victor Bazarov
    May 26, 2004
  5. James Brown
    Replies:
    12
    Views:
    492
    Greg Comeau
    Sep 24, 2004
Loading...

Share This Page