Copy vector’s functions into your own class

I

Immortal Nephi

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.
 
J

James Kanze

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.
 
C

cpp4ever

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.

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
 
J

James Kanze

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.)
 

Ask a Question

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

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,982
Messages
2,570,186
Members
46,744
Latest member
CortneyMcK

Latest Threads

Top