Using arrays as a template parameters in my rudimentary vector class
Coming from a PHP background, I'm trying to learn C++, since I find it an interesting language. As a practice I want to create a simple Vector class using templates, which is not to hard. However, I run into one problem.
I have created the following template class:
template <typename T>
class Vector
{
public:
Vector(int length开发者_运维问答);
~Vector(void);
int getLength();
T& operator[] (const int index);
private:
T *_items;
int _count;
};
template <typename T>
Vector<T>::Vector(int length)
{
_items = new T[length];
_count = length;
}
template <typename T>
T& Vector<T>::operator[]( const int index )
{
if (index >= getLength() || index < 0)
throw exception("Array out of bounds.");
return _items[index];
}
All functions are implemented, but they're not relevant to my question, so I haven't copied them here.
This class works as expected, with one exception: If I want to create a vector of array's, it doesn't work. e.g.:
Vector<int[2]> someVector(5);
What I obviously want is that the _items property of the vector class will be an int[5][2]. However, since the compiler replaces the 'T' with 'int[2]', the _items property will be int[2][5] (or at least, that's what I understood from debugging, please correct me if I'm wrong). As a result, the [] operator doesn't work correctly anymore, and therefore this whole class is useless for arrays.
Is there a way to solve this problem, so that this class also works for arrays? And if that's not possible, is there a way to prevent this class being initialized with arrays?
Edit: Thanks for all your responses so far. However, I might have been not entirely clear with my question. First of all, I created this class to get used to c++, I know there is a std::vector class, and I also now that it's better to use a vector of vectors. That's not really the problem. I just want to understand templates better, and c++ in general, so I want to know how to deal with this type of problems. I want to be able to create classes which don't make the program crash. If I, or someone else, would use this class right now and tried to use primitive arrays instead of vectors for this class, at some point the program will crash since the array is wrong (Vector(y) becomes int[x][y] instead of int[y][x] internally). So I want a solution which either creates the correct array, or prevents the vector being initialized with arrays at all.
Quite simply, don't ever use the in-built primitive arrays. For anything. They suck, tremendously. Always use a class wrapper such as boost::array
, if you don't have TR1 or C++0x both of which also provide an array
class. A Vector<boost::array<int, 2>>
will trivially compile.
Why not use primitive arrays?
They have hideous implicit conversions to pointers, forget their size at the drop of a hat, aren't first-class citizens (can't assign to them, for example), don't check their bounds, for example. boost::array<int, 2>
is exactly a primitive array without crappy conversions, is fully generic- for example, your Vector template works fine with a boost::array<int, 2>
off the bat, and it can do bounds checking in the at()
function.
I'm not suggesting using a dynamic array instead. boost::array
is not a dynamically sized array. It is a constant size, value type array, that will not convert to a pointer, it has functions for use in the Standard library like begin
, end
, size
, and it can be treated like any other type- unlike arrays, which have a dozen special rules- as you've found out.
I see a few things wrong with this.
- If you are making a generic vector class, why deal with a vector of arrays rather than a vector of vectors?
Rather than defining a vector of type int[2], try making a vector of vectors of size 2 with something like this:
Vector<Vector<int>> vector(5);
for (int i = 0; i < 5; i++)
{
vector[i] = Vector<int>(2);
}
- Rather than using a constant sized array, try using a pointer.
Rather than using a pointer to arrays of size 2, use a pointer to a pointer, and allocate two spaces for that pointer. Pointers are a lot easier to deal with in C++ because you can simply pass the address of the pointer rather than having to copy the entire array. It's generally very bad form to pass arrays.
- Add a default parameter to your constructor
Rather than declaring the constructor with Vector(int length);
, try using Vector(int length = 0);
so that if the user doesn't specify a length it will default to a size of zero.
Finally, are you aware that there is in fact an std::vector, or are you aware of this and simply trying to replicate it? Templates are known to be one of the hardest subjects of C++, good luck!
The condition must say index >= getLength()
, because getLength() is not an allowed index value too (the first element's index is 0
, the last's is getLength()-1
)
精彩评论