Click here to Skip to main content
Click here to Skip to main content

A Java Style Vector Class in C++

, 17 Dec 2002
Rate this:
Please Sign up or sign in to vote.
An introduction to a vector collection class for typed pointers.

Introduction

This article will introduce you to a C++ class that was created to store and manage a collection of typed pointers. Its purpose is to easily manage a collection of object pointers with a familiar Java-like interface. This article is the first in several that I plan to post, describing and sharing some of the useful implementations that I have used extensively over the years.

Background

Before MFC, storing and managing a collection of object pointers was widely used in the software that I was developing. The software was not written for MFC and so, the MFC collection objects were not available. I could use STL, but design criteria prevented me from using such templates. A class designed to provide this support was constructed and used in application development. As time went by, its design was added and pruned to keep the best functionality in the class. Once project work came along in Java, I was quite taken by the clarity of the interface and its approach to class and method naming. If there is one thing I don't like, its cryptic, obfuscating code. What's the point of sharing code if you get a headache just sorting it out? Its a bit like reading a dry physics book.

I decided to carry this approach over to the collection of support classes I now use and this is the result of one such effort.

Why not STL?

For clarity, we had to develop software modules (source) that could be used by one client (customer) in Java, and another client (customer) in MFC. This meant parallel development and no STL, so we needed a set of core classes in C++ that were as similar as possible to Java, thus making the transition easier and saving money.

The ZVector class

The vector class, as its name suggests is a vector list manager that mimics much of the Java look and feel. There is a simple 'Z' prefix to the class to prevent conflict in the namespace. Functionally, it is capable of handling the same problems that are commonly done by the CTypePtrArray. The primary difference is, it is much easier to read and use with the Java-like interface. Another difference is, it is written to be pure C++, with no dependence on the operating system or the Windows API (stdafx.h optional). Hence, it should be portable to any OS. (I say 'should', because I have not actually used it in another OS). The class is not very big, and that's just the point. Keep it simple.

The solution

My approach to the solution is straightforward. First a class was created to manage the manipulation of the type neutral pointers. These pointers can be pointers to any type that the user desires. Its key purpose is to provide memory allocation and memory access functions for the vector list. It also optimizes these processes to reduce unneeded reallocations and thus improve speed. In addition, it takes a very careful approach to tracking the object, much like its Java counterpart.

Here is the vector manager class:

class ZS_EXPORT ZVectorBuffer 
   {
   //----------------------------------
   // Instance variables
   //----------------------------------
   private:
      static   Ptr            pNull;

   //----------------------------------
   // Instance variables
   //----------------------------------
   protected:
               Ptr         *  pPtr;
               int            iDataCount;
               int            iDataCapacity;
               int            iDataIncrement;

   //----------------------------------
   // Constructor/Destructor
   //----------------------------------
   private:
                              ZVectorBuffer(const ZVectorBuffer &array);
   public:
                              ZVectorBuffer(int initial=0,int increment=8);
                             ~ZVectorBuffer();

   //----------------------------------
   // Instance methods
   //----------------------------------
   private:
               void           operator = (const ZVectorBuffer &that);
               bool           move(int from_index, int to_index);
   public:

               void           ensureCapacity(int elements);
               void           setSize(int size);

               int            size()                                 const;
               int            capacity()                             const;
               int            indexOf(CPtr ptr,int start=0)          const;
               bool           contains(CPtr ptr)                     const;
               bool           isEmpty()                              const;
               void           copy(const ZVectorBuffer &that);
               void           append(const ZVectorBuffer &that);

               Ptr         &  getElement(int i)                      const;
               void           addElement(Ptr ptr);
               bool           mergeElement(Ptr ptr);
               void           removeElement(Ptr ptr);
               void           removeElementAt(int i);
               void           removeAll();

               void           sort(int (*compare)(CPtr, CPtr));

               bool           raise (CPtr ptr);
               bool           lower (CPtr ptr);
               bool           toHead(CPtr ptr);
               bool           toTail(CPtr ptr);
   };

You will notice in examining the class that there is a short form of char * called Ptr and const char * called CPtr. This is a typedef that is simply used to make the code more readable. The second class is that class that you will actually use when creating one of these objects. It is the template class called ZVector. Its purpose is to create instances of typed lists and provide the proper typecasting when the object is used, so you don't have to. Here it is:

template<class T> class ZVector : public ZVectorBuffer
   {
   public:
      T* &      elementAt(int i)       const { return (T*&)getElement(i);  }
      T* &      operator [] (int i)    const { return (T*&)getElement(i);  }
      T* &      firstElement()         const { return (T*&)getElement(0);  }
      T* &      lastElement() const { return (T*&)getElement(iDataCount-1);}

   public:
      void      operator << (T *  t)         { addElement(t);    }
      void      operator >> (T *  t)         { removeElement(t); }
      void      setElementAt(T * t,int i)    { pPtr[i] = t;     }
   };

This class is constructed purely inline, providing the primary operator that would be used in the application. If you look closely, you will also notice a dummy static pointer installed in the vector manager class. Since the access operator requires a pointer reference, the dummy pointer is used to satisfy this condition if the index is out of bounds. Assigning this is harmless and I would rather do this than involve exceptions at such a low level.

Using the ZVector class

Finally, I will end up with a couple of code snippets to show how the class would be used in a typical application.

In the declaration, the representation is quite simple. Instantiate a template object in the class definition or body of code and then use it. Rarely would one create the object dynamically, and I have never found a need for it.

   //----------------------------------
   // Instance variables
   //----------------------------------
   private:
      ZVector <MyClass>     vChildren;

Or...

