Copy vector’s functions into your own class

Discussion in 'C++' started by Immortal Nephi, Sep 15, 2010.

  1. I want to design three different classes. Three classes’ names are
    Array_1D, Array_2D and Array_3D. Array_1D has all elements in
    column. Array_2D enchances Array_1D by adding row like matrix. Also,
    Array_3D enchanges Array_2D by adding plane like cube.

    I wonder if I don’t like to define vector like below.

    vector< int > Array_1D;
    vector< vector< int > > Array_2D;
    vector< vector< vector< int > > > Array_3D;

    It is so confusing to me. I prefer to use only one vector. I can
    add data members to that class like column, row, plane.

    template< typename element_type >
    class Array_1D {
    public:
    typedef typename vector< element_type >::size_type size_type;

    Array_1D() {}
    Array_1D( size_type column ) : m_column( column ) {
    m_data.resize( column );
    }

    private:
    vector< element_type > m_data;
    size_type m_column;
    };

    template< typename element_type >
    class Array_2D : public Array_1D< element_type > {
    public:
    typedef typename vector< element_type >::size_type size_type;

    Array_2D() {}
    Array_2D(
    size_type column,
    size_type row
    ) : m_column( column ), m_row( row ) {
    m_data.resize( row * column );
    }

    private:
    size_type m_row;
    };

    template< typename element_type >
    class Array_3D : public Array_2D< element_type > {
    public:
    typedef typename vector< element_type >::size_type size_type;

    Array_3D() {}
    Array_3D(
    size_type column,
    size_type row
    size_type plane
    ) : m_column( column ), m_row( row ), m_plane( plane ) {
    m_data.resize( plane * row * column );
    }

    private:
    size_type m_plane;
    };

    Do you see that three classes are clean readable code? If I want to
    add some vector’s functions into my own class, I would write my own
    function like begin(), end(), clear, empty, resize. They behave
    differently because they are not the same as vector’s functions.
    Also, I add Insert_Column, Insert_Row, Insert_Plane, Remove_Column,
    Remove_Row, Remove_Plane functions.
    I don’t use inheritance to override vector’s function. I use
    composition and write my own functions.
    My question is – is it ok if I write my own functions which they
    behave like vector’s functionality? Also, I can write my own copy
    constructor and assignment operator.
    Immortal Nephi, Sep 15, 2010
    #1
    1. Advertising

  2. Immortal Nephi

    James Kanze Guest

    On Sep 15, 1:49 am, Immortal Nephi <> wrote:
    > I want to design three different classes. Three classes’
    > names are Array_1D, Array_2D and Array_3D. Array_1D has all
    > elements in column. Array_2D enchances Array_1D by adding row
    > like matrix. Also, Array_3D enchanges Array_2D by adding
    > plane like cube.


    > I wonder if I don’t like to define vector like below.


    > vector< int > Array_1D;
    > vector< vector< int > > Array_2D;
    > vector< vector< vector< int > > > Array_3D;


    > It is so confusing to me. I prefer to use only one vector.


    That's usually the preferred solution, but which is better may
    depend on the C++ implementation.

    At any rate, you doubtlessly want to hide this implementation
    detail; the typedef's (if used) should be private, in the class.

    > I can add data members to that class like column, row, plane.


    To which class? I'm not sure what you mean here.

    > template< typename element_type >
    > class Array_1D {
    > public:
    > typedef typename vector< element_type >::size_type size_type;


    Just use size_t and be done with it.

    > Array_1D() {}
    > Array_1D( size_type column ) : m_column( column ) {
    > m_data.resize( column );
    > }


    > private:
    > vector< element_type > m_data;
    > size_type m_column;


    You don't actually need this one. It's m_data.size().

    > };


    > template< typename element_type >
    > class Array_2D : public Array_1D< element_type > {


    This is a serious design error. An Array_2D is not an Array_1D.
    Inheritance is a poor choice here; you have two unrelated types.
    (You likely do want to provide functions in Array_2D which
    returns a given row or column, as an Array_1D.)


    [...]
    > template< typename element_type >
    > class Array_3D : public Array_2D< element_type > {


    As above. This is very poor design.

    [...]
    > Do you see that three classes are clean readable code?


    No. The inheritance is all wrong.

    > If I want to add some vector’s functions into my own class,
    > I would write my own function like begin(), end(), clear,
    > empty, resize. They behave differently because they are not
    > the same as vector’s functions.


    > Also, I add Insert_Column, Insert_Row, Insert_Plane,
    > Remove_Column, Remove_Row, Remove_Plane functions.
    > I don’t use inheritance to override vector’s function. I use
    > composition and write my own functions.


    Yes. Since you don't (or shouldn't) derive from vector, you
    have to provide your own.

    > My question is – is it ok if I write my own functions which they
    > behave like vector’s functionality?


    Why not?

    > Also, I can write my own copy constructor and assignment
    > operator.


    You can, but you probably don't have to; the compiler generated
    defaults will do the right thing (as long as the only members
    are std::vector and the size types). You might want to,
    however, to ensure that they aren't inline.

    --
    James Kanze
    James Kanze, Sep 15, 2010
    #2
    1. Advertising

  3. Immortal Nephi

    cpp4ever Guest

    On 09/15/2010 10:18 AM, James Kanze wrote:
    > On Sep 15, 1:49 am, Immortal Nephi <> wrote:
    >> I want to design three different classes. Three classes’
    >> names are Array_1D, Array_2D and Array_3D. Array_1D has all
    >> elements in column. Array_2D enchances Array_1D by adding row
    >> like matrix. Also, Array_3D enchanges Array_2D by adding
    >> plane like cube.

    >
    >> I wonder if I don’t like to define vector like below.

    >
    >> vector< int > Array_1D;
    >> vector< vector< int > > Array_2D;
    >> vector< vector< vector< int > > > Array_3D;

    >
    >> It is so confusing to me. I prefer to use only one vector.

    >
    > That's usually the preferred solution, but which is better may
    > depend on the C++ implementation.
    >
    > At any rate, you doubtlessly want to hide this implementation
    > detail; the typedef's (if used) should be private, in the class.
    >
    >> I can add data members to that class like column, row, plane.

    >
    > To which class? I'm not sure what you mean here.
    >
    >> template< typename element_type >
    >> class Array_1D {
    >> public:
    >> typedef typename vector< element_type >::size_type size_type;

    >
    > Just use size_t and be done with it.
    >
    >> Array_1D() {}
    >> Array_1D( size_type column ) : m_column( column ) {
    >> m_data.resize( column );
    >> }

    >
    >> private:
    >> vector< element_type > m_data;
    >> size_type m_column;

    >
    > You don't actually need this one. It's m_data.size().
    >
    >> };

    >
    >> template< typename element_type >
    >> class Array_2D : public Array_1D< element_type > {

    >
    > This is a serious design error. An Array_2D is not an Array_1D.
    > Inheritance is a poor choice here; you have two unrelated types.
    > (You likely do want to provide functions in Array_2D which
    > returns a given row or column, as an Array_1D.)
    >
    >
    > [...]
    >> template< typename element_type >
    >> class Array_3D : public Array_2D< element_type > {

    >
    > As above. This is very poor design.
    >
    > [...]
    >> Do you see that three classes are clean readable code?

    >
    > No. The inheritance is all wrong.
    >
    >> If I want to add some vector’s functions into my own class,
    >> I would write my own function like begin(), end(), clear,
    >> empty, resize. They behave differently because they are not
    >> the same as vector’s functions.

    >
    >> Also, I add Insert_Column, Insert_Row, Insert_Plane,
    >> Remove_Column, Remove_Row, Remove_Plane functions.
    >> I don’t use inheritance to override vector’s function. I use
    >> composition and write my own functions.

    >
    > Yes. Since you don't (or shouldn't) derive from vector, you
    > have to provide your own.
    >
    >> My question is – is it ok if I write my own functions which they
    >> behave like vector’s functionality?

    >
    > Why not?
    >
    >> Also, I can write my own copy constructor and assignment
    >> operator.

    >
    > You can, but you probably don't have to; the compiler generated
    > defaults will do the right thing (as long as the only members
    > are std::vector and the size types). You might want to,
    > however, to ensure that they aren't inline.
    >
    > --
    > James Kanze
    >


    Personally I prefer to do the following

    typedef std::vector<int> Array_1D;
    typedef std::vector<Array_1D> Array_2D;
    typedef std::vector<Array_2D> Array_3D;

    or even

    template <typename T>
    class MyArray
    {
    public:
    typedef std::vector<T> _1D;
    typedef std::vector<_1D> _2D;
    typedef std::vector<_2D> _3D;

    // can add member functionality as required
    };


    But if you want/need your own member functions or member function names
    then creating your own class implementations is required. This will mean
    creating more code, which adds extra potential for errors and hence more
    testing. But as I believe in the KISS, (keep it simple stupid),
    principle, I can only recommend you do what you find simplest.

    HTH
    cpp4ever, Sep 15, 2010
    #3
  4. Immortal Nephi

    James Kanze Guest

    On Sep 15, 11:31 am, cpp4ever <>
    wrote:
    > On 09/15/2010 10:18 AM, James Kanze wrote:


    [...]
    > Personally I prefer to do the following


    > typedef std::vector<int> Array_1D;
    > typedef std::vector<Array_1D> Array_2D;
    > typedef std::vector<Array_2D> Array_3D;


    Except that it doesn't work. The resulting interface allows the
    client code to change the size of individual rows, for example,
    thus breaking an essential invariant, and doesn't provide
    a simple interface for the client to determine the dimensions.

    [...]
    > But as I believe in the KISS, (keep it simple stupid),
    > principle, I can only recommend you do what you find simplest.


    The simplest, but which works. (Make it as simple as possible,
    but no simpler.)

    --
    James Kanze
    James Kanze, Sep 15, 2010
    #4
    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. Replies:
    8
    Views:
    1,913
    Csaba
    Feb 18, 2006
  2. Jeffrey Barish

    Problem using copy.copy with my own class

    Jeffrey Barish, Apr 22, 2008, in forum: Python
    Replies:
    7
    Views:
    363
    Jeffrey Barish
    Apr 24, 2008
  3. c676228
    Replies:
    3
    Views:
    171
    c676228
    Sep 14, 2006
  4. David Filmer
    Replies:
    17
    Views:
    258
    J. Romano
    Aug 18, 2004
  5. ARGENTINA
    Replies:
    4
    Views:
    167
    Joe Smith
    Dec 30, 2004
Loading...

Share This Page