void some_method()
   {
   ZVector<MyClass> vector;       // Create a typed vector

   vector.addElement(new MyClass());    // Add one object
   vector.addElement(new MyClass());    // Add another object (unique)

   MyClass *object = vector[1];         // Access second object

   vector.removeElement(object);        // Remove the second object
   delete object;                       // Delete the second object

   object = vector[0];                  // Access first object
   delete object;                       // Delete the first object
   }

Conclusions

Simple but effective. It is not fool-proof thought. If you tried really hard you could break it, but in everyday use it is bulletproof. In almost all cases I use the template operator exclusively and only a few methods from the manager class. I have approximately 7-10 programmers and engineers using it on a daily basis and it has not caused any problems. I believe its performance to be very good, although I have not put it up against other classes in benchmarks. I welcome any information on this.

This is a core class. In future I will show some derived implementations using this as the base class. They also will contain a Java-like interface to make them look and feel very familiar.

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here

Share

About the Author

Craig Muller
Web Developer
Canada Canada
Craig Muller has a post graduate degree in electrical engineering and specializes in software development for the power systems industry.
 
His first programming experience was in 1978 writing APL on an IBM-360 linked by a teletype machine. Early programming work was done in 1982-1983 when he developed Fortran programs to solve transfer functions for dynamic systems.
 
Software development was taken up as a career in 1987 while completing a master degree in engineering. Since then he has had 15 years diverse experience in C, C++, Java, MFC, and GUI development applied to power system simulator technology and advanced data visualization tools.
 
Founder of a company called ZSystems in 1998 that specializes in visualization and GUI object development. ZSystems continues to develop software for both Java and C++ applications. Recently, he returned to the Manitoba HVDC Research Centre to manage development of the electromagnetic transients simulator 'PSCAD'.

Comments and Discussions

 
Generalmove function PinmemberSymbios20-Mar-07 10:16 
QuestionCode Review - possible Bug Found - memory leak PinmemberSymbios19-Mar-07 13:04 
AnswerRe: Code Review - possible Bug Found - memory leak PinmemberCraig Muller20-Mar-07 5:51 
GeneralRe: Code Review - possible Bug Found - memory leak PinmemberSymbios20-Mar-07 6:23 
GeneralRe: Code Review - possible Bug Found - memory leak PinmemberCraig Muller20-Mar-07 6:58 
GeneralThank you PinmemberDudeZ19-Aug-06 6:07 
GeneralSort Pinmemberdynz4-Nov-04 2:39 
GeneralRe: Sort PinmemberCraig Muller4-Nov-04 6:22 
GeneralRe: Sort PinsussAnonymous4-Nov-04 20:57 
GeneralGreat for eVC++ 3.0 compiler PinmemberStober2-Nov-04 10:05 
GeneralRe: Great for eVC++ 3.0 compiler PinmemberCraig Muller4-Nov-04 6:08 
GeneralRe: Great for eVC++ 3.0 compiler PinmemberHeapWalker27-Jul-05 5:07 
GeneralThanks PinmemberYoung-Dae, Choi19-Mar-03 8:18 
GeneralRe: Thanks PinmemberCraig Muller20-Mar-03 5:12 
GeneralStop the insanity !!! PinmemberChristian Graus18-Dec-02 16:41 
GeneralNice work PinsussGreg Arakelian18-Dec-02 16:20 
GeneralSTL already does this PinmemberMarc Clifton18-Dec-02 5:49 
GeneralRe: STL already does this PinmemberTim Smith18-Dec-02 6:04 
GeneralRe: STL already does this PinmemberChristian Graus18-Dec-02 16:33 
GeneralRe: STL already does this PinmemberCraig Muller18-Dec-02 12:16 
QuestionHow about using the STL PinmemberDaniel Andersson17-Dec-02 23:24 
AnswerRe: How about using the STL PinmemberChristian Graus18-Dec-02 0:27 
AnswerRe: How about using the STL PinmemberTim Smith18-Dec-02 6:12 
GeneralRe: How about using the STL Pinmembermollusk18-Dec-02 7:25 
GeneralRe: How about using the STL PinmemberTim Smith18-Dec-02 7:47 
GeneralRe: How about using the STL PinsussMarc Britten18-Dec-02 8:01 
GeneralRe: How about using the STL PinmemberTim Smith18-Dec-02 8:27 
GeneralRe: How about using the STL PinmemberDaniel Andersson18-Dec-02 7:40 
GeneralRe: How about using the STL PinmemberTim Smith18-Dec-02 8:05 
GeneralRe: How about using the STL Pinmembercompiler18-Dec-02 8:29 
GeneralRe: How about using the STL PinmemberDaniel Andersson18-Dec-02 8:32 
GeneralRe: How about using the STL PinmemberDaniel Andersson18-Dec-02 10:17 
GeneralRe: How about using the STL PinmemberCraig Muller18-Dec-02 10:30 
GeneralRe: How about using the STL PinsussMarc Britten18-Dec-02 9:06 
GeneralRe: How about using the STL PinmemberWilliam E. Kempf19-Dec-02 7:27 
GeneralRe: How about using the STL PinmemberWilliam E. Kempf19-Dec-02 7:40 
AnswerRe: How about using the STL PinmemberJohn Burton19-Dec-02 0:26 
GeneralRe: How about using the STL PinmemberDaniel Andersson19-Dec-02 1:09 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.

| Advertise | Privacy | Terms of Use | Mobile
Web03 | 2.8.141223.1 | Last Updated 18 Dec 2002
Article Copyright 2002 by Craig Muller
Everything else Copyright © CodeProject, 1999-2014
Layout: fixed | fluid